Winapi 在Win32中从WM_PAINT外部调用UpdateWindow?

Winapi 在Win32中从WM_PAINT外部调用UpdateWindow?,winapi,Winapi,我是Win32的初学者,很难让窗口在需要时重新绘制自己。我怀疑这和我想用的东西有关 无效(hWnd、NULL、FALSE); 更新窗口(hWnd) 在回调WndProc WM_命令函数内,即WM_油漆外。是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 谢谢大家! 是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢 不,事实并非如此 您描述的基本上是绘画的正常工作方式,如果您只调用invalidate,就会发生

我是Win32的初学者,很难让窗口在需要时重新绘制自己。我怀疑这和我想用的东西有关 无效(hWnd、NULL、FALSE); 更新窗口(hWnd)

在回调WndProc WM_命令函数内,即WM_油漆外。是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢

谢谢大家!

是否窗口不会立即更新自身,而是将所有重画调用堆积起来,等待调用WM_PAINT时的“稍后”呢

不,事实并非如此

您描述的基本上是绘画的正常工作方式,如果您只调用
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需要付出努力