如何在WPF Webbrowser Control上停用“右键单击”?

我似乎无法找到答案。 有人知道吗?

谢谢

下面是一个实用程序类的代码,允许您停用WPF的WebBrowser上下文菜单。 它还允许您抑制脚本错误( WPF WebBrowser控件 – 如何抑制脚本错误? )并更改IE的DOCHOSTUIFLAG 。

使用范例:

public partial class Player : Window { private WebBrowserHostUIHandler _wbHandler; public Player() { InitializeComponent(); ... _wbHandler = new WebBrowserHostUIHandler(MyWebBrower); _wbHandler.IsWebBrowserContextMenuEnabled = false; } } 

实用代码:

 public class WebBrowserHostUIHandler : Native.IDocHostUIHandler { private const uint E_NOTIMPL = 0x80004001; private const uint S_OK = 0; private const uint S_FALSE = 1; public WebBrowserHostUIHandler(WebBrowser browser) { if (browser == null) throw new ArgumentNullException("browser"); Browser = browser; browser.LoadCompleted += OnLoadCompleted; browser.Navigated += OnNavigated; IsWebBrowserContextMenuEnabled = true; Flags |= HostUIFlags.ENABLE_REDIRECT_NOTIFICATION; } public WebBrowser Browser { get; private set; } public HostUIFlags Flags { get; set; } public bool IsWebBrowserContextMenuEnabled { get; set; } public bool ScriptErrorsSuppressed { get; set; } private void OnNavigated(object sender, NavigationEventArgs e) { SetSilent(Browser, ScriptErrorsSuppressed); } private void OnLoadCompleted(object sender, NavigationEventArgs e) { Native.ICustomDoc doc = Browser.Document as Native.ICustomDoc; if (doc != null) { doc.SetUIHandler(this); } } uint Native.IDocHostUIHandler.ShowContextMenu(int dwID, Native.POINT pt, object pcmdtReserved, object pdispReserved) { return IsWebBrowserContextMenuEnabled ? S_FALSE : S_OK; } uint Native.IDocHostUIHandler.GetHostInfo(ref Native.DOCHOSTUIINFO info) { info.dwFlags = (int)Flags; info.dwDoubleClick = 0; return S_OK; } uint Native.IDocHostUIHandler.ShowUI(int dwID, object activeObject, object commandTarget, object frame, object doc) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.HideUI() { return E_NOTIMPL; } uint Native.IDocHostUIHandler.UpdateUI() { return E_NOTIMPL; } uint Native.IDocHostUIHandler.EnableModeless(bool fEnable) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.OnDocWindowActivate(bool fActivate) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.OnFrameWindowActivate(bool fActivate) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.ResizeBorder(Native.COMRECT rect, object doc, bool fFrameWindow) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.TranslateAccelerator(ref System.Windows.Forms.Message msg, ref Guid group, int nCmdID) { return S_FALSE; } uint Native.IDocHostUIHandler.GetOptionKeyPath(string[] pbstrKey, int dw) { return E_NOTIMPL; } uint Native.IDocHostUIHandler.GetDropTarget(object pDropTarget, out object ppDropTarget) { ppDropTarget = null; return E_NOTIMPL; } uint Native.IDocHostUIHandler.GetExternal(out object ppDispatch) { ppDispatch = Browser.ObjectForScripting; return S_OK; } uint Native.IDocHostUIHandler.TranslateUrl(int dwTranslate, string strURLIn, out string pstrURLOut) { pstrURLOut = null; return E_NOTIMPL; } uint Native.IDocHostUIHandler.FilterDataObject(IDataObject pDO, out IDataObject ppDORet) { ppDORet = null; return E_NOTIMPL; } public static void SetSilent(WebBrowser browser, bool silent) { Native.IOleServiceProvider sp = browser.Document as Native.IOleServiceProvider; if (sp != null) { Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046"); Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"); object webBrowser; sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser); if (webBrowser != null) { webBrowser.GetType().InvokeMember("Silent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty, null, webBrowser, new object[] { silent }); } } } } internal static class Native { [ComImport, Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDocHostUIHandler { [PreserveSig] uint ShowContextMenu(int dwID, POINT pt, [MarshalAs(UnmanagedType.Interface)] object pcmdtReserved, [MarshalAs(UnmanagedType.Interface)] object pdispReserved); [PreserveSig] uint GetHostInfo(ref DOCHOSTUIINFO info); [PreserveSig] uint ShowUI(int dwID, [MarshalAs(UnmanagedType.Interface)] object activeObject, [MarshalAs(UnmanagedType.Interface)] object commandTarget, [MarshalAs(UnmanagedType.Interface)] object frame, [MarshalAs(UnmanagedType.Interface)] object doc); [PreserveSig] uint HideUI(); [PreserveSig] uint UpdateUI(); [PreserveSig] uint EnableModeless(bool fEnable); [PreserveSig] uint OnDocWindowActivate(bool fActivate); [PreserveSig] uint OnFrameWindowActivate(bool fActivate); [PreserveSig] uint ResizeBorder(COMRECT rect, [MarshalAs(UnmanagedType.Interface)] object doc, bool fFrameWindow); [PreserveSig] uint TranslateAccelerator(ref System.Windows.Forms.Message msg, ref Guid group, int nCmdID); [PreserveSig] uint GetOptionKeyPath([Out, MarshalAs(UnmanagedType.LPArray)] string[] pbstrKey, int dw); [PreserveSig] uint GetDropTarget([In, MarshalAs(UnmanagedType.Interface)] object pDropTarget, [MarshalAs(UnmanagedType.Interface)] out object ppDropTarget); [PreserveSig] uint GetExternal([MarshalAs(UnmanagedType.IDispatch)] out object ppDispatch); [PreserveSig] uint TranslateUrl(int dwTranslate, [MarshalAs(UnmanagedType.LPWStr)] string strURLIn, [MarshalAs(UnmanagedType.LPWStr)] out string pstrURLOut); [PreserveSig] uint FilterDataObject(IDataObject pDO, out IDataObject ppDORet); } [StructLayout(LayoutKind.Sequential)] internal struct DOCHOSTUIINFO { public int cbSize; public int dwFlags; public int dwDoubleClick; public IntPtr dwReserved1; public IntPtr dwReserved2; } [StructLayout(LayoutKind.Sequential)] internal struct COMRECT { public int left; public int top; public int right; public int bottom; } [StructLayout(LayoutKind.Sequential)] internal class POINT { public int x; public int y; } [ComImport, Guid("3050F3F0-98B5-11CF-BB82-00AA00BDCE0B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ICustomDoc { [PreserveSig] int SetUIHandler(IDocHostUIHandler pUIHandler); } [ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IOleServiceProvider { [PreserveSig] uint QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject); } } [Flags] public enum HostUIFlags { DIALOG = 0x00000001, DISABLE_HELP_MENU = 0x00000002, NO3DBORDER = 0x00000004, SCROLL_NO = 0x00000008, DISABLE_SCRIPT_INACTIVE = 0x00000010, OPENNEWWIN = 0x00000020, DISABLE_OFFSCREEN = 0x00000040, FLAT_SCROLLBAR = 0x00000080, DIV_BLOCKDEFAULT = 0x00000100, ACTIVATE_CLIENTHIT_ONLY = 0x00000200, OVERRIDEBEHAVIORFACTORY = 0x00000400, CODEPAGELINKEDFONTS = 0x00000800, URL_ENCODING_DISABLE_UTF8 = 0x00001000, URL_ENCODING_ENABLE_UTF8 = 0x00002000, ENABLE_FORMS_AUTOCOMPLETE = 0x00004000, ENABLE_INPLACE_NAVIGATION = 0x00010000, IME_ENABLE_RECONVERSION = 0x00020000, THEME = 0x00040000, NOTHEME = 0x00080000, NOPICS = 0x00100000, NO3DOUTERBORDER = 0x00200000, DISABLE_EDIT_NS_FIXUP = 0x00400000, LOCAL_MACHINE_ACCESS_CHECK = 0x00800000, DISABLE_UNTRUSTEDPROTOCOL = 0x01000000, HOST_NAVIGATES = 0x02000000, ENABLE_REDIRECT_NOTIFICATION = 0x04000000, USE_WINDOWLESS_SELECTCONTROL = 0x08000000, USE_WINDOWED_SELECTCONTROL = 0x10000000, ENABLE_ACTIVEX_INACTIVATE_MODE = 0x20000000, DPI_AWARE = 0x40000000 } 

参考mshtml

 using mshtml; 

然后,您可以通过访问文档来执行此操作:

 MainBrowser.Navigate("https://www.domain.com"); MainBrowser.LoadCompleted += (o, args) => { var doc = (HTMLDocumentEvents2_Event) MainBrowser.Document; doc.oncontextmenu += obj => false; }; 

从内部WebBrowserSite类:

 int UnsafeNativeMethods.IDocHostUIHandler.ShowContextMenu(int dwID, NativeMethods.POINT pt, object pcmdtReserved, object pdispReserved) { // Returning S_FALSE will allow the native control to do default processing, // ie, execute the shortcut key. Returning S_OK will cancel the context menu return NativeMethods.S_FALSE; } 

硬烤,你不能覆盖这个。 将Winforms WebBrower放在WindowsFormsHost中将是一种解决方法,它有一个更智能的实现,使用IsWebBrowserContextMenuEnabled属性并允许您创建自己的上下文菜单。

这是一个老问题,但我有一个独特的问题,我希望/需要使用.Net Core SDK的较新的CSProj文件格式,但它有一个已知的问题 ,无法引用扩展库,如mshtml。 所以我终于找到了一个没有mshtml参考的解决方案。

一些灵感来自https://stackoverflow.com/a/28464764/2646868 ,其中用户将WebBrowser.Document属性WebBrowser.Documentdynamic

假设webView是WebBrowser控件的名称,请将LoadCompleted事件挂钩,如下所示:

 private void webView_LoadCompleted(object sender, NavigationEventArgs e) { dynamic document = webView.Document; document.oncontextmenu += new Func(() => false); }