单击标题栏按钮时,全局低级鼠标钩子会导致冻结

Posted

技术标签:

【中文标题】单击标题栏按钮时,全局低级鼠标钩子会导致冻结【英文标题】:Global low level mouse hook causes freeze when clicking on title bar buttons 【发布时间】:2010-11-21 15:14:34 【问题描述】:

我正在为 IE 编写一个插件。我需要在外部单击时关闭模式对话框。

到目前为止,我已经使用 WM_NCACTIVATE 来接收这些通知,但似乎在 Windows 7 (IE8) 上我没有收到此消息(我以低完整性运行,我已经使用 spy++ 对其进行了验证;它似乎当我以高完整性运行时它确实有效 - 奇怪的东西)。

我尝试将常规鼠标挂钩用于 DeskBand UI 线程。我确实得到了所有的鼠标事件,除了来自对话框之外的事件。

所以我转而使用全局低级鼠标挂钩 (WH_MOUSE_LL)。 一切正常,但由于一些非常奇怪的原因,当我单击任何一个标题栏按钮时,我会出现 5-10 秒的冻结。

经过一些在线研究,我意识到这是一个常见问题,但我没有找到解决方案。有些人说这是性能问题,但即使我的钩子函数只调用“CallNextHook”,它仍然会发生。

关于如何修复它的任何想法或在外部点击时关闭模式对话框的替代想法?

【问题讨论】:

我认为甚至尝试覆盖标准 Windows 行为的基本位(例如模态窗口是什么的想法)是一个非常可怕的想法。我也怀疑这就是为什么你发现它很难做到。这个问题只会让我想知道为什么有人要这样做,而我能想出的答案闻起来并不好。 我同意;模态对话框的重点是模态的。如果您不想要模态对话框,请务必将对话框设为模态。 【参考方案1】:

我通过删除 WH_MOUSE_LL 解决了这个问题。 这在 Windows XP 中运行良好,但会冻结整个计算机,有时会冻结到我打开和关闭计算机。

我认为他们没有修复这个错误很荒谬。 这浪费了我很多时间。

【讨论】:

【参考方案2】:

有根据的猜测:我怀疑由于您是 IE 插件,因此您在低完整性进程中运行(这就是 IE 保护模式的工作方式)。默认情况下,低完整性进程不能将窗口消息发送到中等或高完整性进程。标题栏可能是 IE 框架的一部分,这可能是一个中等完整性的过程。在您的钩子处理中,您可能会导致发送额外的消息。例如,由于它是在您的对话框外单击,您可能会发送一条消息以关闭对话框。完整性机制会阻止消息,因为您正在跨越低完整性/中等完整性边界。五秒钟后,系统确定应用程序已无响应,从而设法使原始点击消息解开。

换句话说:从低完整性进程中设置低级钩子几乎肯定是个坏主意。

(一般来说,全局挂钩通常不是一个好主意,因为它们会为系统中的所有 UI 进程带来成本。其他程序不应该为您的程序正常运行而纳税。)

Windows 中的模态对话框具有确定/取消/关闭命令按钮。你的不应该是个例外。通过点击离开来关闭对话框与设计模型背道而驰,因此您可能难以实现这一点,即使您管理了一个脆弱的黑客,它也可能会使您的用户感到困惑和烦恼。

Windows 中的其他元素,如弹出菜单或下拉菜单,通过捕获鼠标完成单击时关闭(请参阅SetCapture),这允许菜单代码查看鼠标何时执行某些操作窗外。但是对于对话框来说这将是非常困难的,因为对话框有子控件也需要与鼠标交互。捕获鼠标会阻止孩子们获得他们需要的消息。

您需要与设计该功能的人一起重新考虑关闭点击离开的决定。任何实施它的尝试都将是一个脆弱的黑客攻击,并可能使用户感到困惑。

【讨论】:

【参考方案3】:

我在低级鼠标挂钩中也遇到过这个问题,当打开上下文菜单可能会导致系统冻结一两秒。

这是一个优先级倒置问题。尝试通过调用SetThreadPriority 来提高安装钩子的线程的优先级。

【讨论】:

反对者,请提供理由。 (例如,您认为这不是优先级倒置问题,或者您有更好的解决方案) 我没有投反对票,但我没有看到任何证据表明这是优先级倒置。在没有清楚理解潜在问题(例如,证明存在优先级倒置)的情况下混淆优先级似乎是鲁莽的。 这很难证明,但我唯一的解释。事实是:没有鼠标钩,工作正常。鼠标钩:偶尔挂起。高优先级线程中的鼠标钩子:工作正常。我每次都能重现。如果有人有更好的解释,我很乐意听到。

以上是关于单击标题栏按钮时,全局低级鼠标钩子会导致冻结的主要内容,如果未能解决你的问题,请参考以下文章

什么可能导致低级鼠标钩子错过按钮事件?

c++:使用全局鼠标钩子重新定位窗口

UIsearchBar 取消按钮导致导航栏未隐藏

为啥将文本添加到 RichEdit 窗口会冻结它?

导航栏按钮单击事件在单击其下方区域时触发。

SecureCRT快速执行