您的位置:首页 > 大数据 > 人工智能

MFC中重写OnPaint实现双缓冲绘图

2017-02-05 14:14 239 查看
在VC/MFC用CDC绘图时,频繁的刷新,屏幕会出现闪烁的现象,CPU时间占用率相当高,绘图效率极低,很容易出现程序崩溃。

在图形图象处理编程过程中,双缓冲是一种基本的技术。我们知道,如果窗体在响应WM_PAINT消息的时候要进行复杂的图形处理,那么窗体在重绘时由于过频的刷新而引起闪烁现象。解决这一问题的有效方法就是双缓冲技术。

因为窗体在刷新时,总要有一个擦除原来图象的过程OnEraseBkgnd,它利用背景色填充窗体绘图区,然后在调用新的绘图代码进行重绘,这样一擦一写造成了图象颜色的反差。当WM_PAINT的响应很频繁的时候,这种反差也就越发明显。于是我们就看到了闪烁现象。

我们会很自然的想到,避免背景色的填充是最直接的办法。但是那样的话,窗体上会变的一团糟。因为每次绘制图象的时候都没有将原来的图象清除,造成了图象的残留,于是窗体重绘时,画面往往会变的乱七八糟。所以单纯的禁止背景重绘是不够的。我们还要进行重新绘图,但要求速度很快,于是我们想到了使用BitBlt函数。它可以支持图形块的复制,速度很快。我们可以先在内存中作图,然后用此函数将做好的图复制到前台,同时禁止背景刷新,这样就消除了闪烁。

当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。基于这样的操作不是直接操作绘图区域,而是操作内存中绘图,因而从人眼看到的画面角度闪烁会缓解很多。

双缓存绘图思路

1.创建内存DC。

2.创建Bitmap用来作为画图的画布。(如果用物理DC去创建可以画彩色图,如果用内存DC是黑白的)

3.把Bitmap选入内存DC中。

4.进行画图。(可以把图片画在bitmap上,作为背景,也可以通过,MoveTo,LineTo等进行画)

5.把内存DC上的内容复制到物理DC上。

6.关闭DC连接,清理创建的内存DC和Bitmap。

注意:

1.内存DC如果和物理DC大小一致的话不用进行缩放,如果是不一致的话还要进行缩放处理。缩放与否使用BitBlt和StretchBlt方法,一个是可以缩放的。这里不展开。

2.注意关闭DC连接,否则很容易造成资源泄露。尤其是GDI资源。

以下代码基于OnPaint函数:

CPaintDC dc(this);
CRect rectClient;
CDC dcMem,dcBkgnd;
CBitmap bitmapTemp, *pOldBitmap;
GetClientRect(&rectClient);//获取窗口信息
bitmapTemp.CreateCompatibleBitmap(&dc, rectClient.Width(), rectClient.Height());//创建内存位图
dcMem.CreateCompatibelBitmap(&dc); //依附窗口DC创建兼容的DC
pOldBitmap = dcMem.SelectObject(&bitmapTemp);//将内存位图选入内存dc
//填充颜色
dcMem.FillSolidRect(rectClient,RGB(255,125,0));   //填充颜色

/*
各种绘图操作在这里进行
*/

dc.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &dcMem, 0, 0, SRCCOPY);//绘制图片到主dc
dcMem.SelectObject(pOldBitmap);//清理


BitBlt函数说明:

函数原型

BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);


参数

hdcDest:指向目标设备环境的句柄。

nXDest:指定目标矩形区域左上角的X轴逻辑坐标。

nYDest:指定目标矩形区域左上角的Y轴逻辑坐标。

nWidth:指定源和目标矩形区域的逻辑宽度。

nHeight:指定源和目标矩形区域的逻辑高度。

hdcSrc:指向源设备环境的句柄。

nXSrc:指定源矩形区域左上角的X轴逻辑坐标。

nYSrc:指定源矩形区域左上角的Y轴逻辑坐标。

dwRop:指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: