在Win32中从外部WM_PAINT调用UpdateWindow?

时间:2016-12-02 11:30:43

标签: winapi

我是Win32的初学者,在我想要的时候很难让窗口重绘自己。我怀疑它与我试图使用的东西有关 InvalidateRect(hWnd,NULL,FALSE); UpdateWindow(HWND);

在CALLBACK WndProc WM_COMMAND函数内,即在WM_PAINT之外。是这样的情况下,窗口不会立即自动更新,而是会堆积所有的重绘调用,并等到以后再过来'什么时候调用WM_PAINT?

谢谢!

2 个答案:

答案 0 :(得分:2)

  

是否会出现窗口不会立即自动更新的情况,而是会堆积所有重绘调用并等到“以后”#39;什么时候调用WM_PAINT?

不,这是的情况。

你所描述的基本上是绘制正常的方式,如果你只是简单地调用InvalidateRect会发生什么。窗口的客户区域将简单地标记为"无效"当没有消息在队列中等待处理时,将发送WM_PAINT消息。你的描述唯一出错的是绘画/重绘电话不会堆积起来#34;如果您拨打InvalidateRect 20次,则只会收到1 WM_PAINT条消息。这个"懒惰"背后的想法绘画策略是绘画是一种低优先级,但价格昂贵的操作,并且“热切地”#34;绘画会导致一堆浪费的周期 - 你可能会画一些只会在几微秒后重新粉刷的东西。

但你调用UpdateWindow的事实改变了所有这一切。此指令强制重新绘制立即。正如the documentation所说:

  

如果窗口的更新区域不为空,则UpdateWindow函数通过向窗口发送WM_PAINT消息来更新指定窗口的客户区域。该函数将WM_PAINT消息直接发送到指定窗口的窗口过程,绕过应用程序队列。如果更新区域为空,则不会发送任何消息。

InvalidateRect的初始调用将窗口的客户区标记为无效,从而创建一个非空的更新区域"对于窗口。随后对UpdateWindow的调用注意到此窗口需要重新绘制,并通过直接向窗口过程发送WM_PAINT消息,绕过正常情况强制重新发送 消息队列。

通常情况下,没有理由拨打UpdateWindow。让窗口管理器在确定是重新绘制的适当时间时处理发送绘制消息。你需要拨打UpdateWindow的唯一一次是,如果你为了回应不同的消息而做了类似昂贵计算的事情。这将阻止UI线程,阻止处理任何其他消息,包括WM_PAINT消息。出于多种原因,这是一个糟糕的事情。其中之一是它让你的窗户不被重新粉刷。另一个更严重的问题是,它会导致您的应用程序从用户的角度出现无响应,因为它会停止响应输入消息。如果您需要进行一些耗时的计算,请在后台线程上进行。

是少数几种你可能想要调用UpdateWindow的情况。我已经使用了几次,它的工作方式完全如上所述。我不知道为什么你不能让它上班;你忘了在你的问题中包含一个重现问题的代码示例。

  

当我在WM_COMMAND中放入InvalidateRect后跟UpdateWindow

时,它似乎没有这样做

这在WM_COMMAND消息处理程序中完成并不重要。你可以从任何地方做到这一点。重要的是,您首先导致窗口客户区的某些部分变为无效(使用InvalidateRect完成),然后立即强制重绘该无效区域(您完成了与UpdateWindow)。

如果我不得不推测你的问题,那就是你的重绘 立即被触发,窗口 重新粉刷,但是当你的时候看到它,另一个重绘已经发生,你的变化正在被涂上。这会在你的WM_PAINT处理逻辑中提出一个错误,但正如我所说,我们看不到它,所以这只是猜测。

答案 1 :(得分:-1)

如果其他一些新手有类似的问题,在你的InvalidateRect之前放入Sleep(2000)以及关于你当前所在位置的字符串输出可能是有用的,这样你就毫无疑问了关于什么时候发生至少那是我发现问题的方法......