Windows在一些事件发生时,会将窗体的client部分至为无效,并发送WM_PAINT消息,比如:
1 A previously hidden area of the window is brought into view when a user moves a window or uncovers a window.
2 The user resizes the window (if the window class style has the CS_HREDRAW and CW_VREDRAW bits set).
3 The program uses the ScrollWindow or ScrollDC function to scroll part of its client area.
4 The program uses the InvalidateRect or InvalidateRgn function to explicitly generate a WM_PAINT message.
这些消息可能直接发送到window procedure,也可能放入消息队列。
Windows对于WM_PAINT消息必须处理,但如果在Windows处理一个WM_PAINT消息时,又有新的WM_PAINT消息进入消息队列,
也就是又有新的client area变为无效区域,那么,Windows会把新旧无效区域合并成一个新的无效区域。
有时候,Windows不做合并,在把新的消息放入消息队列后就等待window procedure自行处理了。
Windows在上述1-3的情况下,将自动使用wndclass.hbrBackground属性指定的背景色来将无效区域擦“干净“,并发送WM_PAINT消息。
在这之后,如果window procedure对于WM_PAINT消息的处理使用了BeginPaint (hwnd, &ps) ;来将整个client area(不只无效区域)重新变为有效,那么由于Windows已经擦过无效区域,因此,BeginPaint的&ps指向的PAINTSTRUCT结构的fErase参数将为FALSE。
如果使用第4种方法由用户程序指定无效区域时,使用了InvalidateRect (hwnd, NULL, TRUE/FALSE)。
则无效区域是否擦除将由InvalidateRect的最后一个参数指定:
TRUE->BeginPaint会擦出无效区域的内容;BeginPaint调用后PAINTSTRUCT结构的fErase参数将为FALSE;
FALSE->BeginPaint会保留无效区域的内容;BeginPaint调用后PAINTSTRUCT结构的fErase参数将为TRUE。
另一个重要问题是:clipping region。这个概念是指可以描画或输出文字的区域。
这个与invalid region不同。
当调用hdc = BeginPaint (hwnd, &ps) ; 获得Device Context的指针时clipping region就是invalid region;
当调用hdc = GetDC (hwnd) ; 获得Device Context的指针时, clipping region是整个client area。即可以在整个用户区任意描画。
device context可以设置mapping mode,即logic coordinates如何转换到physical coordinates;
在不同的mapping mode下,GetTextMetrics 返回的字体大小的数值和单位会有变化,如1pixel,2mm,
虽然用不同 mapping mode单位下表示的字体大小的数值不同,字体的实际大小是确定的,
字体实际大小只取决于显示器分辩率(如1024X768)和所选择的Font(如System Font)。