walter
walter

Reputation: 823

Why my implementation of IDocHostUIHandler is ignored

I have created derived control from WebBrowser control that has own IDocHostUIHandler implementation following idea from CreateWebBrowserSiteBase method:

The WebBrowser.WebBrowserSite class provides default implementations of the OLE IDocHostUIHandler interface. You can provide your own implementation of this interface or implement any other WebBrowser ActiveX control interface in order to customize the behavior of the control.

The problem that is not working. My code looks next way:

[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
}

My questions are:

  1. Do I have to implement other interfaces to make it working;
  2. Is that by design, I have read some post that it is related to a bug in .net framework implementation of WebBrowser

I know that is possible to go ICustomDoc.SetUIHandler way, but it is not what I am looking for.

I was having idea at some point to give up with c# and do that with unmanaged code. Is that the way?

Upvotes: 3

Views: 1905

Answers (2)

noseratio
noseratio

Reputation: 61726

I've just dealt with exactly the same problem: how to provide a custom implementation of IDocHostUIHandler to WinForms WebBrowser control. The problem is that the base class WebBrowserSite has already implemented its own version of IDocHostUIHandler (which is an internal interface, so it's not possible to explicitly re-implement it in the derived class NewWebBrowserSite). However, in theory it should not be a problem to implement another C# interface with the same GIID and methods layout (because that's all the COM client - the underlying WebBrowser ActiveX Control - cares about in this particular case).

Unfortunately, it was not possible until .NET 4.0. Luckily, now it is, by means of the new ICustomQueryInterface feature:

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;
    }   
}

Upvotes: 4

Jason Watkins
Jason Watkins

Reputation: 3785

You can't simply override the interfaces implemented by a class. If the methods for IDocHostUIHandler are not marked as virtual, you can't replace them.

The fact that the interface is defined in UnsafeNativeMethods is also a clue that you probably shouldn't be messing with it unless you have a very good idea of what you're doing.

Upvotes: 1

Related Questions