全局低级鼠标钩子导致在点击标题栏按钮时出现冻结

3

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

到目前为止,我已经使用WM_NCACTIVATE接收这些通知,但似乎在Windows 7(IE8)上我没有收到这个消息(我正在低完整性下运行,并使用spy++进行验证;当我以高完整性运行时它似乎有效 - 奇怪的事情)。

我尝试使用DeskBand UI线程的常规鼠标钩子。我确实获得了所有鼠标事件,除了来自对话框外部的事件。

所以我转而使用全局低级别鼠标钩子(WH_MOUSE_LL)。一切都很顺利,但出现了一个非常奇怪的问题:当我单击任何一个标题栏按钮时,会出现5-10秒的冻结。

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

有没有什么想法可以解决这个问题或者有没有其他的想法来在外部点击时关闭模态对话框?


4
我认为这是一个非常糟糕的想法,甚至试图覆盖基本的标准Windows行为,例如模态窗口的概念。我还怀疑这就是你发现很难做到的原因。这个问题让我想知道为什么有人想要这样做,而我能想到的答案并不怎么好闻。 - Andrew Barber
我同意,模态对话框的整个重点就在于是模态的。如果您不想要一个模态对话框,请确保将其设为非模态。 - i_am_jorf
3个回答

1

我通过移除 WH_MOUSE_LL 来解决了这个问题。 在 Windows XP 中,这很好用,但会导致整个计算机死机,有时需要重启计算机。

我认为他们没有修复这个漏洞是荒谬的。 这浪费了我很多时间。


0

我在低级别鼠标钩子中也遇到了这个问题,当打开上下文菜单时,系统会冻结一两秒钟。

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


请给出理由再进行点踩。例如,您认为这不是优先级倒置问题,或者您有更好的解决方案。 - Fozi
我没有投反对票,但是我没有看到任何证据表明这是一个优先级反转的问题。在没有清楚理解底层问题(例如,证明存在优先级反转)的情况下擅自处理优先级似乎是鲁莽的。 - Adrian McCarthy
1
很难证明,但这是我的唯一解释。事实是:没有鼠标钩子,程序运行良好。鼠标钩子:偶尔会挂起。在高优先级线程中的鼠标钩子:正常工作。我每次都能重现这个问题。如果有更好的解释,我很乐意听取。 - Fozi

0
合理猜测:我猜测你是一个IE插件,正在低完整性进程中运行(这是IE保护模式的工作原理)。低完整性进程默认情况下不能向中等或高完整性进程发送窗口消息。标题栏可能是IE框架的一部分,该框架可能是中等完整性进程。在您的钩子处理中,也许您会导致额外的消息被发送。例如,由于它是对话框外的单击,您可能会发送一条消息来关闭对话框。完整性机制会阻止该消息,因为您正在跨越低完整性/中等完整性边界。五秒钟后,系统确定应用程序已变得无响应,这使得原始单击消息得以解除。

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

(总的来说,全局钩子通常都不是一个好主意,因为它们会对系统中的所有UI进程产生影响。其他程序不应该为了您的程序能够正确运行而付出代价。)

Windows 中的模态对话框通常都有确认/取消/关闭的命令按钮。你的应用程序不应该例外。通过点击空白处来关闭对话框是违反设计模式的,所以你很可能会遇到麻烦,即使你成功实现了一个脆弱的解决方案,也很可能会让用户感到困惑和烦恼。
在 Windows 中,其他元素比如弹出或下拉菜单,可以通过捕获鼠标(参见 SetCapture)来实现点击空白处关闭窗口,这样就可以让菜单代码看到鼠标在窗口外进行了操作。但是对于一个包含子控件的对话框来说,这将非常困难,因为子控件也需要与鼠标交互。捕获鼠标将阻止子控件接收它们需要的消息。
你需要重新考虑与设计该功能的人员商讨是否需要在点击空白处关闭对话框。任何试图实现该功能的尝试都将是脆弱的 hack 并且可能会让用户感到困惑。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接