我有一个使用默认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]
应用程序日志和事件查看器中都没有跟踪错误。
有谁知道这种行为可能是什么原因?有没有可行的解决方法?
答案 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);
}