【问题标题】:Why my implementation of IDocHostUIHandler is ignored为什么我的 IDocHostUIHandler 实现被忽略
【发布时间】:2013-03-09 01:51:11
【问题描述】:

我从WebBrowser 控件创建了派生控件,该控件具有自己的IDocHostUIHandler 实现,遵循CreateWebBrowserSiteBase 方法的想法:

WebBrowser.WebBrowserSite 类提供默认实现 OLE IDocHostUIHandler 接口。您可以提供自己的 实现此接口或实现任何其他 WebBrowser ActiveX 控件接口,以便自定义的行为 控制。

无法解决的问题。我的代码如下所示:

[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
public MyBrowser(){}

protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
    var manager = new NewWebBrowserSite(this);
    return manager;
}

protected class NewWebBrowserSite : WebBrowserSite, 
    UnsafeNativeMethods.IDocHostUIHandler
{
    private MyBrowser host;
    public NewWebBrowserSite(MyBrowser h)
        : base(h)
    {
        this.host = h; 
    }

    int UnsafeNativeMethods.IDocHostUIHandler.ShowContextMenu(int dwID, NativeMethods.POINT pt, object pcmdtReserved, object pdispReserved)
    {
        MyBrowser wb = (MyBrowser)this.host;
        // other code
    }

    // rest of IDocHostUIHandler methods
}

我的问题是:

  1. 是否必须实现其他接口才能使其正常工作?
  2. 这是设计使然吗,我读过一些post,它与WebBrowser 的.net 框架实现中的一个错误有关

我知道可以采用ICustomDoc.SetUIHandler 的方式,但这不是我想要的。

我曾经有过放弃 c# 并使用非托管代码的想法。是这样吗?

【问题讨论】:

    标签: c# .net browser webbrowser-control


    【解决方案1】:

    我刚刚处理了完全相同的问题:如何为 WinForms WebBrowser 控件提供 IDocHostUIHandler 的自定义实现。问题是基类WebBrowserSite已经实现了自己的IDocHostUIHandler版本(这是一个internal接口,所以在派生类NewWebBrowserSite中不可能explicitly re-implement它)。但是,理论上,用相同的 GIID 和方法布局实现另一个 C# 接口应该不成问题(因为在这种特殊情况下,这就是所有 COM 客户端 - 底层 WebBrowser ActiveX 控件 - 所关心的)。

    不幸的是,在 .NET 4.0 之前这是不可能的。幸运的是,现在有了新的ICustomQueryInterface 功能:

    protected class NewWebBrowserSite : WebBrowserSite, 
        UnsafeNativeMethods.IDocHostUIHandler
        ICustomQueryInterface
    {
        private MyBrowser host;
        public NewWebBrowserSite(MyBrowser h): base(h)
        {
            this.host = h; 
        }
    
        int UnsafeNativeMethods.IDocHostUIHandler.ShowContextMenu(int dwID, NativeMethods.POINT pt, object pcmdtReserved, object pdispReserved)
        {
            MyBrowser wb = (MyBrowser)this.host;
            // other code
        }
    
        // rest of IDocHostUIHandler methods
    
        // ICustomQueryInterface
    
        public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
        {
            if (iid == typeof(UnsafeNativeMethods.IDocHostUIHandler).GUID)
            {
                ppv = Marshal.GetComInterfaceForObject(this, typeof(UnsafeNativeMethods.IDocHostUIHandler), CustomQueryInterfaceMode.Ignore);
            }
            else
            {
                ppv = IntPtr.Zero;
                return CustomQueryInterfaceResult.NotHandled;
            }
            return CustomQueryInterfaceResult.Handled;
        }   
    }
    

    【讨论】:

    • 别忘了致电Marshal.Release
    • @PaulB.,到底在哪里称呼它?
    • 哦,我想你是对的,QueryInterface 的调用者对此负责,对不起。
    【解决方案2】:

    您不能简单地覆盖类实现的接口。如果 IDocHostUIHandler 的方法未标记为虚拟,则无法替换它们。

    接口在UnsafeNativeMethods 中定义的事实也是一个线索,除非您非常清楚自己在做什么,否则您可能不应该弄乱它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-30
      • 2016-06-20
      • 1970-01-01
      • 2013-04-24
      • 2017-01-15
      • 2015-03-03
      • 2018-03-12
      • 2010-11-01
      相关资源
      最近更新 更多