[英]why not to send WM_PAINT manually
我已经读过,我不应该手动发送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;
}
}
WM_PAINT
官方文档声明您不应该在备注部分的第一句中。 说真的,这应该是没有理由的。
至于技术原因,我猜这是其中之一,取自BeginPaint
备注部分:
更新区域由InvalidateRect或InvalidateRgn函数以及系统调整,移动,创建,滚动或影响客户区域的任何其他操作后设置。
因此,如果手动发送WM_PAINT
BeginPaint
可能无法正常工作。
可能有更多原因/意外。
如果要触发立即重绘,正确的方法是:
使用InvalidateRect()
然后使用UpdateWindow()
。
使用RedrawWindow()
。
这些将触发生成新的WM_PAINT
消息。
您没有任何关于其他程序的窗口的信息来揭开您的窗口。 只有操作系统才有此信息。 因此,您并不总是知道窗口何时何地需要重新绘制。 WM_PAINT和BeginPaint提供了这个缺失的信息。
因为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
意在接收,而不是发送。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.