WPF WebBrowser Control

时间:2015-07-14 15:44:04

标签: c# wpf visual-studio-2010

您好我需要在wpf中为Web浏览器控件创建自定义上下文菜单。这是我的xaml代码无效:

<WebBrowser x:Name="EmailBox"  ap:BrowserBehavior.HtmlString="{Binding Message, Mode=OneWay}">
    <WebBrowser.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Copy" Command="ApplicationCommands.Copy"/>
            <MenuItem Header="Copy to Customer Reference ID" 
                  Command="{Binding CopyID}"
                  CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, 
                  Path=PlacementTarget.Selection.Text}">
                <MenuItem.Icon>
                    <Image Source="{StaticResource CopyImageSource}" Width="16" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Header="Copy to Comments"
                  Command="{Binding CopyToCommentsCommand}"
                  CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, 
                  Path=PlacementTarget.Selection.Text}">
                <MenuItem.Icon>
                    <Image Source="{StaticResource NoteCopyI}" Width="16" />
                </MenuItem.Icon>
            </MenuItem>
        </ContextMenu>
    </WebBrowser.ContextMenu>
</WebBrowser>

我从其他地方复制了上下文菜单代码。这适用于其他控件,但不适用于webbrowser控件。是否有可能使这项工作?

4 个答案:

答案 0 :(得分:2)

您好,您必须添加对Microsoft HTML对象库的引用,而不是...

XAML

<Window x:Class="WPFCustomContextMenuInWebBrowser.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFCustomContextMenuInWebBrowser"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <ContextMenu x:Key="MnuCustom" StaysOpen="True">
      <MenuItem Header="Custom 1"></MenuItem>
      <MenuItem Header="Custom 1"></MenuItem>
      <MenuItem Header="Custom 3"></MenuItem>
    </ContextMenu>
  </Window.Resources>
    <Grid>
        <WebBrowser x:Name="Wb"></WebBrowser>
    </Grid>
</Window>

C#

using System.Windows.Controls;
using MSHTML;

namespace WPFCustomContextMenuInWebBrowser {
  public partial class MainWindow {
    private HTMLDocumentEvents2_Event _docEvent;
    public MainWindow() {
      InitializeComponent();
      Wb.Navigate("http://google.com");
      Wb.LoadCompleted += delegate {
        if (_docEvent != null) {
          _docEvent.oncontextmenu -= _docEvent_oncontextmenu;
        }
        if (Wb.Document != null) {
          _docEvent = (HTMLDocumentEvents2_Event)Wb.Document;
          _docEvent.oncontextmenu += _docEvent_oncontextmenu;
        }
      };
    }

    bool _docEvent_oncontextmenu(IHTMLEventObj pEvtObj) {
      WbShowContextMenu();
      return false;
    }

    public void WbShowContextMenu() {
      ContextMenu cm = FindResource("MnuCustom") as ContextMenu;
      if (cm == null) return;
      cm.PlacementTarget = Wb;
      cm.IsOpen = true;
    }
  }
}

答案 1 :(得分:1)

不,这是不可能的。
WebBrowser控件是本机WebBrowser ActiveX组件的一个非常薄的包装器,它是Internet Explorer子系统的一部分。它托管在它自己的窗口主机(WPF窗口和WebBrowser有不同的HWND)中,因此WPF只知道进入和离开WebBrowser的焦点,但不知道任何键盘/鼠标事件。此外,还有所谓的“空域问题”:WPF渲染和屏幕区域的原生区域不能重叠。
 因此,您不能将WPF ContextMenu与WebBrowser一起使用,因为:

  1. WPF未收到鼠标右键单击事件以打开上下文菜单
  2. WPF无法在WebBrowser上方绘制上下文菜单
  3. 另外,我认为在浏览器的内容中使用html / js模拟ContextMenu并不容易 - 我记得,ActiveX组件使用IE5(quirk)渲染模式,如果不改变注册表就不可能改变它文件。
    您可以尝试使用带有WebBrowser.Document对象的ActiveX API来禁用本机上下文菜单,并通过WinAPI自己绘制另一个菜单,这不是一件容易的事。 所以,我建议寻找其他纯WPF浏览器控件或HTML渲染器,例如awesomium

答案 2 :(得分:0)

XAML如下:

<!--WebBrowser to Display Chat Messages-->
    <WebBrowser Name="webBrowser"
                    Source="http://stakoverflow.com"                        
                    Navigated="webBrowser_Navigated"
                    Navigating="webBrowser_Navigating"
                    LoadCompleted="webBrowser_LoadCompleted">
        <WebBrowser.ContextMenu>
            <ContextMenu x:Name="wbContextMenu" >
                <MenuItem x:Name="menuItem1" Header="Test Item" Click="menuItem1_Click" />
            </ContextMenu>
        </WebBrowser.ContextMenu            
    </WebBrowser>

代码如下:

using mshtml;

private mshtml.HTMLDocumentEvents2_Event documentEvents;

在构造函数或xaml中设置LoadComplete事件:

webBrowser.LoadCompleted += webBrowser_LoadCompleted;

然后在该方法中创建新的webbrowser文档对象并查看可用属性并创建新事件,如下所示:

private void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
    documentEvents = (HTMLDocumentEvents2_Event)webBrowserChat.Document; // this will access the events properties as needed
    documentEvents.oncontextmenu += webBrowserChat_ContextMenuOpening;
}

private bool webBrowserChat_ContextMenuOpening(IHTMLEventObj pEvtObj)
{
    wbContextMenu.PlacementTarget = pEvtObj as ContextMenu; // Creates target spot where contextmenu will appear
    wbContextMenu.IsOpen = true; // Opens contextmneu
    return false; // ContextMenu wont open
    // return true;  ContextMenu will open
    // Here you can create your custom contextmenu or whatever you want
}

答案 3 :(得分:0)

我已经采用了@MartinHoly提供的解决方案并且我遇到了问题:上下文菜单只能弹出一次(例如,如果右键单击滚动条,或者选择一个自定义菜单项 - 下次右键单击WebBrowser带来的标准IE菜单)。我做了以下解决方法: xaml:

<Window x:Class="WPFCustomContextMenuInWebBrowser.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WPFCustomContextMenuInWebBrowser"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <ContextMenu x:Key="MnuCustom" StaysOpen="True">
      <MenuItem Header="Custom 1"></MenuItem>
      <MenuItem Header="Custom 2"></MenuItem>
      <MenuItem Header="Custom 3"></MenuItem>
    </ContextMenu>
  </Window.Resources>
<Grid>
    <WebBrowser x:Name="Browser"></WebBrowser>
</Grid>

背后的代码:

using System.Windows.Controls;
using MSHTML;

namespace WPFCustomContextMenuInWebBrowser {
  public partial class MainWindow {

    public MainWindow() 
    {
      InitializeComponent();
      Browser.LoadCompleted += BrowserOnLoadCompleted;
    }

    void BrowserOnLoadCompleted(object sender, NavigationEventArgs navigationEventArgs)
    {
        var mshtmlDoc = Browser.Document as HTMLDocument;
        if (mshtmlDoc == null) return;
                    var doc2event = mshtmlDoc as HTMLDocumentEvents2_Event;
        if (doc2event != null)
        {               
            doc2event.onfocusin += FocusInContextMenu;
        }            
    }

    bool OpenContextMenu(IHTMLEventObj pEvtObj)
    {
        WbShowContextMenu(pEvtObj as ContextMenu);
        return false;
    }

    void FocusInContextMenu(IHTMLEventObj pevtobj)
    {
        var mshtmlDoc = Browser.Document as HTMLDocument;
        var doc2event = mshtmlDoc as HTMLDocumentEvents2_Event;
        if (doc2event != null)
        {
            doc2event.oncontextmenu -= OpenContextMenu;
            doc2event.onfocusin -= FocusInContextMenu;
            doc2event.oncontextmenu += OpenContextMenu;
            doc2event.onfocusin += FocusInContextMenu;
        }
    }

    public void WbShowContextMenu() 
    {
      ContextMenu cm = FindResource("MnuCustom") as ContextMenu;
      if (cm == null) return;
      cm.PlacementTarget = Browser;
      cm.IsOpen = true;
    }
  }
}