0

我有一个第 3 方开源控件(实际上哪个并不重要,但它的 CefSharp 的 Chromium Web 浏览器 [v 43])。

最初,如果在控件内部单击时打开了表单菜单,则存在一个问题,该菜单不会自行关闭(好像控件正在吞噬单击事件)。

为了避免这种情况,示例应用程序建议截取窗体和控件之间的WM_MOUSEACTIVATE消息,并通过将WM_NCLBUTTONDOWN发布回包含窗体上的元素(在我的例子中是面板栏)来做出反应。这解决了这个问题。

然而,它创造了另一个。现在,一旦您在控件内部(触摸屏)至少触摸 3 次,您就不能再触摸该控件之外的元素。您必须用鼠标单击 [外部元素] 才能恢复再次响应触摸事件所需的焦点水平。

我发现如果我还截获WM_SETCURSOR消息(到控件)并阻塞泵 5 毫秒(Thread.Sleep()),那么问题就会神奇地消失。

我很想知道发生了什么。我介于这是一个线程/上下文问题的理论之间,或者延迟WM_SETCURSOR消息是允许表单中的相邻消息首先处理(这不可能是真的,因为它们共享同一个线程)。

因此,我进行了测试(没有 5ms 的睡眠)并实时记录了控件和表单接收到的所有消息。在测试过程中,我用鼠标单击了我的面板栏(浏览器控件上方),然后触摸(长和短)控件内部的各个区域,然后再次触摸该栏(被忽略)。

在此处输入图像描述

以下是消息:

10/13/2015 02:37:00.295 PM  Form: WM_PARENTNOTIFY       1. [Click bar]
10/13/2015 02:37:00.295 PM  Form: WM_MOUSEACTIVATE

10/13/2015 02:37:05.458 PM  Chromium: WM_NCHITTEST      2. [Touch 1 -long]
10/13/2015 02:37:05.458 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:05.458 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:05.458 PM  Form: 587
10/13/2015 02:37:05.458 PM  Chromium: 587
10/13/2015 02:37:05.458 PM  Chromium: WM_MOUSEACTIVATE
10/13/2015 02:37:05.458 PM  Chromium: 585
10/13/2015 02:37:05.458 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:05.458 PM  Chromium: 716
10/13/2015 02:37:05.458 PM  Chromium: WM_TOUCH  (x23)
10/13/2015 02:37:05.458 PM  Chromium: 582
10/13/2015 02:37:05.458 PM  Chromium: 581       (x22)
10/13/2015 02:37:05.674 PM  Chromium: 583
10/13/2015 02:37:05.674 PM  Chromium: 586
10/13/2015 02:37:05.674 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:05.674 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:05.674 PM  Chromium: WM_MOUSEMOVE
10/13/2015 02:37:05.674 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:05.674 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:05.674 PM  Chromium: WM_MOUSEACTIVATE
10/13/2015 02:37:05.674 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:05.674 PM  Chromium: WM_LBUTTONDOWN
10/13/2015 02:37:05.674 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:05.674 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:05.674 PM  Chromium: WM_LBUTTONUP

10/13/2015 02:37:10.509 PM  Chromium: WM_NCHITTEST      3. [Touch 2 -long]
10/13/2015 02:37:10.509 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:10.509 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:10.509 PM  Form: 587
10/13/2015 02:37:10.509 PM  Chromium: 587
10/13/2015 02:37:10.509 PM  Chromium: WM_MOUSEACTIVATE
10/13/2015 02:37:10.509 PM  Chromium: 585
10/13/2015 02:37:10.509 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:10.509 PM  Chromium: 716
10/13/2015 02:37:10.509 PM  Chromium: WM_TOUCH  (x27)
10/13/2015 02:37:10.509 PM  Chromium: 582
10/13/2015 02:37:10.509 PM  Chromium: 581       (x25)
10/13/2015 02:37:10.755 PM  Chromium: 583
10/13/2015 02:37:10.755 PM  Chromium: 586
10/13/2015 02:37:10.755 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:10.755 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:10.755 PM  Chromium: WM_MOUSEMOVE
10/13/2015 02:37:10.755 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:10.755 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:10.755 PM  Chromium: WM_MOUSEACTIVATE
10/13/2015 02:37:10.755 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:10.755 PM  Chromium: WM_LBUTTONDOWN
10/13/2015 02:37:10.755 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:10.755 PM  Chromium: WM_SETCURSOR
10/13/2015 02:37:10.755 PM  Chromium: WM_LBUTTONUP

10/13/2015 02:37:25.525 PM  Chromium: WM_NCHITTEST      4. [Touch 3 -short]
10/13/2015 02:37:25.525 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:25.525 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:25.525 PM  Form: 587
10/13/2015 02:37:25.525 PM  Chromium: 587
10/13/2015 02:37:25.525 PM  Chromium: 585
10/13/2015 02:37:25.525 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:25.525 PM  Chromium: 716
10/13/2015 02:37:25.525 PM  Chromium: WM_TOUCH  (x7)
10/13/2015 02:37:25.525 PM  Chromium: 582
10/13/2015 02:37:25.525 PM  Chromium: 581       (x5)
10/13/2015 02:37:25.586 PM  Chromium: 583
10/13/2015 02:37:25.586 PM  Chromium: 586

10/13/2015 02:37:30.440 PM  Chromium: WM_NCHITTEST      5. [Touch 4 -short]
10/13/2015 02:37:30.440 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:30.440 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:30.440 PM  Form: 587
10/13/2015 02:37:30.440 PM  Chromium: 587
10/13/2015 02:37:30.440 PM  Chromium: 585
10/13/2015 02:37:30.440 PM  Chromium: WM_NCHITTEST
10/13/2015 02:37:30.440 PM  Chromium: 716
10/13/2015 02:37:30.440 PM  Chromium: WM_TOUCH  (x10)
10/13/2015 02:37:30.440 PM  Chromium: 582
10/13/2015 02:37:30.440 PM  Chromium: 581       (x8)
10/13/2015 02:37:30.518 PM  Chromium: 583
10/13/2015 02:37:30.518 PM  Chromium: 586

10/13/2015 02:37:35.324 PM  Form: WM_NCHITTEST          6. [Bar (i button) touch -ignored]
10/13/2015 02:37:35.324 PM  Form: WM_NCHITTEST
10/13/2015 02:37:35.324 PM  Form: WM_PARENTNOTIFY
10/13/2015 02:37:35.324 PM  Form: 587
10/13/2015 02:37:35.324 PM  Form: 282

根据这些,第3次和第4次触球打破了焦点。我们可以看到 chromium 控件在 586 之后停止接收最后一堆消息。我猜它缺少WM_PARENTNOTIFY备份到导致问题的表单。

我找不到有关 282、581、582、583、586 和 587 消息的任何信息。我可能会对 586 消息做出反应,并手动将WM_PARENTNOTIFY 发布到表单?我不确定快速连续接收其中两个会产生什么影响?

有谁知道为什么WM_SETCURSOR上的 5ms 睡眠保持这些消息流动?

或者关于修复的任何更好的想法?

4

1 回答 1

0

一旦我包含了面板控件、按钮和所有我能想到的鼠标事件,我就能发现一个模式:

这是一种有效的方法:

....
10/14/2015 01:00:10.263 PM  Chromium: WM_NCHITTEST
10/14/2015 01:00:10.263 PM  Chromium: WM_SETCURSOR
10/14/2015 01:00:10.263 PM  Chromium: WM_MOUSEMOVE
10/14/2015 01:00:10.263 PM  Chromium: WM_NCHITTEST
10/14/2015 01:00:10.263 PM  Form: WM_PARENTNOTIFY
10/14/2015 01:00:10.263 PM  Chromium: WM_MOUSEACTIVATE              <--
10/14/2015 01:00:10.263 PM  panelBrowserHeader: WM_NCLBUTTONDOWN    <--
10/14/2015 01:00:10.263 PM  Chromium: WM_SETCURSOR                  <--
10/14/2015 01:00:10.263 PM  Chromium: WM_LBUTTONDOWN
10/14/2015 01:00:10.263 PM  Chromium: WM_NCHITTEST
10/14/2015 01:00:10.263 PM  Chromium: WM_SETCURSOR
10/14/2015 01:00:10.263 PM  Chromium: WM_LBUTTONUP

这是一个没有:

....
10/14/2015 01:00:15.240 PM  Chromium: WM_NCHITTEST
10/14/2015 01:00:15.240 PM  Chromium: WM_SETCURSOR
10/14/2015 01:00:15.240 PM  Chromium: WM_MOUSEMOVE
10/14/2015 01:00:15.240 PM  Chromium: WM_NCHITTEST
10/14/2015 01:00:15.240 PM  Form: WM_PARENTNOTIFY
10/14/2015 01:00:15.240 PM  Chromium: WM_MOUSEACTIVATE              <--
10/14/2015 01:00:15.240 PM  Chromium: WM_SETCURSOR                  <--
10/14/2015 01:00:15.240 PM  panelBrowserHeader: WM_NCLBUTTONDOWN    <--
10/14/2015 01:00:15.240 PM  Chromium: WM_LBUTTONDOWN
10/14/2015 01:00:15.240 PM  Chromium: WM_MOUSELEAVE     

问题是,WM_NCLBUTTONDOWN 事件(作为对 WM_MOUSEACTIVATE 消息的反应而发布)有时会在下一个计划的 WM_SETCURSOR 消息之后发生。这似乎给人一种触摸事件在其原始控件范围之外完成的错觉,因此它触发了自己的 WM_MOUSELEAVE 消息。

通过延迟 WM_SETCURSOR 消息,它可以确保它们以正确的顺序触发。

我仍然对此感到困惑,因为我确信消息泵是一个单线程循环时间,它在每个控件的消息队列中进行切片。因此,当我的 Chromium 控件收到 WM_CURSOR 消息时阻止执行,我认为我正在阻止该 GUI 线程上存在的所有消息队列。

Anywho,它回答了为什么这样一个随机的“修复”绕过了这个问题的问题。

于 2015-10-14T16:01:14.510 回答