Click here to Skip to main content
15,914,111 members
Articles / Programming Languages / C#
Article

Using MSHTML Advanced Hosting Interfaces

Rate me:
Please Sign up or sign in to vote.
4.11/5 (29 votes)
25 Jun 20023 min read 613.1K   5.3K   146   106
This article shows you how to use the Advanced Hosting Interfaces such as IDocHostUIHandler

Overview

This article shows you how to use the MSHTML Advanced Hosting Interfaces, specifically IDocHostUIHandler, from .NET. These interfaces allow you very fine control over the user interface presented by the Microsoft Web Browser Control, for example, you can show your own context menu. I'll show you an easy way to use this interface without having to re-write the interface definitions yourself. As a bonus, I'll show you how to receive events from elements in the document.

The Problem

It is easy enough to put a web browser control on a form and get a fully-functional browser right away. But in your application, you might want finer control over how the control interacts with the user. For example, the standard IE context menu does not look particularly nice when you application shows an ultra-cool DHTML-based user interface. An interface called IDocHostUIHandler affords you this level of control.

Implementing IDocHostUIHandler

IDocHostUIHandler has to be implemented by your application. You can then use ICustomDoc::SetUIHandler to tell MSHTML that you have this interface.

IDocHostUIHandler is defined in MsHtmHst.idl in the Internet Development SDK, part of the Platform SDK. One approach I've seen is to do the import by hand - write the interface definition yourself in your source code.

The other approach, the one I'm going to use, is to create a type library with the interfaces we need declared in it, and then use the tlbimp tool to create an Interop assembly. No fiddling with marshalling yourself.

The first step would be to create an IDL file with the interfaces we need declared in it. You shall also need a UUID for the generated type library. There are only a few interfaces we need, and the entire IDL becomes:

MsHtmHstInterop.idl

MIDL
[
    uuid(47F05070-FD66-45cc-AD99-74260F94A16B)
]
library MsHtmHstInterop
{
    import "MsHtmHst.idl";
    
    enum tagDOCHOSTUIDBLCLK;
    enum tagDOCHOSTUIFLAG;
    enum tagDOCHOSTUITYPE;
    
    interface ICustomDoc;
    interface IDocHostShowUI;
    interface IDocHostUIHandler;
    interface IDocHostUIHandler2;
    interface IHostDialogHelper;
};

I've included all the Advanced Hosting interfaces and enumerations here.

The next step is to generate the type library. Just compile the IDL file to get a TLB, using the Platform SDK tool MIDL.

midl MsHtmHstInterop.idl /tlb bin\MsHtmHstInterop.tlb

Now we need an interop assembly. We just have to use tlbimp on the newly created TLB file:

tlbimp bin\MsHtmHstInterop.tlb /out:bin\MsHtmHstInterop.dll

Now we can use the interfaces we need with just a using statement in our C# code:

HtmlUI.cs (partial)

C#
using MsHtmHstInterop;

Wiring up

For the sample application, I have put just a single web browser control on a form. The form class implements IDocHostUIHandler.

To hook up the interface to MSHTML, we first need to get the ICustomDoc interface, and then call the SetUIHandler method with our interface as an argument.

HtmlUI.cs (partial - HtmlUIForm constructor)

C#
public HtmlUIForm()
{
    InitializeComponent();
            
    this.WebBrowser.DocumentComplete += 
          new DWebBrowserEvents2_DocumentCompleteEventHandler(this.WebBrowser_DocumentComplete);
            
    object flags = 0;
    object targetFrame = String.Empty;
    object postData = String.Empty;
    object headers = String.Empty;
    this.WebBrowser.Navigate("about:blank", ref flags, ref targetFrame, 
                             ref postData, ref headers);
            
    ICustomDoc cDoc = (ICustomDoc)this.WebBrowser.Document;
    cDoc.SetUIHandler((IDocHostUIHandler)this);
            
    this.WebBrowser.Navigate(@"res://HtmlUI.exe/Sample1.htm", ref flags, ref targetFrame, 
                             ref postData, ref headers);
}

That's all there is to it. Of course, the form class implements the IDocHostUIHandler member functions.

HTML files in resources

You'll notice that I've used the res: protocol in my code. This is a neat way to package your HTML files and other support files - they're in the EXE itself. There are several advantages to this approach: your users cannot easily change the application's user interface, and you don't have to bother with packing more files into your install package.

You just have to make an RC file defining the resource:

HtmlUI.rc

Sample1.htm HTML "Sample1.htm"

This can then be compiled to get a RES file. You can add the RES file to your assembly with the /win32res C# compiler switch.

Handling Document Events

If your application has a DHTML-based user interface, you would definitely need to catch events from elements on the page in order to make it functional. If you run the sample app, you can see that clicking the button on the page shows you a message box. This message box has been invoked from the C# app, not from any scripts on the page. Here's the code:

HtmlUI.cs (partial)

C#
private void WebBrowser_DocumentComplete(object sender, 
                                    AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
{
    // Get the document.
    IHTMLDocument2 doc = (IHTMLDocument2)this.WebBrowser.Document;
    
    // Get a reference to the button.
    HTMLButtonElement button = (HTMLButtonElement)doc.all.item("theButton", null);
    
    // Attach the event handler with the events interface.
    ((HTMLButtonElementEvents2_Event)button).onclick += 
                   new HTMLButtonElementEvents2_onclickEventHandler(this.Button_onclick);
}
        
private bool Button_onclick(IHTMLEventObj e)
{
    MessageBox.Show("Alert from the app: Received theButton.onclick!");
    return true;
}

Building the app

I have included a makefile which you can use to build from the command prompt. Just use nmake all to build the app. Note that the tlbimp mshtml.tlb step takes a while.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
President NikSci
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: What about window.external? Pin
Brett Morien5-Aug-02 19:29
sussBrett Morien5-Aug-02 19:29 
QuestionHow to listen to mouse clicks as well as show customized context menu Pin
Member 826014-Aug-02 15:58
Member 826014-Aug-02 15:58 
AnswerRe: How to listen to mouse clicks as well as show customized context menu Pin
Member 826015-Aug-02 5:13
Member 826015-Aug-02 5:13 
GeneralUsing IHTMLEditHost Pin
Niels Gebauer23-Jul-02 15:54
sussNiels Gebauer23-Jul-02 15:54 
GeneralRe: Using IHTMLEditHost Pin
Nikhil Dabas28-Jul-02 8:53
Nikhil Dabas28-Jul-02 8:53 
GeneralRe: Using IHTMLEditHost Pin
NIels Gebauer29-Jul-02 17:56
sussNIels Gebauer29-Jul-02 17:56 
GeneralRe: Using IHTMLEditHost Pin
Nikhil Dabas3-Aug-02 22:46
Nikhil Dabas3-Aug-02 22:46 
GeneralVB .Net Pin
1-Jul-02 15:24
suss1-Jul-02 15:24 
I tried to convert this code to VB.Net but it doesn't seem to be working. The application won't pick up the Button Clicked Events. I have an html file called start.htm with two buttons... Open FileNew File. I'm not sure exactly what is wrong but here is my code.

Imports MsHtmHstInterop
Imports MSHTML
Imports AxSHDocVw

Public Class frmChild
Inherits System.Windows.Forms.Form
Implements IDocHostUIHandler


'Windows Form Designer generated code, including protected webStart as AxWebBrowser

Protected Sub InitializeBrowsers()
Dim o As Object
Dim theLoc As String = Application.StartupPath
webStart.Navigate("about:blank", o, o, o, o)

Dim cDoc As ICustomDoc = CType(webStart.Document, ICustomDoc)
cDoc.SetUIHandler(CType(Me, IDocHostUIHandler))

webStart.Navigate(theLoc & "\html\start.htm", o, o, o)
End Sub

Private Sub WebBrowser_DocumentComplete(ByVal sender As Object, _
ByVal e As AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent) _
Handles webStart.DocumentComplete
' Get the document
Dim doc As IHTMLDocument2 = CType(webStart.Document, IHTMLDocument2)
' Get references to the buttons
Dim btnOpen As HTMLButtonElement = CType(doc.all.item("btnOpen", Nothing), HTMLButtonElement)
Dim btnNew As HTMLButtonElement = CType(doc.all.item("btnNew", Nothing), HTMLButtonElement)
' Attach the event handlers with the events interface
AddHandler CType(btnOpen, HTMLButtonElementEvents2_Event).onclick, _
New HTMLButtonElementEvents2_onclickEventHandler(AddressOf Me.ButtonOpen_onclick)
AddHandler CType(btnNew, HTMLButtonElementEvents2_Event).onclick, _
New HTMLButtonElementEvents2_onclickEventHandler(AddressOf Me.ButtonNew_onclick)
End Sub

Private Function ButtonOpen_onclick(ByVal e As IHTMLEventObj) As Boolean
MsgBox("Alert from the app: Received HTMLElement btnOpen.onclick Event!")
Return True
End Function

Private Function ButtonNew_onclick(ByVal e As IHTMLEventObj) As Boolean
MsgBox("Alert from the app: Received HTMLElement btnNew.onclick Event!")
Return True
End Function

'''''''''''''''''''''''''''''''''''''
' IDocHostUIHandler implementation '
'''''''''''''''''''''''''''''''''''''

Sub EnableModeless(ByVal fEnable As Integer) _
Implements IDocHostUIHandler.EnableModeless
End Sub

'ppDORet out
Sub FilterDataObject(ByVal pDO As MsHtmHstInterop.IDataObject, ByRef ppDORet As MsHtmHstInterop.IDataObject) _
Implements IDocHostUIHandler.FilterDataObject
ppDORet = Nothing
End Sub

'ppDropTarget out
Sub GetDropTarget(ByVal pDropTarget As IDropTarget, ByRef ppDropTarget As IDropTarget) _
Implements IDocHostUIHandler.GetDropTarget
ppDropTarget = Nothing
End Sub

'ppDispatch out
Sub GetExternal(ByRef ppDispatch As Object) _
Implements IDocHostUIHandler.GetExternal
ppDispatch = Nothing
End Sub

Sub GetHostInfo(ByRef pInfo As _DOCHOSTUIINFO) _
Implements IDocHostUIHandler.GetHostInfo
End Sub

'pchKey out
Sub GetOptionKeyPath(ByRef pchKey As String, ByVal dw As UInt32) _
Implements IDocHostUIHandler.GetOptionKeyPath
pchKey = Nothing
End Sub

Sub HideUI() _
Implements IDocHostUIHandler.HideUI
End Sub

Sub OnDocWindowActivate(ByVal fActivate As Integer) _
Implements IDocHostUIHandler.OnDocWindowActivate
End Sub

Sub OnFrameWindowActivate(ByVal fActivate As Integer) _
Implements IDocHostUIHandler.OnFrameWindowActivate
End Sub

Sub ResizeBorder(ByRef prcBorder As MsHtmHstInterop.tagRECT, ByVal pUIWindow As IOleInPlaceUIWindow, _
ByVal fRameWindow As Integer) _
Implements IDocHostUIHandler.ResizeBorder
End Sub

Sub ShowContextMenu(ByVal dwID As UInt32, ByRef ppt As MsHtmHstInterop.tagPOINT, _
ByVal pcmdtReserved As Object, ByVal pdispReserved As Object) _
Implements IDocHostUIHandler.ShowContextMenu
End Sub

Sub ShowUI(ByVal dwID As UInt32, ByVal pActiveObject As IOleInPlaceActiveObject, _
ByVal pCommandTarget As IOleCommandTarget, ByVal pFrame As IOleInPlaceFrame, _
ByVal pDoc As IOleInPlaceUIWindow) _
Implements IDocHostUIHandler.ShowUI
End Sub

Sub TranslateAccelerator(ByRef lpmsg As tagMSG, ByRef pguidCmdGroup As Guid, ByVal nCmdID As UInt32) _
Implements IDocHostUIHandler.TranslateAccelerator
End Sub

Sub TranslateUrl(ByVal dwTranslate As UInt32, ByRef pchURLIn As UInt16, _
ByVal ppchURLOut As IntPtr) _
Implements IDocHostUIHandler.TranslateUrl
End Sub

Sub UpdateUI() _
Implements IDocHostUIHandler.UpdateUI
End Sub

Thanks
GeneralRe: VB .Net Pin
Nikhil Dabas2-Jul-02 10:46
Nikhil Dabas2-Jul-02 10:46 
GeneralRe: VB .Net Pin
Gene Sivorot28-Jul-02 20:23
Gene Sivorot28-Jul-02 20:23 
GeneralDownload Dialog Box Pin
29-Jun-02 6:28
suss29-Jun-02 6:28 
GeneralRe: Download Dialog Box Pin
Nikhil Dabas29-Jun-02 9:38
Nikhil Dabas29-Jun-02 9:38 
GeneralRe: Download Dialog Box Pin
Gene Sivorot30-Jul-02 13:05
Gene Sivorot30-Jul-02 13:05 
Generalgreat work, Nikhil Pin
28-Jun-02 16:52
suss28-Jun-02 16:52 
GeneralReturn value from TranslateAccelerator Pin
27-Jun-02 17:20
suss27-Jun-02 17:20 
GeneralRe: Return value from TranslateAccelerator Pin
Nikhil Dabas28-Jun-02 1:47
Nikhil Dabas28-Jun-02 1:47 
GeneralRe: Return value from TranslateAccelerator Pin
Fred Heida30-Jun-02 11:50
Fred Heida30-Jun-02 11:50 
GeneralRe: Return value from TranslateAccelerator Pin
Nikhil Dabas2-Jul-02 9:43
Nikhil Dabas2-Jul-02 9:43 
GeneralRe: Return value from TranslateAccelerator Pin
Nikhil Dabas2-Jul-02 10:39
Nikhil Dabas2-Jul-02 10:39 
GeneralRe: Return value from TranslateAccelerator Pin
Fred Heida2-Jul-02 11:07
Fred Heida2-Jul-02 11:07 
GeneralThank You, Thank You, Thank You Pin
26-Jun-02 11:03
suss26-Jun-02 11:03 
GeneralNice work Nikhil Pin
Nish Nishant25-Jun-02 23:42
sitebuilderNish Nishant25-Jun-02 23:42 
GeneralRe: Nice work Nikhil Pin
Nikhil Dabas26-Jun-02 1:08
Nikhil Dabas26-Jun-02 1:08 
GeneralRe: Nice work Nikhil Pin
26-Jun-02 6:25
suss26-Jun-02 6:25 
GeneralRe: Nice work Nikhil Pin
Nikhil Dabas26-Jun-02 9:08
Nikhil Dabas26-Jun-02 9:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.