如何在 WPF WebBrowser 中使用“后退”和“前进”导航按钮事件?
Posted
技术标签:
【中文标题】如何在 WPF WebBrowser 中使用“后退”和“前进”导航按钮事件?【英文标题】:How to use 'Back' & 'Forward' navigation button events in WPF WebBrowser? 【发布时间】:2011-09-16 07:42:21 【问题描述】:WPF 中的WebBrowser
控件继承自UIElement
,但我们无法在UIElement
事件中注册事件处理程序。为什么? WPF WebBrowser Mouse Events not working as expected有回答,但还是看不懂。
无论如何,将处理程序连接到WebBrowser
的文档提供的事件可以捕获大多数鼠标事件,但不能使用“后退”和“前进”导航按钮事件。由于Internet Explorer可以做到这一点,我认为这是可能的。有没有办法解决这个问题?
更新:
在这个问题中,'Back' & 'Forward' navigation buttons
mean XButton1 和 XButton2 在 5 键鼠标系统中。
UPDATE2:我用 Navid Rahmani 的回答解决了这个问题。我认为有人会需要这个答案,所以我附上主要部分。如果发现任何问题或更合理的解决方案,请告诉我。
//This code assumes the `WebBrowser` field named _webBrowser is already initiated.
//For the detail out of this code, please refer to the Navid Rahmani's answer.
private bool _isMouseOver;
private htmlDocumentEvents2_Event _docEvent;
public ctor()
_webBrowser.LoadCompleted += _webBrowser_LoadCompleted;
private void _webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
if (_docEvent != null)
_docEvent.onmouseover -= _docEvent_onmouseover;
_docEvent.onmouseout -= _docEvent_onmouseout;
if (_webBrowser.Document != null)
_docEvent = (HTMLDocumentEvents2_Event)_webBrowser.Document;
_docEvent.onmouseover += _docEvent_onmouseover;
_docEvent.onmouseout += _docEvent_onmouseout;
void _docEvent_onmouseout(IHTMLEventObj pEvtObj)
_isMouseOver = false;
void _docEvent_onmouseover(IHTMLEventObj pEvtObj)
_isMouseOver = true;
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
if (_isMouseOver)
if (nCode >= 0 && (MouseMessages)wParam == MouseMessages.XBUTTON)
var hookStruct = (Msllhookstruct)Marshal.PtrToStructure(lParam, typeof(Msllhookstruct));
if (hookStruct.mouseData == 0x10000)
//do something when XButto1 clicked
else if (hookStruct.mouseData == 0x20000)
//do something when XButto2 clicked
return CallNextHookEx(_hookID, nCode, wParam, lParam);
private enum MouseMessages
//WM_LBUTTONDOWN = 0x00A1,
//WM_LBUTTONUP = 0x0202,
//WM_MOUSEMOVE = 0x0200,
//WM_MOUSEWHEEL = 0x020A,
//WM_RBUTTONDOWN = 0x0204,
//WM_RBUTTONUP = 0x0205,
XBUTTON = 0x020B,
【问题讨论】:
没问题。这是通过您的努力解决的。 【参考方案1】:WebBrowser 控件实际上只是 Trident COM 对象的薄包装器。它不像其他内置控件那样是“纯 WPF”……所以很多正常的东西都不能用它。要回答您的问题,您可以获得的最接近的方法是连接到 Navigating 事件。这不会告诉您用户是在尝试前进还是后退或其他地方,但它会给您 URL 和设置 e.Cancel = true 以停止导航的机会(通常随后调用 Navigate(url) 进行其他地方的用户)。
【讨论】:
首先,感谢您的回答。但是,无论方向如何,我都无法使用鼠标XButton
click 为WebBrowser
的导航事件注册事件句柄。【参考方案2】:
您可以使用鼠标的低级挂钩并检查xbutton1或xbutton2是否被点击 看here
WM_XBUTTONDOWN
的值看http://msdn.microsoft.com/en-us/library/ms646245(VS.85).aspx
【讨论】:
我试过作为你的答案,但WM_LBUTTONDOWN
event 很酷,XBUTTON
event 不是。我试过0x0001 and 0x0020
作为MouseMessages enum
的值XBUTTON
event。我做错了什么?
你检查高位文本了吗?看看这个链接msdn.microsoft.com/en-us/library/ms997498.aspx
不,你应该检查0x020C
和按钮检查高位字参数0x0001
和0x0002
感谢您的评论。我实现了鼠标导航事件的使用,0x020B
作为MouseMessages enum
,0x10000
用于左侧XBUTTON
和0x20000
用于右侧XBUTTON
作为hookStruct.mouseData
。但是,如果在窗口中的任何位置触发事件,则会处理鼠标导航事件。
您可以检查鼠标是否在文档上。【参考方案3】:
更简单的方法....
这适用于 WPF 和 .net 4.5
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
if (e.ChangedButton.Equals(MouseButton.XButton1)) MessageBox.Show(@"back");
if (e.ChangedButton.Equals(MouseButton.XButton2)) MessageBox.Show(@"forward");
【讨论】:
MouseDown 和 PreviewMouseDown 被 WebBrowser 控件吞噬,所以它对我不起作用。【参考方案4】:TL;DR
安装我的 nuget 包 Lette.Wpf.AppCommands (source on GitHub) 并将其添加到您的主窗口:
<l:Window.AppCommandBindings>
<AppCommandBinding AppCommand="BrowserBackward" Command="Binding BackCommand" />
</l:Window.AppCommandBindings>
只要按下“返回”按钮(无论是哪个),都会调用BackCommand
。
说明
XButton1
和 XButton2
可能默认映射到 Back 和 Forward 导航,但情况可能并非总是如此。这些按钮可以重新映射到其他功能,有些鼠标有五个以上的按钮。那么,您实际上是如何收听Backwards navigation 消息的呢?
-
联系
WndProc
。
收听WM_APPCOMMAND
消息。
在lparam
中,做一些位旋转并找到实际的APPCOMMAND_*
值。
如果它是所需的值(例如APPCOMMAND_BROWSER_BACKWARD
),请执行您的操作。
例子:
var hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(mainWindow).Handle);
hwndSource.AddHook(WndProc);
// ...
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
if (msg == WM_APPCOMMAND)
var appCommand = BitTwiddling(lparam);
if (appCommand == APPCOMMAND_BROWSER_BACKWARD)
// do your thing
return IntPtr.Zero;
mainWindow
是对主窗口的引用(Window
类型)。
BitTwiddling
基本上是:将IntPtr
转换为int
,右移16 位,然后用0x7FFF 屏蔽。
【讨论】:
以上是关于如何在 WPF WebBrowser 中使用“后退”和“前进”导航按钮事件?的主要内容,如果未能解决你的问题,请参考以下文章
WPF:如何在弹出窗口中自动调整 WebBrowser 的大小?
在 WPF 中使用 WebBrowser 关闭窗口后音频继续播放