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。
完整程序在这里:
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。