【问题标题】:onmousemove listener on WPF WebBrowser control stops working after few secondsWPF WebBrowser 控件上的 onmousemove 侦听器在几秒钟后停止工作
【发布时间】:2015-08-03 17:33:09
【问题描述】:

我有一个使用默认 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]

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

有人知道导致这种行为的原因是什么吗?有什么可能的解决方法吗?

【问题讨论】:

    标签: c# wpf webbrowser-control activex


    【解决方案1】:

    刚刚找到了另一种实现此行为的方法,并且有效。我仍然不知道究竟是为什么。 该解决方案可能看起来有点复杂,但这是我迄今为止发现的唯一方法。 首先,定义一个类,作为生成的 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);
      }
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 2014-09-26
      相关资源
      最近更新 更多