言归正传!在研究了站长的文章《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如果为非零值则擦除背景,否则不擦除背景,就是这个字段起了最大的作用。