IDocHostUIHandler Extended CHtmlView | CodeGuru

IDocHostUIHandler Extended CHtmlView

I recently wanted to exploit the features of Internet Explorer to prevent users from selecting text in my CHtmlView. The current implementation does not support a simple way to do this (such as an EnableTextSelection function call), so I decided to investigate. Here are some of the ‘hidden’ features I want to expose… There is […]

Written By
CodeGuru Staff
CodeGuru Staff
Jul 29, 1999
3 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

I recently wanted to exploit the features of Internet Explorer to prevent users from selecting
text in my CHtmlView. The current implementation does not support a simple way to do this
(such as an EnableTextSelection function call), so I decided to investigate.

Here are some of the ‘hidden’ features I want to expose…

There is a Microsoft example called ‘Driller’ which is the basis of a solution, but the problem
is that it was written before the introduction of CHtmlView, so I began to enhance it.

What we need to do

The functionality we want is part of the IDocHostUIHandler interface. Therefore, we need to
find a way of replacing it with our own version. We do this by replacing the ActiveX control
container.

Step 1: Creating the container

We need to create two classes: one derived from COleControlSite, the other from COccManager.

Here is a rough outline of the format for ROleControlSite.h…

#include <mshtmhst.h>
class ROleControlSite : public COleControlSite
{
public:
	ROleControlSite(COleControlContainer *pCnt = NULL):COleControlSite(pCnt) {}
protected:
DECLARE_INTERFACE_MAP();
BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)
// interface functions here
END_INTERFACE_PART(DocHostUIHandler)
BEGIN_INTERFACE_PART(DocHostShowUI, IDocHostShowUI)
// interface functions here
END_INTERFACE_PART(DocHostShowUI)
};
class ROccManager : public COccManager
{
public:
	ROleControlSite *m_pROleControlSite;
	ROccManager() { m_pROleControlSite = NULL; }
	COleControlSite* CreateSite(COleControlContainer* pCtrlCont)
	{
		m_pROleControlSite = new ROleControlSite(pCtrlCont);
		return m_pROleControlSite;
	}
};

The functions for the interface are defined in ROleControlSite.cpp. This is where we tell
Internet Explorer the properties we want for the browser. It is very important that the
#include <../src/occimpl.h> is as written.

Here is a rough outline of the format for ROleControlSite.cpp…

#include “stdafx.h”
#undef AFX_DATA
#define AFX_DATA AFX_DATA_IMPORT
#include <..\src\occimpl.h>
#undef AFX_DATA
#define AFX_DATA AFX_DATA_EXPORT
#include “ROleControlSite.h”
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_INTERFACE_MAP(ROleControlSite, COleControlSite)
	INTERFACE_PART(ROleControlSite, IID_IDocHostUIHandler, DocHostUIHandler)
	INTERFACE_PART(ROleControlSite, IID_IDocHostShowUI, DocHostShowUI)
END_INTERFACE_MAP()
// implementation of the interface’s functions here
// …
Advertisement

Step 2: Using our container

When MFC creates a CHtmlView, it calls AfxEnableControlContainer(). This is the key to our
solution. If we pass our own container as a parameter, then it will use our interfaces that
we defined.

We add a new class derived from CHtmlView called RHtmlView. We then include the files
necessary to use our container in RHtmlView.cpp. All .cpp files which use RHtmlView must include
the following files, however the strict #include in ROleControlSite.cpp is not necessary here…

#include <..\src\occimpl.h>
#include “ROleControlSite.h

Next, we add a member variable to RHtmlView for the container…

ROccManager m_pROccManager;

In our RHtmlView class, we replace the Create function with this…

BOOL RHtmlView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
	const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
	///////////////////////////////////
	// The following does the same as MFC source, except that
	// AfxEnableControlContainer() is called with our handler.
	///////////////////////////////////
	CRect c_clientRect;
	GetClientRect(&c_clientRect);
	///////////////////////////////////
	// create the view window:
	m_pCreateContext = pContext;
	if (!CView::Create(lpszClassName, lpszWindowName, dwStyle, rect,
		pParentWnd,  nID, pContext))
	{
		return FALSE;
	}
	AfxEnableControlContainer(&m_pROccManager);
	///////////////////////////////////
	// create the control window:
	if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, lpszWindowName,
				WS_VISIBLE | WS_CHILD, c_clientRect, this, AFX_IDW_PANE_FIRST))
	{
		DestroyWindow();
		return FALSE;
	}
	LPUNKNOWN lpUnk = m_wndBrowser.GetControlUnknown();
	HRESULT hr = lpUnk->QueryInterface(IID_IWebBrowser2, (void**) &m_pBrowserApp);
	if (!SUCCEEDED(hr))
	{
		m_pBrowserApp = NULL;
		m_wndBrowser.DestroyWindow();
		DestroyWindow();
		return FALSE;
	}
	///////////////////////////////////
	// Our initialisation:
	SetWindowText(“RHtmlView”);
	SetClassLong(this->m_hWnd, GCL_STYLE, CS_DBLCLKS);
	///////////////////////////////////
	return TRUE;
}

At this point, we have a working RHtmlView which uses our IDocHostUIHandler code. Note the
use of SetClassLong in RHtmlView::Create to remove irritating flicker when resizing.

Step 3: Specifying our own properties

When a page is loaded, the GetHostInfo function is called. This is where we specify flags
for the user interface of the control. Flags are defined in the MSDN Visual Studio Reference.

I have added extra functions to ROleControlSite to allow storage of the flags. The following
is our definition of GetHostInfo…

// GetHostInfo
STDMETHODIMP ROleControlSite::XDocHostUIHandler::GetHostInfo(
		/* [i/o] */	DOCHOSTUIINFO __RPC_FAR *pInfo)
{
	METHOD_PROLOGUE(ROleControlSite, DocHostUIHandler)
	pInfo->cbSize = sizeof(DOCHOSTUIINFO);
	pInfo->dwFlags = pThis->GetXDocHostUI_Flag();
	pInfo->dwDoubleClick = pThis->GetXDocHostUI_DblClk();
	return S_OK;
}

For the context-menu flag, we have to add some extra code like so…

// ShowContextMenu
STDMETHODIMP ROleControlSite::XDocHostUIHandler::ShowContextMenu(
		/* [in ] */	DWORD dwID,
		/* [in ] */	POINT __RPC_FAR *ppt,
		/* [in ] */	IUnknown __RPC_FAR *pcmdtReserved,
		/* [in ] */	IDispatch __RPC_FAR *pdispReserved)
{
	METHOD_PROLOGUE(ROleControlSite, DocHostUIHandler)
	// Don’t show context menu
	if (pThis->GetXDocHostUI_Flag() & DOCHOSTUIFLAG_DISABLE_HELP_MENU) return S_OK;
	// Otherwise, show default
 	return S_FALSE;
}
Advertisement

Step 4: Usability

With the implementation so far, we must take complicated steps to change the flags from
outside of ROleControlSite.cpp. Therefore, much of this is dealt with by adding functions to
RHtmlView. Here is the complete list…

// XDocHostUI_DblClk interface
	DWORD GetXDocHostUI_DblClk();
	void SetXDocHostUI_DblClk(DWORD dwSet);
// XDocHostUI_Flag interface
	DWORD GetXDocHostUI_Flag();
	void SetXDocHostUI_Flag(DWORD dwSet);
	BOOL GetXDocHostUIFlag_Dialog();
	BOOL GetXDocHostUIFlag_DisableHelpMenu();
	BOOL GetXDocHostUIFlag_No3dBorder();
	BOOL GetXDocHostUIFlag_ScrollNo();
	BOOL GetXDocHostUIFlag_DisableScriptInactive();
	BOOL GetXDocHostUIFlag_OpenNewWin();
	BOOL GetXDocHostUIFlag_DisableOffscreen();
	BOOL GetXDocHostUIFlag_FlatScrollbar();
	BOOL GetXDocHostUIFlag_DivBlockDefault();
	BOOL GetXDocHostUIFlag_ActivateClienthitOnly();
	void SetXDocHostUIFlag_Dialog(BOOL bSet);
	void SetXDocHostUIFlag_DisableHelpMenu(BOOL bSet);
	void SetXDocHostUIFlag_No3dBorder(BOOL bSet);
	void SetXDocHostUIFlag_ScrollNo(BOOL bSet);
	void SetXDocHostUIFlag_DisableScriptInactive(BOOL bSet);
	void SetXDocHostUIFlag_OpenNewWin(BOOL bSet);
	void SetXDocHostUIFlag_DisableOffscreen(BOOL bSet);
	void SetXDocHostUIFlag_FlatScrollbar(BOOL bSet);
	void SetXDocHostUIFlag_DivBlockDefault(BOOL bSet);
	void SetXDocHostUIFlag_ActivateClienthitOnly(BOOL bSet);

An important issue to note is that we must call Navigate2 with the current location in order
to dynamically change the properties, otherwise we see no effect. Therefore, I also updated
some standard CHtmlView functions…

void RHtmlView::SetRegisterAsBrowser(BOOL bNewValue)
{
	CHtmlView::SetRegisterAsBrowser(bNewValue);
	Navigate2(GetLocationURL(), 0, NULL, NULL);
}
void RHtmlView::SetRegisterAsDropTarget(BOOL bNewValue)
{
	CHtmlView::SetRegisterAsDropTarget(bNewValue);
	Navigate2(GetLocationURL(), 0, NULL, NULL);
}
void RHtmlView::SetSilent(BOOL bNewValue)
{
	CHtmlView::SetSilent(bNewValue);
	Navigate2(GetLocationURL(), 0, NULL, NULL);
}
void RHtmlView::SetTheaterMode(BOOL bNewValue)
{
	CHtmlView::SetTheaterMode(bNewValue);
	Navigate2(GetLocationURL(), 0, NULL, NULL);
}

Step 5: Adding RHtmlView to a project

First of all, create a view derived from CHtmlView. You should edit the source files, replacing
all references of CHtmlView with RHtmlView.

Add the files RHtmlView.cpp, RHtmlView.h, ROleControlSite.cpp, and ROleControlSite.h to your
project.

In all files which #include your view’s header file, #include the following before the view’s
header file is #included…

#include <..\src\occimpl.h>
#include “ROleControlSite.h

You should now have the extra functionality. Note that all RHtmlView’s created can have different properties.

Possible Enhancements

  • Add functions to control downloading Images, Videos, and ActiveX controls. (the AtlBrowser
    sample does this)
  • Extend the DOM by implementing an IDispatch interface, and passing it in GetExternal.
  • Add the ability to stop the browser acting as a drag+drop server.
Advertisement

Download

Download demo project (and Release Executable) – 75 Kb

Download source – 6 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.