不要在WM_ACTIVATE里调用可以触发活动转移的函数

不要在WM_ACTIVATE里调用可以触发活动转移的函数

一、来源

    WM_ACTIVATE的问题6月19号发现了,当时发现窗口会收到两次WM_ACTIVATE消息,很是奇怪,但找不到入手点,就没有深入追究。前几天同事发现有个按钮点击了没反应,是因为WM_LBUTTONDOW消息丢失,导致按钮事件没有生成,这才发现是WM_ACTIVATE有问题,总算找到原因了。但这是为什么呢?这就需要详细分析了。
二、详细分析

    避免在WM_ACTIVATE里调用可能触发活动转移的函数(如:ShowWindow( SW_HIDE ));

    有一个窗口A显示着,点击了跟窗口A使用同一个消息线程的B窗口,让A窗口因为失去活动而隐藏,如果在A窗口的WM_ACTIVATE失活动消息的响应里,调用本窗口ShowWindow(SW_HIDE),那么可能导致B窗口没有收到WM_LBUTTONDOWN。所以,千万不要在WM_ACTIVATE里调用ShowWindow(SW_HIDE)。而应该PostMessage,把ShowWindow放在其它地方做。

    这种情况是在用窗口模拟实现菜单,这个菜单有开关效果,还有失活动隐藏效果的时候出现的。

    假设菜单窗口为MenuWnd,跟菜单窗口有同一个UI线程的主窗口MainWnd

    错误的过程如下:

    菜单窗口MenuWnd在显示的情况下,点击主窗口MainWnd的客户区。这个时候,菜单窗口收到WM_ACTIVATE,WM_ACTIVATE消息里做了菜单窗口的隐藏ShowWIndow( SW_HIDE ),而这个时刻,活动还没有设置到主窗口上(因为菜单窗口跟主窗口使用同一个消息队列,菜单窗口的处理阻塞了(参考MSDN中的WM_ACTIVATE)),此时活动的还是菜单窗口,它隐藏后又触发了WM_ACTIVATE,于是菜单窗口第二次收到WM_ACTIVATE,这时候的ShowWindow( SW_HIDE )不会执行(因为已经隐藏了),所以不会出现死循环,接着主窗口处理WM_ACTIVATE获得活动,ShowWIndow( SW_HIDE )执行完毕返回,继续执行第一次WM_ACTIVATE的处理,然后返回。

    消息流是这样的:

    菜单窗口失活动WM_ACTIVATE-->菜单窗口隐藏-->菜单窗口失活动WM_ACTIVATE-->主窗口获活动WM_ACTIVATE-->菜单窗口失活动响应返回-->主窗口收到WM_LBUTTONUP.

    本来以为菜单窗口失活动响应返回后还会有一次主窗口获取活动消息,一次菜单窗口失活动响应返回,因为A窗口失活动消息、A窗口失活动返回、B窗口获取活动这三个是配对存在的,但用spy++抓取,没发现。我只关注主窗口:主窗口的WM_ACTIVATE获活动消息丢失了,而且主窗口的WM_LBUTTONDOWN也丢失了。

    如果点击的不是主窗口区域,而是在不同UI线程里的其他进程窗口,那么菜单窗口ShowWindow(SW_HIDE)不会再触发WM_ACTIVATE,那就不会有问题

可以猜测,为什么系统不再给主窗口发出WM_ACTIVATE呢?也许是因为发现已经发过一次比这次WM_ACTIVATE更新的消息了,那么这个消息就被丢弃,连带它的WM_LBUTTONDOWN也被丢弃。猜测:当发生WM_ACTIVATE重新设置时,会导致还没派发的鼠标点击消息丢失。

附图:spy++抓取,在错误的代码里,点击主窗口的一个按钮,活动如何从菜单窗口转到主窗口(按钮窗口),主窗口(按钮窗口)没收到WM_LBUTTONDOW消息

 

另外,通过syp++查看测试小程序,系统发送消息的顺序,可能是这样子的(点击的是非客户区):WM_NCLBUTTONDOWN --> WM_ACTIVATE --> WM_LBUTTONUP这样的顺序产生的,又或者是这样子(点击的是客户区):WM_ACTIVATE --> WM_LBUTTONDOWN --> WM_LBUTTONUP。WM_NCLBUTTONDOWN消息早于WM_ACTIVATE。

附上简单的验证代码

http://files.cnblogs.com/cswuyg/%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%EF%BC%8CActivateTest.rar

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解压密码:123 安装说明:https://blog.csdn.net/hongfu951/article/details/118517942 嵌入2021概述 Altair Activate / Compose / Embed 2021是SolidThinking强大而全面的工程套件,帮助设计师和系统工程师控制和模拟产品设计。它是一个多学科的设计和工程应用,使用基于模型的开发技术,通过独特地结合数学,基于信号,物理和3D建模技术,以推动创新的概念研究,控制设计,系统性能优化,控制器实现和测试。它是一个高效和可靠的应用程序,具有各种功能和许多方便的工具,为用户节省时间和金钱。它使产品创造者、系统仿真和控制工程师能够通过优化基于模型的开发来建模、模拟和优化多学科系统,确保所有的设计需求都被成功满足,同时还能在设计过程的早期识别系统级别的问题。该程序为计算、编辑和可视化数据以及编写脚本和故障排除脚本提供了一个用户友好的环境,这对于自动化过程和加速重复计算非常有用。您也可以下载Altair (solidThinking) Inspire Suite 2021免费下载。 2021是一个功能打包的实用程序,为工程师和结构分析师提供先进的开发模型,概念设计和生产模拟,以帮助他们实现其期望的质量。它还为基于模型的嵌入式系统开发提供了一个可视化环境,该环境可以自动地从模型的框图中生成代码,并将它们转移到控制硬件中。该程序结合了Altair Activate, Compose和Embed的力量,每个都有自己独特的目的和功能,如Altair Activate为工程师和用户提供了所有的工具,以快速地建模和模拟他们的产品。类似地,Altair Compose允许用户为复杂的等式执行不同类型的复杂而乏味的计算,并执行操作、调试脚本、编程和提供可视化数据。而Altair Embed,一个强大而先进的工具,使用户能够从框图模型等开发嵌入式系统。它将自动转换您的框图和状态图到微控制器单元(MCU)硬件就绪代码。您也可以下载Altair EDEM Professional 2021免费下载。
解压密码:123 安装说明:https://blog.csdn.net/hongfu951/article/details/118517942 嵌入2021概述 Altair Activate / Compose / Embed 2021是SolidThinking强大而全面的工程套件,帮助设计师和系统工程师控制和模拟产品设计。它是一个多学科的设计和工程应用,使用基于模型的开发技术,通过独特地结合数学,基于信号,物理和3D建模技术,以推动创新的概念研究,控制设计,系统性能优化,控制器实现和测试。它是一个高效和可靠的应用程序,具有各种功能和许多方便的工具,为用户节省时间和金钱。它使产品创造者、系统仿真和控制工程师能够通过优化基于模型的开发来建模、模拟和优化多学科系统,确保所有的设计需求都被成功满足,同时还能在设计过程的早期识别系统级别的问题。该程序为计算、编辑和可视化数据以及编写脚本和故障排除脚本提供了一个用户友好的环境,这对于自动化过程和加速重复计算非常有用。您也可以下载Altair (solidThinking) Inspire Suite 2021免费下载。 2021是一个功能打包的实用程序,为工程师和结构分析师提供先进的开发模型,概念设计和生产模拟,以帮助他们实现其期望的质量。它还为基于模型的嵌入式系统开发提供了一个可视化环境,该环境可以自动地从模型的框图中生成代码,并将它们转移到控制硬件中。该程序结合了Altair Activate, Compose和Embed的力量,每个都有自己独特的目的和功能,如Altair Activate为工程师和用户提供了所有的工具,以快速地建模和模拟他们的产品。类似地,Altair Compose允许用户为复杂的等式执行不同类型的复杂而乏味的计算,并执行操作、调试脚本、编程和提供可视化数据。而Altair Embed,一个强大而先进的工具,使用户能够从框图模型等开发嵌入式系统。它将自动转换您的框图和状态图到微控制器单元(MCU)硬件就绪代码。您也可以下载Altair EDEM Professional 2021免费下载。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值