在 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 源代码:
#pragma once // 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 : public DWebBrowserEvents2, public IDocHostUIHandler { 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; // _CoUnadvise中就已经被Release // 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__