WPF WebBrowser 控件上的 onmousemove 侦听器在几秒钟后停止工作

onmousemove listener on WPF WebBrowser control stops working after few seconds

我有一个使用默认 WebBrowser 控件 (System.Windows.Controls.WebBrowser) 的 Windows WPF 应用程序。 我需要拦截浏览器上发生的 MouseMove 事件。为了订阅事件,我使用了以下代码片段(这些是包装 WebBrowser 的 UserControl 的方法):

public void HookInputElementForKeyboard()
{
    HTMLDocument htmlDocument = (HTMLDocument)webBrowserControl.Document;

    htmlDocument.attachEvent("oncontextmenu", new ContextMenuDisablerEventHandler());
    HTMLDocumentEvents_Event documentEvents = htmlDocument as HTMLDocumentEvents_Event;
    documentEvents.onmousemove += DocumentOnMouseMove;
}

private void DocumentOnMouseMove()
{
    HTMLDocument document = webBrowserControl.Document as HTMLDocument;
    var window = document.parentWindow as IHTMLWindow2;
    var currentEvent = window.@event;
    MouseMoveOnDocumentEventArgs args = new MouseMoveOnDocumentEventArgs(currentEvent.clientX, currentEvent.clientX);
    var now = DateTime.Now;
    logger.Debug(now.Second + "." + now.Millisecond + ": " + args.ToString());
    // fires the event of the wrapping UserControl to notify the MouseMove to external clients
    OnMouseMoveOnDocument(args);
}

HookInputElementForKeyboard 在 WebBrowser 的 LoadCompleted 事件上被调用。 问题是在一段看似随机的时间(通常是几秒钟)之后,回调 DocumentOnMouseMove 停止被调用。 这是我的日志的摘录,其中包含事件的时间戳(格式为 <timestampSeconds>: [<clientX>; <clientY>]):

2015-07-14 10:30:22,005 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - onmousemove event subscribed at 22.5
[some other unrelated logs]
2015-07-14 10:30:22,568 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.568: [4; 4]
2015-07-14 10:30:22,584 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.584: [15; 15]
2015-07-14 10:30:22,584 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.584: [24; 24]
[...]
2015-07-14 10:30:22,599 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.599: [33; 33]
2015-07-14 10:30:22,599 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.599: [45; 45]
2015-07-14 10:30:22,615 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.615: [63; 63]
2015-07-14 10:30:22,615 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 22.615: [92; 92]
[...]
2015-07-14 10:30:23,849 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 23.849: [565; 565]
2015-07-14 10:30:23,849 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 23.849: [571; 571]
2015-07-14 10:30:23,865 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 23.865: [580; 580]
2015-07-14 10:30:23,865 [8] DEBUG Common.GUI.UserControls.WebBrowserView [(null)] - 23.865: [587; 587]
[from now on, the MouseMove event is not captured any more, even if I keep moving the pointer]

应用程序日志和事件查看器中都没有跟踪到错误。

有人知道造成这种行为的原因是什么吗?有任何可能的解决方法吗?

刚刚找到了另一种实现此行为的方法并且它有效。我仍然不知道为什么。 该解决方案可能看起来有点复杂,但这是迄今为止我找到的唯一方法。 首先,定义一个 class 作为生成的 mousemove 事件的收集器 通过 WebBrowser 控件。我称之为 class DomMouseMoveEventManager:

 [ComVisible(true)]
 [ClassInterface(ClassInterfaceType.AutoDispatch)]
 public class DomMouseMoveEventManager
 {
     public event DomMouseMoveEventHandler DomMouseMove;
     [DispId(0)]
     public void CallbackFunction(mshtml.IHTMLEventObj arg)
     {
         //Console.WriteLine(String.Format("[{0}, {1}]", arg.clientX, arg.clientY));
         OnDomMouseMove(arg.clientX, arg.clientY);
     }

     private void OnDomMouseMove(int clientX, int clientY)
     {
         if(DomMouseMove != null)
         {
             var args = new DomMouseMoveEventArgs(clientX, clientY);
             DomMouseMove(this, args);
         }
     }
 }

请注意 class 有一个名为 DomMouseMove 的事件:使用此事件而不是 客户端中的直接监听器 class。之前我们有:

  private void HookOnMouseMove()
  {
      var document = WebBrowserControl.Document as HTMLDocument;
      var documentEvents = document as HTMLDocumentEvents_Event;
      documentEvents.onmousemove += documentEvents_onmousemove;
  }

现在我们使用 DomMouseMoveEventManager 类型的成员注册事件,如下所示:

  private DomMouseMoveEventManager mouseMoveManager;
  private void HookOnMouseMove()
  {
      var document = WebBrowserControl.Document as HTMLDocument;
      document.attachEvent("onmousemove", mouseMoveManager);
  }

显然,您还需要一个事件参数 class:

  public class DomMouseMoveEventArgs : RoutedEventArgs
  {
      public int ClientX { get; set; }
      public int ClientY { get; set; }

      public DomMouseMoveEventArgs(int clientX, int clientY)
      {
          ClientX = clientX;
          ClientY = clientY;
      }
  }

而且,为了完成图片,这就是我将客户端 class 附加到 DomMouseMoveEventManager:

// The constructor of the client class that must be notified the mousemove event
  public WebBrowserAdapter()
  {
      InitializeComponent();
      this.Loaded += WebBrowserAdapter_Loaded;
      mouseMoveManager = new DomMouseMoveEventManager();
      mouseMoveManager.DomMouseMove += mouseMoveManager_DomMouseMove;
  }

  void mouseMoveManager_DomMouseMove(object source, DomMouseMoveEventArgs args)
  {
      diagnosticBlock.Text = "[" + args.ClientX + "; " + args.ClientY + "]";
      OnDomMouseMove(args.ClientX, args.ClientY);
  }