当前位置:C++技术网 > 资讯 > BeginPaint,EndPaint与GetDC函数的区别

BeginPaint,EndPaint与GetDC函数的区别

更新时间:2016-01-03 16:27:31浏览次数:1+次

首先说下为什么写这篇文章。之前一个学姐给我看了一个图片查看器,我觉得不错,就想自己做着试试。其实,我很早就想做这样的小软件了,既然有了大概的模型,我就正好试试。对于那个图片查看器,其实就是BitBlt与stretchBlt函数的应用。可是,我遇到了一个问题,就会如何擦出之前显示的图片。举个例子:我正常显示了一张图片,现在我点击“缩小”按钮,将图片缩小。很简单,就是利用stretchBlt函数就行,可是,你会发现,之前“正常”按钮显示出来的图片依旧在,也就是说,现在窗口的客户区上有两个图片,这明显不符合软件设计要求。然后,我就一直研究,我琢磨着应该是需要重绘,但是装逼失败。这个问题缠我有十几天了,之间尽管有期末考试,期末复习,我依旧正常研究,这下估计考试得挂。
言归正传!在研究了站长的文章《InvalidateRect无效矩形的图文分析和在字符串中移动光标》后尝试着做了一下,发现装逼成功!对于窗口无效的知识,请看《判断窗口有没有无效矩形即判断窗口是否需要刷新以及无效矩形有多大》、《无效矩形无效区域到底是什么东西?
三篇文章都是站长写的。描述的很详细!
下面是重点。BeginPaint() 和EndPaint() 可以删除消息队列中的WM_PAINT消息,并使无效区域有效。 
GetDC()和ReleaseDC()并不删除也不能使无效区域有效,因此当程序跳出 WM_PAINT 时 ,无效区域仍然存在。系统就回不断发送WM_PAINT消息,于是程序不断处理WM_PAINT消息。

BeginPaint、EndPaint会告诉GDI内部,这个窗口需要重画的地方已经重画了,这样WM_PAINT处理完返回给系统后,系统不会再重发WM_PAINT,而GetDC没有告诉系统这个窗口需要重画的地方已经画过,在你把程序返回给系统后,系统一直以为通知你的重画命令你还没有乖乖的执行或者执行出错,所以在消息空闲时,它还会不断地发WM_PAINT催促你画,导致程序卡死。

那么为什么BeginPaint函数就有这个功能?我们看看他的构造函数:

BeginPaint(
    __in HWND hWnd,
    __out LPPAINTSTRUCT lpPaint);
lpPaint是一个结构体。
typedef struct tagPAINTSTRUCT {
 HDC hdc;
 BOOL fErase;
 RECT rcPaint;
 BOOL fRestore;
 BOOL fIncUpdate;
 BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;
hdc是获取设备句柄。
fErase是否擦新背景。
rcPaint是显示的窗口大小。
fRestore、fIncUpdate、rgbReserved是保留使用的参数。
fErase如果为非零值则擦除背景,否则不擦除背景,就是这个字段起了最大的作用。