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

时间:2015-07-14 10:39:01

标签: c# wpf webbrowser-control activex

我有一个使用默认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);
}
在WebBrowser的HookInputElementForKeyboard事件上调用

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]

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

有谁知道这种行为可能是什么原因?有没有可行的解决方法?

1 个答案:

答案 0 :(得分:0)

刚刚找到另一种方法来实现这种行为,它的工作原理。我仍然不知道为什么。 解决方案可能看起来有点复杂,但这是我到目前为止找到的唯一方法。 首先,定义一个类,它将充当生成的mousemove事件的收集器 通过WebBrowser控件。我打电话给这个班级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);
         }
     }
 }

请注意,该类有一个名为DomMouseMove的事件:使用此事件而不是 客户端类中的直接侦听器。我们以前在哪里:

  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);
  }

显然,你还需要一个event args类:

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

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

并且,为了完成图片,这是我将客户端类附加到的方式 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);
  }