Extending WebBrowser using WebBrowserSite won't call methods - sample code?

  • Thread starter Thread starter DavidB
  • Start date Start date
D

DavidB

Trying to extend a 2.0 WebBrowser control using WebBrowserSite as per docs.
Tried implementing IDocHostUIHandler, IDocHostUIHandler2,
IInternetSecuritymanager, IServiceProvider.
The only methods which get called (so far) are
IDocHostUIHandler2.GetOverrideKeyPath() and IServiceProvider.QueryService().
What do I have to do to get the others to be called?
A bit of sample code would do wonders at this point!!!

DavidB
 
DavidB said:
Trying to extend a 2.0 WebBrowser control using WebBrowserSite as per
docs. Tried implementing IDocHostUIHandler, IDocHostUIHandler2,
IInternetSecuritymanager, IServiceProvider.
The only methods which get called (so far) are
IDocHostUIHandler2.GetOverrideKeyPath() and
IServiceProvider.QueryService(). What do I have to do to get the
others to be called?

If you managed to get IDocHostUIHandler2 called, then you should not
have any difficulty with IDocHostUIHandler. Check your QueryInterface
implementation, make sure you are actually answering positively to
requests for this interface.

IInternetSecurityManager is retrieved with
IServiceProvider::QueryService call. You say QueryService does get
called - so just implement it appropriately.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
 
No, that quite specifically isn't happening. Only one member of
IDocHostUIHandler2 gets called (the non-inherited member). Implement
IDocHostUIHandler in exactly the same way and nothing in it gets called.
Those interfaces do not get requested by WebBrowserSite.QueryService().

I don't have or expect to have an implementation of QueryInterface. I assume
the CCW looks after that.

I've got code for doing this in C++, and in C# with managed axWebBrowser in
Framework 1.1. I'm just trying to get WebBrowserSite to do something useful
in Framework 2.0. One small piece of sample code doing something useful
would most likely solve my problem.

Any links, samples, suggestions?

DavidB
 
DavidB said:
No, that quite specifically isn't happening. Only one member of
IDocHostUIHandler2 gets called (the non-inherited member). Implement
IDocHostUIHandler in exactly the same way and nothing in it gets
called. Those interfaces do not get requested by
WebBrowserSite.QueryService().
I don't have or expect to have an implementation of QueryInterface. I
assume the CCW looks after that.

I have no idea what CCW is.
I've got code for doing this in C++, and in C# with managed
axWebBrowser in Framework 1.1. I'm just trying to get WebBrowserSite
to do something useful in Framework 2.0.

Ah. I don't use .NET and know very little about it. Sorry for wasting
your time. Hopefully somebody more knowledgeable in .NET interop will
pick up from here.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
 
David,

The CCW does take care of the QueryInterface call, but if your
IDocHostUIHandler is not getting called, I am suspicious of how you have it
defined. Verify that the GUID attribute on the interface definition is
correct and that the interface is COM visible. If you like, post it here
and I'll take a look.
 
Colin Neller said:
David,

The CCW does take care of the QueryInterface call, but if your
IDocHostUIHandler is not getting called, I am suspicious of how you have
it defined. Verify that the GUID attribute on the interface definition is
correct and that the interface is COM visible. If you like, post it here
and I'll take a look.

The interface is as correct as I can get it. I tried emorcillo olelib,
pinvoke.net and manual.

The interface is implemented on class ExtWebBrowserSite :
WebBrowser.WebBrowserSite, which is the way I read the docs. I assume this
class cannot be made COM visible, since it inherits from a protected class,
but doesn't need to be.

I implemented IDocHostUIHandler, IDocHostUIHandler2 and IServiceProvider on
this class (see code). Of these, only IDocHostUIHandler2.GetOverrideKeyPath
and IServiceProvider.QueryService get called.

IServiceProvider.QueryService gets called for many SIDs including
ISecurityManager but not including IDocHostUIHandler or IDocHostUIHandler2.
Without this, I don't see how I can implement IDocHostUIHandler on a
different class.

But there are probably many things I don't understand. Any help much
appreciated. Sample code would be even better.

[BTW thanks for the link on your blog. I've seen that C# code for NewWindow3
mentioned before, but not been able to find it.]

DavidB

------------ code starts here (long) -------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Diagnostics;

namespace WebGetWebControl {

/// <summary>
/// Implement class to extend the Web Browser
/// </summary>
public class ExtWebBrowser : WebBrowser
{

////////////////////////////////////////////////////////////////
/// <summary>
/// Implement class that allows ActiveX control to retrieve
extensibility interfaces
/// </summary>
class ExtWebBrowserSite : WebBrowser.WebBrowserSite
, olelib.IServiceProvider
, olelib.IDocHostUIHandler
, olelib.IDocHostUIHandler2
{
WebBrowser _host;
public ExtWebBrowserSite(WebBrowser host)
: base(host) {
_host = host;
Debug.WriteLine(String.Format("ExWBSite ctor {0}", host));
}

#region IDocHostUIHandler Members

void olelib.IDocHostUIHandler.EnableModeless(int fEnable) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 0));
throw new Exception("The method or operation is not
implemented.");
}

olelib.IDataObject
olelib.IDocHostUIHandler.FilterDataObject(olelib.IDataObject pDO) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 1));
throw new Exception("The method or operation is not
implemented.");
}

olelib.IDropTarget
olelib.IDocHostUIHandler.GetDropTarget(olelib.IDropTarget pDropTarget) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 2));
throw new Exception("The method or operation is not
implemented.");
}

object olelib.IDocHostUIHandler.GetExternal() {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 3));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.GetHostInfo(ref
olelib.DOCHOSTUIINFO pInfo) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 4));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.GetOptionKeyPath(ref int
pOLESTRchKey, int dw) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 5));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.HideUI() {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 6));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.OnDocWindowActivate(int fActivate)
{
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 7));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.OnFrameWindowActivate(int
fActivate) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 8));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.ResizeBorder(ref olelib.RECT
prcBorder, olelib.IOleInPlaceUIWindow pUIWindow, int fRameWindow) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 9));
throw new Exception("The method or operation is not
implemented.");
}

void
olelib.IDocHostUIHandler.ShowContextMenu(olelib.ContextMenuTarget dwContext,
ref olelib.POINT pPOINT, olelib.IOleCommandTarget pCommandTarget, object
HTMLTagElement) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 10));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.ShowUI(int dwID,
olelib.IOleInPlaceActiveObject pActiveObject, olelib.IOleCommandTarget
pCommandTarget, olelib.IOleInPlaceFrame pFrame, olelib.IOleInPlaceUIWindow
pDoc) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 11));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.TranslateAccelerator(ref
olelib.MSG lpmsg, ref olelib.UUID pguidCmdGroup, int nCmdID) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 12));
throw new Exception("The method or operation is not
implemented.");
}

int olelib.IDocHostUIHandler.TranslateUrl(int dwTranslate, int
pchURLIn) {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 13));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler.UpdateUI() {
Debug.WriteLine(String.Format("IDocHostUIHandler {0}", 14));
throw new Exception("The method or operation is not
implemented.");
}

#endregion

#region IDocHostUIHandler2 Members

void olelib.IDocHostUIHandler2.EnableModeless(int fEnable) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 0));
throw new Exception("The method or operation is not
implemented.");
}

olelib.IDataObject
olelib.IDocHostUIHandler2.FilterDataObject(olelib.IDataObject pDO) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 1));
throw new Exception("The method or operation is not
implemented.");
}

olelib.IDropTarget
olelib.IDocHostUIHandler2.GetDropTarget(olelib.IDropTarget pDropTarget) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 2));
throw new Exception("The method or operation is not
implemented.");
}

object olelib.IDocHostUIHandler2.GetExternal() {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 3));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.GetHostInfo(ref
olelib.DOCHOSTUIINFO pInfo) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 4));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.GetOptionKeyPath(ref int
pOLESTRchKey, int dw) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 5));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.GetOverrideKeyPath(ref int
pchKey, int dw) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 6));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.HideUI() {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 7));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.OnDocWindowActivate(int
fActivate) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 8));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.OnFrameWindowActivate(int
fActivate) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 8));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.ResizeBorder(ref olelib.RECT
prcBorder, olelib.IOleInPlaceUIWindow pUIWindow, int fRameWindow) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 8));
throw new Exception("The method or operation is not
implemented.");
}

void
olelib.IDocHostUIHandler2.ShowContextMenu(olelib.ContextMenuTarget
dwContext, ref olelib.POINT pPOINT, olelib.IOleCommandTarget pCommandTarget,
object HTMLTagElement) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}", 9));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.ShowUI(int dwID,
olelib.IOleInPlaceActiveObject pActiveObject, olelib.IOleCommandTarget
pCommandTarget, olelib.IOleInPlaceFrame pFrame, olelib.IOleInPlaceUIWindow
pDoc) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}",
10));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.TranslateAccelerator(ref
olelib.MSG lpmsg, ref olelib.UUID pguidCmdGroup, int nCmdID) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}",
11));
throw new Exception("The method or operation is not
implemented.");
}

int olelib.IDocHostUIHandler2.TranslateUrl(int dwTranslate, int
pchURLIn) {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}",
12));
throw new Exception("The method or operation is not
implemented.");
}

void olelib.IDocHostUIHandler2.UpdateUI() {
Debug.WriteLine(String.Format("IDocHostUIHandler2 {0}",
13));
throw new Exception("The method or operation is not
implemented.");
}

#endregion

#region IServiceProvider Members

void olelib.IServiceProvider.QueryService(ref olelib.UUID
guidService, ref olelib.UUID riid, IntPtr ppvObject) {
Debug.WriteLine(String.Format("IServiceProvider {0}",
guidService));
throw new Exception("The method or operation is not
implemented.");
}

#endregion
}

//--------------------------------------------------------------
// Override method to tell ActiveX host where to find extensibility
interfaces
//
protected override WebBrowserSiteBase CreateWebBrowserSiteBase() {
return new ExtWebBrowserSite(this);
}

public void Test() {
}
}
}
 
Verify that the GUID attribute on the interface definition is correct and
The interface is implemented on class ExtWebBrowserSite :
WebBrowser.WebBrowserSite, which is the way I read the docs. I assume this
class cannot be made COM visible, since it inherits from a protected
class, but doesn't need to be.

The _interface_ definition needs to be COM visible, not necessarily the
class implementing it. Please post your interface definition for
IDocHostUIHandler.

IServiceProvider.QueryService gets called for many SIDs including
ISecurityManager but not including IDocHostUIHandler or
IDocHostUIHandler2. Without this, I don't see how I can implement
IDocHostUIHandler on a different class.

IDocHostUIHandler and IDocHostUIHandler2 both are queried through
QueryInterface, not QueryService. The behavior you are seeing is the
correct one. You were right to implement IDocHostUIHandler,
IDocHostUIHandler2, and IServiceProvider in the same class.

[BTW thanks for the link on your blog. I've seen that C# code for
NewWindow3 mentioned before, but not been able to find it.]

No problem, but do keep in mind that NewWindow3 is only supported on Windows
XP SP2 and later.
 
The _interface_ definition needs to be COM visible, not necessarily the
class implementing it. Please post your interface definition for
IDocHostUIHandler.

I didn't know that. The documentation says [ComVisible] is true by default;
nothing I can find anywhere about making interfaces ComVisible; I've
implemented other classes and never found any use for [ComVisible]. How
about that. Where do you put it?

Here it is -- exactly as imported from a type library intended for VB.

///////////////////////////////////////////////////
using System;
using System.Runtime.InteropServices;

namespace olelib {
[InterfaceType(1)]
[Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A")]
public interface IDocHostUIHandler {
void EnableModeless(int fEnable);
IDataObject FilterDataObject(IDataObject pDO);
IDropTarget GetDropTarget(IDropTarget pDropTarget);
object GetExternal();
void GetHostInfo(ref DOCHOSTUIINFO pInfo);
void GetOptionKeyPath(ref int pOLESTRchKey, int dw);
void HideUI();
void OnDocWindowActivate(int fActivate);
void OnFrameWindowActivate(int fActivate);
void ResizeBorder(ref RECT prcBorder, IOleInPlaceUIWindow pUIWindow,
int fRameWindow);
void ShowContextMenu(ContextMenuTarget dwContext, ref POINT pPOINT,
IOleCommandTarget pCommandTarget, object HTMLTagElement);
void ShowUI(int dwID, IOleInPlaceActiveObject pActiveObject,
IOleCommandTarget pCommandTarget, IOleInPlaceFrame pFrame,
IOleInPlaceUIWindow pDoc);
void TranslateAccelerator(ref MSG lpmsg, ref UUID pguidCmdGroup, int
nCmdID);
int TranslateUrl(int dwTranslate, int pchURLIn);
void UpdateUI();
}
}
/////////////////////////////////////////////////////
No problem, but do keep in mind that NewWindow3 is only supported on
Windows XP SP2 and later.

Not a problem. It's in-house code, so that's not an issue.

All hints gratefully accepted.

DavidB
 
The _interface_ definition needs to be COM visible, not necessarily the
I didn't know that. The documentation says [ComVisible] is true by
default; nothing I can find anywhere about making interfaces ComVisible;
I've implemented other classes and never found any use for [ComVisible].
How about that. Where do you put it?

I am not absolutely sure about the COM visibility attribute, but it doesn't
hurt. Some examples I have seen have it defined explicitly. You are
correct that it is true by default (unless you have set it false at the
assembly or super-class level), so I doubt it is the problem in your case.

After having reviewed your interface, I noticed that the methods are defined
in alphabetical order. Since this is an IUnknown (not IDispatch) inteface,
the order of the methods must be in the correct order for VTable lookup.
Below is a definition that has the correct order, and I have used it
successfully before (from
http://www.codeproject.com/cs/miscctrl/WebBrowserEx.asp). Also notice the
ComImport attribute... honestly, I don't fully understand what it does
(anyone else care to comment?), but it may be necessary.

--- code ---

[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[GuidAttribute("bd3f23c0-d43e-11cf-893b-00aa00bdce1a")]
internal interface IDocHostUIHandler
{
[PreserveSig]
uint ShowContextMenu(uint dwID, ref tagPOINT ppt,
[MarshalAs(UnmanagedType.IUnknown)] object pcmdtReserved,
[MarshalAs(UnmanagedType.IDispatch)] object pdispReserved);

void GetHostInfo(ref DOCHOSTUIINFO pInfo);
void ShowUI(uint dwID, ref object pActiveObject, ref object
pCommandTarget, ref object pFrame, ref object pDoc);
void HideUI();
void UpdateUI();
void EnableModeless(int fEnable);
void OnDocWindowActivate(int fActivate);
void OnFrameWindowActivate(int fActivate);
void ResizeBorder(ref tagRECT prcBorder, int pUIWindow, int fRameWindow);

[PreserveSig]
uint TranslateAccelerator(ref tagMSG lpMsg, ref Guid pguidCmdGroup, uint
nCmdID);

void GetOptionKeyPath([MarshalAs(UnmanagedType.BStr)] ref string pchKey,
uint dw);
object GetDropTarget(ref object pDropTarget);

[PreserveSig]
int GetExternal([MarshalAs(UnmanagedType.IDispatch)] out object
ppDispatch);

[PreserveSig]
uint TranslateUrl(uint dwTranslate,
[MarshalAs(UnmanagedType.BStr)] string pchURLIn,
[MarshalAs(UnmanagedType.BStr)] ref string ppchURLOut);

IDataObject FilterDataObject(IDataObject pDO);
}
 
Here is my (working) hint:

1.) Create an own class, derive that class solely from
IDocHostUIHandler:

private class MyDocHostUIHandler :
UnsafeNativeMethods.IDocHostUIHandler
{
....
}

2.) introduce the interface definition of ICustomDoc. E.g. like the
following:

[ComImport(), InterfaceType( ComInterfaceType.InterfaceIsIUnknown ),
GuidAttribute( "3050f3f0-98b5-11cf-bb82-00aa00bdce0b" )]
internal interface ICustomDoc
{
[PreserveSig]
void SetUIHandler( IDocHostUIHandler pUIHandler );
}

3.) Call that interface's member:

private MyDocHostUIHandler docHostUIHandler = null;

protected override void OnDocumentCompleted(
WebBrowserDocumentCompletedEventArgs e )
{
if ( docHostUIHandler == null )
{
docHostUIHandler = new MyDocHostUIHandler( this );

((ICustomDoc)Document.DomDocument).SetUIHandler(
docHostUIHandler );
}

base.OnDocumentCompleted( e );
}

4.) Be happy :-)

Best regards
Uwe (http://www.magerquark.com)
 
Thanks, Collin.

The (sorted) interface definition I gave you was generated by the COM import
functionality. The real interface is defined in IDL, and does appear to be
in the correct order. Even so, I tried your definition and it made no
difference.

Unless a Microsoftie is prepared to let us all into the secret, I'm going to
have to write this one off as: Nice idea, no cigar.

DavidB

Colin Neller said:
I didn't know that. The documentation says [ComVisible] is true by
default; nothing I can find anywhere about making interfaces ComVisible;
I've implemented other classes and never found any use for [ComVisible].
How about that. Where do you put it?

I am not absolutely sure about the COM visibility attribute, but it
doesn't hurt. Some examples I have seen have it defined explicitly. You
are correct that it is true by default (unless you have set it false at
the assembly or super-class level), so I doubt it is the problem in your
case.

After having reviewed your interface, I noticed that the methods are
defined in alphabetical order. Since this is an IUnknown (not IDispatch)
inteface, the order of the methods must be in the correct order for VTable
lookup. Below is a definition that has the correct order, and I have used
it successfully before (from
http://www.codeproject.com/cs/miscctrl/WebBrowserEx.asp). Also notice the
ComImport attribute... honestly, I don't fully understand what it does
(anyone else care to comment?), but it may be necessary.

--- code ---

[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[GuidAttribute("bd3f23c0-d43e-11cf-893b-00aa00bdce1a")]
internal interface IDocHostUIHandler
{
[PreserveSig]
uint ShowContextMenu(uint dwID, ref tagPOINT ppt,
[MarshalAs(UnmanagedType.IUnknown)] object pcmdtReserved,
[MarshalAs(UnmanagedType.IDispatch)] object pdispReserved);

void GetHostInfo(ref DOCHOSTUIINFO pInfo);
void ShowUI(uint dwID, ref object pActiveObject, ref object
pCommandTarget, ref object pFrame, ref object pDoc);
void HideUI();
void UpdateUI();
void EnableModeless(int fEnable);
void OnDocWindowActivate(int fActivate);
void OnFrameWindowActivate(int fActivate);
void ResizeBorder(ref tagRECT prcBorder, int pUIWindow, int fRameWindow);

[PreserveSig]
uint TranslateAccelerator(ref tagMSG lpMsg, ref Guid pguidCmdGroup, uint
nCmdID);

void GetOptionKeyPath([MarshalAs(UnmanagedType.BStr)] ref string pchKey,
uint dw);
object GetDropTarget(ref object pDropTarget);

[PreserveSig]
int GetExternal([MarshalAs(UnmanagedType.IDispatch)] out object
ppDispatch);

[PreserveSig]
uint TranslateUrl(uint dwTranslate,
[MarshalAs(UnmanagedType.BStr)] string pchURLIn,
[MarshalAs(UnmanagedType.BStr)] ref string ppchURLOut);

IDataObject FilterDataObject(IDataObject pDO);
}
 
Thanks, Uwe.
I expect that will work. My purpose was to find out whether the .NET 2.0
code could be made to work -- no joy on that so far!
DavidB
 
Have you not been able to use the working sample I posted?

Charles


DavidB said:
Thanks, Collin.

The (sorted) interface definition I gave you was generated by the COM
import functionality. The real interface is defined in IDL, and does
appear to be in the correct order. Even so, I tried your definition and it
made no difference.

Unless a Microsoftie is prepared to let us all into the secret, I'm going
to have to write this one off as: Nice idea, no cigar.

DavidB

Colin Neller said:
The _interface_ definition needs to be COM visible, not necessarily the
class implementing it. Please post your interface definition for
IDocHostUIHandler.
I didn't know that. The documentation says [ComVisible] is true by
default; nothing I can find anywhere about making interfaces ComVisible;
I've implemented other classes and never found any use for [ComVisible].
How about that. Where do you put it?

I am not absolutely sure about the COM visibility attribute, but it
doesn't hurt. Some examples I have seen have it defined explicitly. You
are correct that it is true by default (unless you have set it false at
the assembly or super-class level), so I doubt it is the problem in your
case.

After having reviewed your interface, I noticed that the methods are
defined in alphabetical order. Since this is an IUnknown (not IDispatch)
inteface, the order of the methods must be in the correct order for
VTable lookup. Below is a definition that has the correct order, and I
have used it successfully before (from
http://www.codeproject.com/cs/miscctrl/WebBrowserEx.asp). Also notice
the ComImport attribute... honestly, I don't fully understand what it
does (anyone else care to comment?), but it may be necessary.

--- code ---

[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[GuidAttribute("bd3f23c0-d43e-11cf-893b-00aa00bdce1a")]
internal interface IDocHostUIHandler
{
[PreserveSig]
uint ShowContextMenu(uint dwID, ref tagPOINT ppt,
[MarshalAs(UnmanagedType.IUnknown)] object pcmdtReserved,
[MarshalAs(UnmanagedType.IDispatch)] object pdispReserved);

void GetHostInfo(ref DOCHOSTUIINFO pInfo);
void ShowUI(uint dwID, ref object pActiveObject, ref object
pCommandTarget, ref object pFrame, ref object pDoc);
void HideUI();
void UpdateUI();
void EnableModeless(int fEnable);
void OnDocWindowActivate(int fActivate);
void OnFrameWindowActivate(int fActivate);
void ResizeBorder(ref tagRECT prcBorder, int pUIWindow, int
fRameWindow);

[PreserveSig]
uint TranslateAccelerator(ref tagMSG lpMsg, ref Guid pguidCmdGroup, uint
nCmdID);

void GetOptionKeyPath([MarshalAs(UnmanagedType.BStr)] ref string pchKey,
uint dw);
object GetDropTarget(ref object pDropTarget);

[PreserveSig]
int GetExternal([MarshalAs(UnmanagedType.IDispatch)] out object
ppDispatch);

[PreserveSig]
uint TranslateUrl(uint dwTranslate,
[MarshalAs(UnmanagedType.BStr)] string pchURLIn,
[MarshalAs(UnmanagedType.BStr)] ref string ppchURLOut);

IDataObject FilterDataObject(IDataObject pDO);
}
 
Hello, DavidB!
You wrote on Sun, 19 Mar 2006 13:16:55 GMT:


??>> if ( docHostUIHandler == null )
??>> {
??>> docHostUIHandler = new MyDocHostUIHandler( this );
??>>
??>> ((ICustomDoc)Document.DomDocument).SetUIHandler(
??>> docHostUIHandler );
??>> }

This approach (reassigning UI Handler later) is good for most cases, but
there is one issue that SetUIHandler() can be called only after first
Navigate(), so:
1. IDocHostUIHandler.GetOptionKeyPath() is not called (method of default
WebBrowserSite is already called when initializing WebBrowser), so you can't
set for your component to use custom path in registry to read settings and
though can't do some customizations without affecting whole system (for
example, "Disable script errors" flag can be modified only via this registry
setting)

2. First Navigate() goes using WebBrowserSite's IDocHostUIHandler
implementation, so if you change look(&feel) of component, you'll receive
visual glitches on this first.

BTW, FYI
http://lab.msdn.microsoft.com/produ...edbackid=e2405bec-e366-4081-ac62-ee569032a7cd

that's about IDocHostUIHandler's bug at all
 
Back
Top