Windows API、Charles Petzold checker4.c 程序中的 InvalidateRect

InvalidateRect in Windows API, Charles Petzold checker4.c program

完整程序在这里:

http://examples.oreilly.com/9781572319950/cd_contents/Chap07/Checker4/Checker4.c

ChildWndProc中令我困惑的代码:

 case WM_LBUTTONDOWN :
      SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
      SetFocus (hwnd) ;
      InvalidateRect (hwnd, NULL, FALSE) ;
      return 0 ;

           // For focus messages, invalidate the window for repaint

 case WM_SETFOCUS:
      idFocus = GetWindowLong (hwnd, GWL_ID) ;

           // Fall through

 case WM_KILLFOCUS:
      InvalidateRect (hwnd, NULL, TRUE) ;
      return 0 ;

为什么在ChildWndProc的情况下留言WM_LBUTTONDOWN:

return 0 之前的最后一个语句是 InvalidateRect,因为就在它之前,程序使用 SetFocus 函数向自己发送 WM_SETFOCUS 消息,这会落到WM_KILLFOCUS,里面还有InvalidateRect,只是最后一个参数是TRUE,而不是FALSE.

根据我的理解,程序在 WM_LBUTTONDOWN 中没有 InvalidateRect 的情况下应该可以正常工作,因为它调用 SetFocus,然后使 window 无效,但是当我注释掉 WM_LBUTTONDOWN 中的 InvalidateRect,程序不会在单击鼠标或按下按钮后正确重绘 window。

为什么会这样,为什么在 WM_LBUTTONDOWN InvalidateRect 中最后一个参数是 FALSE 而在 WM_KILLFOCUS 中是 TRUE?

我是 运行 MS Visual Studio C++ 2010 Express Windows XP 32 位。

调用 SetFocus() 不会无条件地发送 WM_SETFOCUS 消息。如果 window 在调用之前已经有焦点,那么 SetFocus() 将不会做任何事情。

换句话说,WM_SETFOCUS 消息仅在焦点更改时发送。

至于TRUE/FALSE参数,就是bErase,是在重新绘制之前擦除整个window,还是在上面涂上什么已经在那了。在我看来,这是一种性能黑客。如果你知道你可以不删除 window(因为你只是更新它的一小部分),你可以在这里传递 TRUE

我认为在 2015 年此优化没有多大价值。如果您需要高性能显示更新,无论如何您都会使用 OpenGL 或 DirectX。