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