mfc闪烁显示文字,mfc弹出窗口
双缓冲是图形图像处理编程过程中的一项基本技术。我们知道,如果窗体在响应WM_PAINT消息时需要复杂的图形处理,那么窗体在重绘时会因为超频刷新而闪烁。解决这一问题的有效方法是双缓冲技术。
因为表单刷新的时候,总有一个擦除原图的过程。OnEraseBkgnd用背景色填充窗体的绘制区域,然后调用新的绘制代码进行重绘,这样就造成了图像颜色的对比。当WM_PAINT的响应频繁时,这种反差就越来越明显。所以我们看到了闪烁现象。
我们自然会认为避免背景色填充是最直接的方式。但那样的话,形式就会变得一塌糊涂。因为每次绘制图像的时候都没有清除原图,造成了图像的残留,所以在重绘表单的时候,画面往往会变得凌乱。所以仅仅禁止背景重绘是不够的。我们要重画,但是需要快,所以想到了用BitBlt函数。可以支持图形块的复制,速度非常快。我们可以先在内存中画一个图,然后用这个函数把完成的图复制到前台。同时禁止背景刷新,从而消除闪烁。这就是双缓冲绘图的基本思想。
首先,按照常用的画图方法编程。即在visual类的OnDraw函数中添加绘图代码。这里我们用下面的代码画一些同心圆:【cpp】查看plaincopyprint?
CBCDoc * pDoc=get document();ASSERT _ VALID(pDoc);CPointptCenterCRectrect,ellipseRectGetClientRect(rect);ptCenter=rect。中心点();for(inti=20;我i - ){ellipseRect。SetRect(ptCenter,pt center);ellipseRect。InflateRect直立(i*10,I * 10);pDC椭圆(ellipseRect);} CBCDoc * pDoc=get document();
ASSERT _ VALID(pDoc);
CPoint ptCenter
CRect rect,ellipseRect
GetClientRect(rect);
ptCenter=rect。中心点();
for(int I=20;我我-)
ellipseRect。SetRect(ptCenter,pt center);
ellipseRect。InflateRect直立(i*10,I * 10);
pDC椭圆(ellipseRect);
运行程序,尝试改变窗口大小,可以发现闪烁现象。
在双缓冲法中,首先要做的是屏蔽背景刷新。后台刷新实际上是响应WM_ERASEBKGND消息。我们在可视类中添加对该消息的响应,我们可以看到缺少的
各省代码如下:
【cpp】查看plaincopyprint?
BOOLCMYView:OnEraseBkgnd(CDC * pDC){ return cview:OnEraseBkgnd(pDC);} BOOL cmy view:OnEraseBkgnd(CDC * pDC)
返回CView:OnEraseBkgnd(pDC);
}
调用父类的是OnEraseBkgnd函数。我们屏蔽这个调用,直接返回TRUE去做吧。
下面是内存缓冲区映射的步骤。
【cpp】查看plaincopyprint?
CBitmapbit有点。LoadBitmapA(IDB _ bitmap 1);BITMAPbm有点。get bitmap(BM);CDCmemDcmemDc。CreateCompatibleDC(pDC);CBitmap*pOldBitmap=memDc。SelectObject(位);CRectrectGetClientRect(rect);pDC-SetStretchBltMode(COLORONCOLOR);//如果不设置这种模式,画面会严重失真PDC-StretchBLT (0,0,rect.width(),rect.height(),memdc,0,0,bm.bmwidth,bm.bmheight,src copy);memDc。select object(pOldBitmap);memDc。DeleteDC();//删除DC兽王。delete object();//删除位图CBitmap位;
有点。LoadBitmapA(IDB _ bitmap 1);
位图BM;
有点。get bitmap(BM);
CDC memDc
memDc。CreateCompatibleDC(pDC);
CBitmap* pOldBitmap=memDc。SelectObject(位);
CRect rect
GetClientRect(rect);
pDC-SetStretchBltMode(COLORONCOLOR);//如果不设置这个模式,画面会严重失真。
pDC- StretchBlt(0,0,rect。Width(),rect。身高(),
memDc,0,0,bm.bmWidth,bm.bmHeight,src copy);
memDc。select object(pOldBitmap);
memDc。DeleteDC();//删除DC
bm。delete object();//删除位图
随着复杂的绘图操作进入后台,我们看到的是快速的复制操作,自然消除了闪烁现象。
问:onerasebkgnd函数中返回TRUE或FALSE有什么区别?
答:
WM_ERASEBKGND
返回值
如果应用程序删除了背景,它应该返回非零值;否则,它应该返回零。
答:true表示后台刷新已处理,false表示需要在OnPaint中处理。
问:在OnEraseBkgnd中绘制对话框背景图和在OnPaint中绘制对话框背景图有什么区别?OnEraseBkgnd和CtlColor有什么区别?
答:
OnEraseBkgnd发生在窗口大小改变等情况下。它将绘制窗口背景;而OnCtlColor发生在需要绘制窗口的控件时,它会绘制窗口的
控制。
答:
OnEraseBkgnd:当需要重画窗口背景时调用。
OnPaint: OnEraseBkgnd此时已经被调用,所以这个响应函数中对后台的操作会覆盖OnEraseBkgnd中的操作。
OncColor:为了在将要绘制窗口时(第一次)做出响应,子窗口可以通过关闭WM_CTLCOLOR来请求父窗口发送HBRUSH。