【问题标题】:How to use 'Back' & 'Forward' navigation button events in WPF WebBrowser?如何在 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 buttonsmean 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,
    }

【问题讨论】:

  • 没问题。这是通过您的努力解决的。

标签: c# wpf webbrowser-control


【解决方案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_LBUTTONDOWNevent 很酷,XBUTTONevent 不是。我试过0x0001 and 0x0020作为MouseMessages enum的值XBUTTONevent。我做错了什么?
  • 你检查高位文本了吗?看看这个链接msdn.microsoft.com/en-us/library/ms997498.aspx
  • 不,你应该检查0x020C 和按钮检查高位字参数0x00010x0002
  • 感谢您的评论。我实现了鼠标导航事件的使用,0x020B 作为MouseMessages enum0x10000 用于左侧XBUTTON0x20000 用于右侧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

说明

XButton1XButton2 可能默认映射到 BackForward 导航,但情况可能并非总是如此。这些按钮可以重新映射到其他功能,有些鼠标有五个以上的按钮。那么,您实际上是如何收听Backwards navigation 消息的呢?

  1. 联系WndProc
  2. 收听WM_APPCOMMAND 消息。
  3. lparam 中,做一些位旋转并找到实际的APPCOMMAND_* 值。
  4. 如果它是所需的值(例如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 屏蔽。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 2023-03-09
    • 2011-01-13
    • 2018-02-04
    • 2018-08-02
    • 1970-01-01
    相关资源
    最近更新 更多