控制 WebBrowser 控件的外观和行为

//转处:http://blog.sina.com.cn/s/blog_4c88b511010095mc.html

在 CSDN 上经常看到以下两个问题:
1、在 MFC 应用程序中,如果创建了一个 WebBrowser 控件(包括 CHtmlView 在内),如何可以把该控件的三维边框禁止掉?
2、在 MFC 应用程序中,如果创建了一个 WebBrowser 控件(包括 CHtmlView 在内),如何可以把该控件的滚动条禁止掉?

其实,这两个问题的解决办法是一样的。待老汉从头道来。

从 Internet Explorer 4.0 开始,WebBrowser 控件的容器可以通过 IDocHostUIHandler 接口对 WebBrowser 控件的外观和某些行为进行定制。上述的两个问题,均可以通过实现该接口来达到我们的目的。但是,由于程序员自己实现 WebBrowser 控件的容器是一件很痛苦的事情,而且 MFC 中的 CHtmlView 和在 IDE 中插入 WebBrowser 控件后生成的包装类已经具有比较完整的功能封装,故罕有人愿意从头再开发自己的容器。不过令人遗憾的是,随 Visual C++ 6.0 发布的 MFC 4.2 版本中并没有对 IDocHostUIHandler 接口进行支持(顺便说一句,从 Visual C++ 7.0 开始,MFC 已经对该接口进行了支持),所以这些问题在 Visual C++ 6.0 中比较突出。

为了解决此问题,老汉特意写了一个类来完成此工作(代码见下)。该类名为 CWebUIController,使用很简单,以对话框上包含了 WebBrowser 控件为例:

假设对话框上的 WebBrowser 控件对应的变量名为 m_webNavigator,则需要以下步骤:

1、向对话框类中添加 CWebUIController m_webUICtrl;

2、在对话框的 OnInitDialog 函数中加入以下代码:

 LPUNKNOWN pUnk = m_webNavigator.GetControlUnknown();
if(pUnk != NULL)
{
IWebBrowser2* pWB2 = NULL;
HRESULT hr = pUnk->QueryInterface(IID_IWebBrowser2, (void**)&pWB2);
if(SUCCEEDED(hr) && pWB2 != NULL)
{
m_webUICtrl.Enable3DBorder(FALSE); // 此代码禁止三维边框
// m_webUICtrl.EnableScrollBar(FALSE); // 此代码禁止滚动条
m_webUICtrl.SetWebBrowser(pWB2);
pWB2->Release();
}
}

3、在对话框的 OnDestroy 函数中加入以下代码:

 m_webUICtrl.SetWebBrowser(NULL); 

也可以在运行时调用 Enable3DBorder() 或者 EnableScrollBar(),调用完成后请调用 WebBrowser 控件的刷新功能。

该类实现于一个独立的头文件 WebUIController.h 中,其完整源代码如下;从源代码中不难看出,还可以很容易的扩充此类的功能,例如控制关联菜单的显示等等。

WebUIController.h 源代码:

// class name: CWebUIController
// author: Dandy Cheung
// email: dandycheung@21cn.com
// date: 2005-3-18

#ifndef __WEBUICONTROLLER_H__
#define __WEBUICONTROLLER_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <MSHTMHST.H>
#include <EXDISP.H>
#include <EXDISPID.H>

inline
HRESULT _CoAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
{
IConnectionPointContainer* pCPC = NULL;
IConnectionPoint* pCP = NULL;
HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
if(SUCCEEDED(hRes) && pCPC != NULL)
{
hRes = pCPC->FindConnectionPoint(iid, &pCP);
if(SUCCEEDED(hRes) && pCP != NULL)
{
hRes = pCP->Advise(pUnk, pdw);
pCP->Release();
}

pCPC->Release();
}

return hRes;
}

inline
HRESULT _CoUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw)
{
IConnectionPointContainer* pCPC = NULL;
IConnectionPoint* pCP = NULL;
HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
if(SUCCEEDED(hRes) && pCPC != NULL)
{
hRes = pCPC->FindConnectionPoint(iid, &pCP);
if(SUCCEEDED(hRes) && pCP != NULL)
{
hRes = pCP->Unadvise(dw);
pCP->Release();
}

pCPC->Release();
}

return hRes;
}

class CWebUIController
{
ULONG m_uRefCount;

IWebBrowser2* m_pWebBrowser2;
DWORD m_dwCookie;

BOOL m_bEnable3DBorder;
BOOL m_bEnableScrollBar;

public:
CWebUIController() : m_uRefCount(0), m_pWebBrowser2(NULL), m_dwCookie(0)
{
m_bEnable3DBorder = TRUE;
m_bEnableScrollBar = TRUE;
}

virtual ~CWebUIController()
{
}

protected:
// IUnknown Methods
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;

if(IsEqualGUID(riid, DIID_DWebBrowserEvents2) ||
IsEqualGUID(riid, IID_IDispatch))
{
*ppvObject = (DWebBrowserEvents2*)this;
AddRef();
return S_OK;
}
else if(IsEqualGUID(riid, IID_IDocHostUIHandler) ||
IsEqualGUID(riid, IID_IUnknown))
{
*ppvObject = (IDocHostUIHandler*)this;
AddRef();
return S_OK;
}

return E_NOINTERFACE;
}

STDMETHOD_(ULONG, AddRef)(void)
{
m_uRefCount++;
return m_uRefCount;
}

STDMETHOD_(ULONG, Release)(void)
{
m_uRefCount--;
ULONG uRefCount = m_uRefCount;
if(uRefCount == 0)
delete this;

return uRefCount;
}

// IDispatch Methods
STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo)
{
return E_NOTIMPL;
}

STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return E_NOTIMPL;
}


STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{
return E_NOTIMPL;
}

STDMETHOD(Invoke)(DISPID dispidMember,REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
if(!pDispParams)
return E_INVALIDARG;

switch(dispidMember)
{
//
// The parameters for this DISPID are as follows:
// [0]: URL to navigate to - VT_BYREF|VT_VARIANT
// [1]: An object that evaluates to the top-level or frame
// WebBrowser object corresponding to the event.
case DISPID_NAVIGATECOMPLETE2:

//
// The IDocHostUIHandler association must be set
// up every time we navigate to a new page.
//
if(pDispParams->cArgs >= 2 && pDispParams->rgvarg[1].vt == VT_DISPATCH)
SetCustomDoc(pDispParams->rgvarg[1].pdispVal);
else
return E_INVALIDARG;

break;

default:
break;
}

return S_OK;
}

// IDocHostUIHandler Methods
protected:
STDMETHOD(ShowContextMenu)(DWORD dwID, POINT FAR* ppt, IUnknown FAR* pcmdtReserved,
IDispatch FAR* pdispReserved)
{
return E_NOTIMPL;
}

STDMETHOD(GetHostInfo)(DOCHOSTUIINFO FAR* pInfo)
{
if(pInfo != NULL)
{
pInfo->dwFlags |= (m_bEnable3DBorder ? 0 : DOCHOSTUIFLAG_NO3DBORDER);
pInfo->dwFlags |= (m_bEnableScrollBar ? 0 : DOCHOSTUIFLAG_SCROLL_NO);
}

return S_OK;
}

STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject FAR* pActiveObject,
IOleCommandTarget FAR* pCommandTarget,
IOleInPlaceFrame FAR* pFrame,
IOleInPlaceUIWindow FAR* pDoc)
{
return E_NOTIMPL;
}

STDMETHOD(HideUI)(void)
{
return E_NOTIMPL;
}

STDMETHOD(UpdateUI)(void)
{
return E_NOTIMPL;
}

STDMETHOD(EnableModeless)(BOOL fEnable)
{
return E_NOTIMPL;
}

STDMETHOD(OnDocWindowActivate)(BOOL fActivate)
{
return E_NOTIMPL;
}

STDMETHOD(OnFrameWindowActivate)(BOOL fActivate)
{
return E_NOTIMPL;
}

STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow FAR* pUIWindow,
BOOL fRameWindow)
{
return E_NOTIMPL;
}

STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID FAR* pguidCmdGroup,
DWORD nCmdID)
{
return E_NOTIMPL;
}

STDMETHOD(GetOptionKeyPath)(LPOLESTR FAR* pchKey, DWORD dw)
{
return E_NOTIMPL;
}

STDMETHOD(GetDropTarget)(IDropTarget* pDropTarget,
IDropTarget** ppDropTarget)
{
return E_NOTIMPL;
}

STDMETHOD(GetExternal)(IDispatch** ppDispatch)
{
return E_NOTIMPL;
}

STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR* pchURLIn,
OLECHAR** ppchURLOut)
{
return E_NOTIMPL;
}

STDMETHOD(FilterDataObject)(IDataObject* pDO, IDataObject** ppDORet)
{
return E_NOTIMPL;
}

public:
HRESULT SetWebBrowser(IWebBrowser2* pWebBrowser2)
{
// Unadvise the event sink, if there was a
// previous reference to the WebBrowser control.
if(m_pWebBrowser2)
{
_CoUnadvise(m_pWebBrowser2, DIID_DWebBrowserEvents2, m_dwCookie);
m_dwCookie = 0;

m_pWebBrowser2->Release();
}

m_pWebBrowser2 = pWebBrowser2;
if(pWebBrowser2 == NULL)
return S_OK;

m_pWebBrowser2->AddRef();

return _CoAdvise(m_pWebBrowser2, (IDispatch*)this, DIID_DWebBrowserEvents2, &m_dwCookie);
}

void Enable3DBorder(BOOL bEnable = TRUE)
{
m_bEnable3DBorder = bEnable;
}

void EnableScrollBar(BOOL bEnable = TRUE)
{
m_bEnableScrollBar = bEnable;
}

private:
void SetCustomDoc(LPDISPATCH lpDisp)
{
if(lpDisp == NULL)
return;

IWebBrowser2* pWebBrowser2 = NULL;
HRESULT hr = lpDisp->QueryInterface(IID_IWebBrowser2, (void**)&pWebBrowser2);

if(SUCCEEDED(hr) && pWebBrowser2)
{
IDispatch* pDoc = NULL;
hr = pWebBrowser2->get_Document(&pDoc);

if(SUCCEEDED(hr) && pDoc)
{
ICustomDoc* pCustDoc = NULL;
hr = pDoc->QueryInterface(IID_ICustomDoc, (void**)&pCustDoc);
if(SUCCEEDED(hr) && pCustDoc != NULL)
{
pCustDoc->SetUIHandler(this);
pCustDoc->Release();
}

pDoc->Release();
}

pWebBrowser2->Release();
}
}
};

#endif // __WEBUICONTROLLER_H__
posted @ 2012-01-01 13:59  stma  阅读(2654)  评论(0)    收藏  举报