为啥我的 IDocHostUIHandler 实现被忽略

Posted

技术标签:

【中文标题】为啥我的 IDocHostUIHandler 实现被忽略【英文标题】: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

我的问题是:

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

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

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

【问题讨论】:

【参考方案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 中定义的事实也是一个线索,除非您非常清楚自己在做什么,否则您可能不应该弄乱它。

【讨论】:

以上是关于为啥我的 IDocHostUIHandler 实现被忽略的主要内容,如果未能解决你的问题,请参考以下文章

C++ COM 设计。组合与多重继承

为啥我的 numpy.random.choice 实现更快?

为啥我的卷积实现比 Tensorflow 的慢?

为啥我的通用服务出现“无法实例化实现类型”错误?

为啥我的基数排序 python 实现比快速排序慢?

为啥我的 Printable 实现在 Swift 操场上不起作用?