简体   繁体   中英

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). I have the need to intercept MouseMove events that happen on the browser. In order to subscribe to the event I use the following code fragment (these are methods of a UserControl that wraps the WebBrowser):

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. The problem is that after a seemingly random amount of time (usually some seconds), the callback DocumentOnMouseMove stops being called. This an extract of my log with the timestamps of the events (format is <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. I called this 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);
         }
     }
 }

Note that the class has an event called DomMouseMove: use this event instead of a direct listener in the client class. 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:

  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:

  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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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