Winapi 在Win32中从WM_PAINT外部调用UpdateWindow?
我是Win32的初学者,很难让窗口在需要时重新绘制自己。我怀疑这和我想用的东西有关 无效(hWnd、NULL、FALSE); 更新窗口(hWnd) 在回调WndProc WM_命令函数内,即WM_油漆外。是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 谢谢大家! 是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 不,事实并非如此 您描述的基本上是绘画的正常工作方式,如果您只调用Winapi 在Win32中从WM_PAINT外部调用UpdateWindow?,winapi,Winapi,我是Win32的初学者,很难让窗口在需要时重新绘制自己。我怀疑这和我想用的东西有关 无效(hWnd、NULL、FALSE); 更新窗口(hWnd) 在回调WndProc WM_命令函数内,即WM_油漆外。是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 谢谢大家! 是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 不,事实并非如此 您描述的基本上是绘画的正常工作方式,如果您只调用invalidate,就会发生
invalidate
,就会发生这种情况。窗口的客户端区域将被简单地标记为“无效”,并且当队列中没有等待处理的消息时,WM_PAINT
消息将被发送。你描述的唯一错误是绘画/重画调用没有“堆积”。如果您调用WM\u PAINT
20次,您将只收到1条WM\u PAINT
消息。这种“懒惰”绘画策略背后的理念是,绘画是一种低优先级但昂贵的操作,“急切”的绘画会导致大量的浪费周期,你可能会在几微秒后重新绘制一些东西
但是,您调用UpdateWindow
的事实改变了这一切。此指令强制立即重新绘制。正如上面所说:
如果窗口的更新区域不是空的,则UpdateWindow函数通过向窗口发送WM_PAINT
消息来更新指定窗口的客户端区域。该函数绕过应用程序队列,直接向指定窗口的窗口过程发送WM_PAINT
消息。如果更新区域为空,则不发送任何消息
对invalidate
的初始调用将窗口的客户端区域标记为无效,从而为窗口创建一个非空的“更新区域”。对UpdateWindow
的后续调用注意到此窗口需要重新绘制,并通过直接发送窗口过程WM_PAINT
消息,绕过正常的消息队列,强制立即进行重新绘制
通常,没有理由调用UpdateWindow
。当窗口管理器确定是重新绘制的适当时间时,让它处理发送绘制消息。您唯一需要调用UpdateWindow
的时间是,如果您正在执行类似昂贵的计算之类的操作,以响应不同的消息。这将阻止UI线程,阻止处理任何其他消息,包括WM_PAINT
消息。这是一件糟糕的事情,原因很多。其中之一是它可以防止你的窗户被重新粉刷。另一个更严重的问题是,从用户的角度来看,它会导致应用程序变得无响应,因为它停止响应输入消息。如果需要进行一些耗时的计算,请在后台线程上进行
但在少数情况下,您可能需要调用UpdateWindow
。我已经用过几次了,它的工作原理与上面描述的完全一样。我不知道为什么你很难让它工作;您忘记在问题中包含重现问题的代码示例
当我在WM_命令中放入invalidate命令,后跟UpdateWindow时,它似乎没有这样做
在WM_命令中执行此操作绝对没有关系。你可以在任何地方做。重要的是,您首先会导致窗口客户端区域的某些部分无效(您可以通过invalidatebuild
完成),然后强制立即重新绘制该无效区域(您可以通过UpdateWindow
完成)
如果我不得不推测你的问题,那就是你的重新绘制会立即被触发,窗口会被重新绘制,但是当你看到它的时候,另一个重新绘制已经发生了,你的更改正在被重新绘制。这可能表明您的WM_PAINT
处理逻辑中存在错误,但正如我所说的,我们看不到它,因此这只是一个猜测。如果其他新手也有类似问题,那么在使用字符串输出您当前所在的位置之前进入睡眠(2000)可能会很有用,这样一来,你就不会怀疑什么时候会发生什么。至少我是这样发现我的问题的……你现在的措辞只会吸引那些知道绘画常规和顺序的回答者。如果你想让其他人尝试一下,你可能想阅读并提供一个,我认为这在一行或10行代码内是可能的。如果你阅读绘画是如何工作的,你就会理解为什么是这样,为什么在消息队列为空时会出现绘画,而WM_PAINT消息是针对任何无效区域合成的。@DavidHeffernan:“[…]将WM_PAINT消息直接发送到指定窗口的窗口过程,绕过应用程序队列。”@IInspectable我知道。这是我的想法,但当我在WM_命令中放入invalidateBu立,然后再加上UpdateWindow时,它似乎没有这样做。无论如何,谢谢你的回复!好的,谢谢你的教学回答,我现在就到了;就像你说的,重新粉刷马上就被触发了。我没有发布源代码,因为它很长,我认为它是一些基本的东西,确实如此。这里关于堆栈溢出的基本规则是发布一个演示您遇到的问题的。当然,g需要付出努力