简体   繁体   English

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

[英]onmousemove listener on WPF WebBrowser control stops working after few seconds

I Have a Windows WPF application that uses the default WebBrowser control (System.Windows.Controls.WebBrowser). 我有一个使用默认WebBrowser控件(System.Windows.Controls.WebBrowser)的Windows WPF应用程序。 I have the need to intercept MouseMove events that happen on the browser. 我需要拦截浏览器上发生的MouseMove事件。 In order to subscribe to the event I use the following code fragment (these are methods of a UserControl that wraps the WebBrowser): 为了订阅事件,我使用以下代码片段(这些是包装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 gets called on the LoadCompleted event of the WebBrowser. HookInputElementForKeyboard在WebBrowser的LoadCompleted事件上被调用。 The problem is that after a seemingly random amount of time (usually some seconds), the callback DocumentOnMouseMove stops being called. 问题是,在看似随机的时间(通常是几秒钟)后,回调DocumentOnMouseMove停止了调用。 This an extract of my log with the timestamps of the events (format is <timestampSeconds>: [<clientX>; <clientY>] ): 这是事件日志的<timestampSeconds>: [<clientX>; <clientY>] (格式为<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]

There is no error traced in the application log nor in the Event Viewer. 在应用程序日志或事件查看器中均未跟踪任何错误。

Anybody knows what could be the cause of this behaviour? 有人知道这种行为的原因是什么? Is there any possible workaround? 有没有可能的解决方法?

Just found another way to implement this behavior and it works. 刚刚找到了实现此行为的另一种方法,并且它可以工作。 I still do not know exactly why. 我仍然不知道为什么。 The solution might seem a bit convoluted, but it's the only way I found so far. 解决方案似乎有些令人费解,但这是我到目前为止发现的唯一方法。 First, define a class that will act as a collector of the mousemove event generated by the WebBrowser control. 首先,定义一个类,该类将充当由WebBrowser控件生成的mousemove事件的收集器。 I called this class DomMouseMoveEventManager : 我称此类为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);
         }
     }
 }

Note that the class has an event called DomMouseMove: use this event instead of a direct listener in the client class. 请注意,该类有一个名为DomMouseMove的事件:在客户端类中使用此事件代替直接侦听器。 Where previously we had: 我们以前在哪里:

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

now we register to the event using a member of type DomMouseMoveEventManager , like this: 现在,我们使用DomMouseMoveEventManager类型的成员注册该事件,如下所示:

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

Obviously, you will also need an event args class: 显然,您还将需要一个事件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;
      }
  }

And, in order to complete the picture, this is how I attach the client class to the DomMouseMoveEventManager: 并且,为了完成图片,这是将客户端类附加到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);
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM