完整程序在这里:
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 ;
为什么在消息 WM_LBUTTONDOWN
的情况下在 ChildWndProc
中:
返回 0 之前的最后一个语句是 InvalidateRect
,因为就在它之前,程序使用 SetFocus
函数向自身发送了 WM_SETFOCUS
消息,这落到 WM_KILLFOCUS
,它也有 InvalidateRect
,只有最后一个参数是 TRUE
,而不是 FALSE
。
根据我的理解,程序应该在 WM_LBUTTONDOWN
中没有 InvalidateRect
的情况下正常工作,因为它调用了 SetFocus
,然后使窗口无效,但是,当我从 WM_LBUTTONDOWN
中注释掉 InvalidateRect
时,程序不会在单击鼠标或按下按钮后正确地重新绘制窗口。
为什么会这样,为什么在 WM_LBUTTONDOWN
InvalidateRect
中最后一个参数是 FALSE
而在 WM_KILLFOCUS
中是真
?
我在 Windows XP 32 位中运行 MS Visual Studio C++ 2010 Express。
最佳答案
调用 SetFocus()
不会无条件地发送 WM_SETFOCUS
消息。如果窗口在调用之前已经获得焦点,SetFocus()
将不会执行任何操作。
换句话说,WM_SETFOCUS
消息仅在焦点更改时发送。
至于TRUE
/FALSE
参数,就是bErase
,是在重新绘制之前删除整个窗口,还是涂上已经存在的东西。在我看来,这是一种性能黑客。如果你知道你可以不删除窗口(因为你只是更新它的一小部分),你可以在这里传递 TRUE
。
我认为在 2015 年这种优化没有多大值(value)。如果您需要高性能显示更新,无论如何您都会使用 OpenGL 或 DirectX。
关于c++ - Windows API 中的 InvalidateRect,Charles Petzold checker4.c 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30258148/