我已经读过,我不应该手动发送WM_PAINT
,而是应该调用InvalidateRect
,但是没有找到任何关于原因的信息。那为什么不呢?
更新适用于InvalidateRect
,但不适用于SendMessage(WM_PAINT)
LRESULT CALLBACK window_proc(HWND wnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
switch (msg)
{
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(wnd, &ps);
Polyline(..);
EndPaint(wnd, &ps);
return 0;
case WM_USER:
// SendMessage(wnd, WM_PAINT, NULL, NULL);
// InvalidateRect(wnd, NULL, FALSE);
return 0;
}
}
答案 0 :(得分:5)
WM_PAINT
的官方文档声明您不应该在备注部分的第一句话中。说真的,这应该是没有理由的原因。
至于技术原因,我想这是其中之一,取自BeginPaint
备注部分:
更新区域由 InvalidateRect 或 InvalidateRgn 功能以及系统调整,移动,创建,滚动或影响客户区的任何其他操作后设置
如果您手动发送BeginPaint
,WM_PAINT
可能无法正常工作。
可能有更多原因/意外。
答案 1 :(得分:3)
如果您想触发立即重绘,正确的方法是:
使用InvalidateRect()
后跟UpdateWindow()
。
使用RedrawWindow()
。
这些将触发生成新的WM_PAINT
消息。
答案 2 :(得分:2)
您没有任何关于其他程序窗口的信息,无法揭开您的窗口。只有操作系统才有此信息。因此,您无需知道窗口何时何地需要重新绘制。 WM_PAINT和BeginPaint提供了这个缺失的信息。
答案 3 :(得分:1)
因为WM_PAINT
不是真实的信息。
可以想象每个窗口都有一个存储“无效区域”的结构,也就是说,“屏幕上窗口的这一部分不再是最新的,需要重新绘制”。
窗口管理器本身(窗口已调整大小,未覆盖等)或通过调用InvalidateRect
,ValidateRect
,EndPaint
等修改了无效区域。
现在,这是GetMessage
如何处理这个问题的粗略模型:
... GetMessage(MSG* msg, ...)
{
while(true) {
if(ThereIsAnyMessageInTheMessageQueue()) {
*msg = GetFirstMessageOfTheMessageQueue();
return ...;
} else if(TheInvalidRegionIsNotEmpty()) {
*msg = CreateWMPaintMessage();
return ...;
} else {
WaitUntilSomethingHappend();
}
}
}
tl; dr:WM_PAINT
意味着收到,而不是发送。