DavidB
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
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
"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:O3nweRER...@TK2MSFTNGP10.phx.gbl...
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.
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
http://www.colinneller.com/blog
"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:%239SBCvJ...@TK2MSFTNGP12.phx.gbl...
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() {
> 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
> 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);
}
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)
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" <cne...@gmail.com> wrote in message
news:e2%23kp9QS...@TK2MSFTNGP09.phx.gbl...
<uwe....@gmail.com> wrote in message
news:1142571480.2...@j52g2000cwj.googlegroups.com...
Charles
"DavidB" <dav...@hurkle.nospam.com> wrote in message
news:YOcTf.10406$dy4....@news-server.bigpond.net.au...
??>> 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.
that's about IDocHostUIHandler's bug at all
--
With best regards, Alexander Ogol. E-mail: alex...@ogol.dp.ua