今天复习了下windows程序设计五第9章节,想到了个问题:
case WM_PAINT : InvalidateRect (hwnd, &rect, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ; TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DRAWITEM : case WM_COMMAND : ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ; hdc = GetDC (hwnd) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1), szBuffer, wsprintf (szBuffer, szFormat, message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"), HIWORD (wParam), LOWORD (wParam), HIWORD (lParam), LOWORD (lParam))) ; ReleaseDC (hwnd, hdc) ; ValidateRect (hwnd, &rect) ; break ;
为什么要用validaterect这个函数呢。查了查,跳到windows程序设计五第2章节,有了答案
发生下面几种事件之一时,窗口消息处理程序会接收到一个WM_PAINT消息:
- 在使用者移动窗口或显示窗口时,窗口中先前被隐藏的区域重新可见。
- 使用者改变窗口的大小(如果窗口类别样式有着CS_HREDRAW和CS_VREDRAW位旗标的设定)。
- 程序使用ScrollWindow或ScrollDC函数滚动显示区域的一部分。
- 程序使用InvalidateRect或InvalidateRgn函数刻意产生WM_PAINT消息。
OK,很明显ScrollWindow会产生一个WM_PAINT消息,那么 case WM_DRAWITEM:
case WM_COMMAND:中的TextOut不就被覆盖了!!,继续看下去
尽管窗口消息处理程序一旦接收到WM_PAINT消息之后,就准备更新整个显示区域,但它经常只需要更新一个较小的区域(最常见的是显示区域中的矩形区域)。显然,当对话框覆盖了部分显示区域时,情况即是如此。在擦除对话框之后,需要重画的只是先前被对话框遮住的矩形区域。
这个区域称为「无效区域」或「更新区域」。正是显示区域内无效区域的存在,才会让Windows将一个WM_PAINT消息放在应用程序的消息队列中。只有在显示区域的某一部分失效时,窗口才会接受WM_PAINT消息。
Windows内部为每个窗口保存一个「绘图信息结构」,这个结构包含了包围无效区域的最小矩形的坐标以及其它信息,这个矩形就叫做「无效矩形」,有时也称为「无效区域」。如果在窗口消息处理程序处理WM_PAINT消息之前显示区域中的另一个区域变为无效,则Windows计算出一个包围两个区域的新的无效区域(以及一个新的无效矩形),并将这种变化后的信息放在绘制信息结构中。Windows不会将多个WM_PAINT消息都放在消息队列中。
窗口消息处理程序可以通过呼叫InvalidateRect使显示区域内的矩形无效。如果消息队列中已经包含一个WM_PAINT消息,Windows将计算出新的无效矩形。否则,它将一个新的WM_PAINT消息放入消息队列中。在接收到WM_PAINT消息时,窗口消息处理程序可以取得无效矩形的坐标(我们马上就会看到这一点)。通过呼叫GetUpdateRect,可以在任何时候取得这些坐标。
在处理WM_PAINT消息处理期间,窗口消息处理程序在呼叫了BeginPaint之后,整个显示区域即变为有效。程序也可以通过呼叫ValidateRect函数使显示区域内的任意矩形区域变为有效。如果这呼叫具有令整个无效区域变为有效的效果,则目前队列中的任何WM_PAINT消息都将被删除。
现在很明白了,validaterect能使所有的无效区域变为有效,则消息队列中WM_PAINT消息被删除了,当然不会响应了。
所以在重载WM_ONPAINT,它默认会生成一个CPaintDC dc(this);,不要以为这只是一个初始化,就直接把它干掉,这样你的所有整个显示区域就一直无效了.