完整程序在这里:
http://examples.oreilly.com/9781572319950/cd_contents/Chap07/Checker4/Checker4.cChildWndProc
中的代码使我感到困惑:
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
:返回0之前的最后一条语句是
InvalidateRect
,因为在此之前,程序使用WM_SETFOCUS
函数向其自身发送SetFocus
消息,该消息属于WM_KILLFOCUS
,后者也具有InvalidateRect
,只有最后一个参数是TRUE
,而不是FALSE
。据我了解,该程序应在
InvalidateRect
中没有WM_LBUTTONDOWN
的情况下正常运行,因为它会调用SetFocus
,这将使该窗口无效,但是当我从InvalidateRect
中注释掉WM_LBUTTONDOWN
时,该程序不会单击鼠标或按钮后,请正确重新粉刷窗口。为什么这样?为什么在
WM_LBUTTONDOWN
InvalidateRect
中最后一个参数是FALSE
,在WM_KILLFOCUS
中它是TRUE
?我正在Windows XP 32bit中运行MS Visual Studio C ++ 2010 Express。
最佳答案
调用SetFocus()
不会无条件发送WM_SETFOCUS
消息。如果在调用之前窗口已经具有焦点,则SetFocus()
将不执行任何操作。
换句话说,仅在焦点更改时发送WM_SETFOCUS
消息。
至于TRUE
/ FALSE
参数,就是bErase
,是在重新绘制之前先擦除整个窗口,还是在现有的窗口上绘制。在我的书中,这是一个性能黑客。如果您知道可以不删除窗口而逃脱(因为您只更新窗口的一小部分),则可以在此处传递TRUE
。
我认为这种优化在2015年没有太大价值。如果需要高性能的显示更新,则无论如何都要使用OpenGL或DirectX。