转自:http://hi.baidu.com/noscan/blog/item/ff8634c2d63bfb1f0ef47758.html
是的,每个窗口要有一个PAINTSTRUCT结构来记录一些绘制信息,PAINTSTRUCT结构保存了窗口绘制客户区的一些信息,例如,绘制客户区时是否要清除背景色,要更新的客户区的矩形区域的大小等等,MFC里的CPaintDC与之对应;
除了BeginPaint可以得到客户区设备描述表的句柄外,GetDC也一样可以得到,MFC里的CClientDC与之对应。
它们之间的区别是前者只能用在WM_PAINT消息处理函数里用来重绘客户区。
后者虽然也表示客户区的设备描述表,但是不能更新无效区(比方说客户区被一个弹出对话框覆盖)。
绘图信息结构 前面提到过,Windows为每个窗口保存一个「绘图信息结构」,这就是PAINTSTRUCT,定义如下: typedef struct tagPAINTSTRUCT { HDC hdc ; BOOL fErase ; RECT rcPaint ; BOOL fRestore ; BOOL fIncUpdate ; BYTE rgbReserved[32] ; } PAINTSTRUCT ; 在程序呼叫BeginPaint时,Windows会适当填入该结构的各个字段值。使用者程序只使用前三个字段,其它字段由Windows内部使用。hdc字段是设备内容句柄。在旧版本的Windows中,BeginPaint的传回值也曾是这个设备内容句柄。在大多数情况下, fErase被标志为FALSE(0),这意味着Windows已经擦除了无效矩形的背景。这最早在BeginPaint函数中发生(如果要在窗口消息处理程序中自己定义一些背景擦除行为,可以自行处理WM_ERASEBKGND消息)。Windows使用WNDCLASS结构的hbrBackground字段指定的画刷来擦除背景,这个WNDCLASS结构是程序在WinMain初始化期间登录窗口类别时使用的。许多Windows程序使用白色画刷。以下叙述设定窗口类别结构字段值: wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 不过,如果程序通过呼叫Windows函数InvalidateRect使显示区域中的矩形失效,则该函数的最后一个参数会指定是否擦除背景。如果这个参数为FALSE(即0),则Windows将不会擦除背景,并且在呼叫完BeginPaint后PAINTSTRUCT结构的fErase字段将为TRUE(非零)。 PAINTSTRUCT结构的rcPaint字段是RECT型态的结构。您已经在第三章中看到,RECT结构定义了一个矩形,其四个字段为left、top、right和bottom。PAINTSTRUCT结构的rcPaint字段定义了无效矩形的边界,如图4-1所示。这些值均以图素为单位,并相对于显示区域的左上角。无效矩形是应该重画的区域。
PAINTSTRUCT中的rcPaint矩形不仅是无效矩形,它还是一个「剪取」矩形。这意味着Windows将绘图操作限制在剪取矩形内(更确切地说,如果无效矩形区域不为矩形,则Windows将绘图操作限制在这个区域内)。 在处理WM_PAINT消息时,为了在更新的矩形外绘图,可以使用如下呼叫: InvalidateRect (hwnd, NULL, TRUE) ; 该呼叫在BeginPaint呼叫之前进行,它使整个显示区域变为无效,并擦除背景。但是,如果最后一个参数等于FALSE,则不擦除背景,原有的东西将保留在原处。 通常这是Windows程序在无论何时收到WM_PAINT消息而不考虑rcPaint结构的情况下简单地重画整个显示区域最方便的方法。例如,如果在显示区域的显示输出中包括了一个圆,但是只有圆的一部分落到了无效矩形中,它就使仅绘制圆的无效部分变得没有意义。这需要画整个圆。在您使用从BeginPaint传回的设备内容句柄时,Windows不会绘制rcPaint矩形外的任何部分。 在第三章的HELLOWIN程序中,我们并不关心处理WM_PAINT消息时的无效矩形。如果文字显示区域恰巧在无效矩形内,则由DrawText恢复之。否则,在处理DrawText呼叫的某个时刻,Windows会确定它无须向显示器上输出。不过,这一决定需要时间。关心程序性能和速度的程序写作者希望在处理WM_PAINT期间使用无效矩形范围,以避免不必要的GDI呼叫。如果绘制时需要存取例如位图这样的磁盘文件,则这就显得尤其重要。 |