在 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(), m_pWebBrowser2(NULL), m_dwCookie()
{
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 == )
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 >= && pDispParams->rgvarg[].vt == VT_DISPATCH)
SetCustomDoc(pDispParams->rgvarg[].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 ? : DOCHOSTUIFLAG_NO3DBORDER);
pInfo->dwFlags |= (m_bEnableScrollBar ? : 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 = ;
// _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__

C++(MFC)中WebBrowser去除3D边框的方法(实现IDocHostUIHandler接口)控制 WebBrowser 控件的外观和行为的更多相关文章

  1. C++(MFC)中WebBrowser去除3D边框的方法(实现IDocHostUIHandler接口)

    先说实在的:最终解决办法是实现IDocHostUIHandler接口,在GetHostInfo方法里解决,但“实现接口”意味着QueryInterface.AddRef.Release三个方法必须实现 ...

  2. MFC中CTime获取日期时间的方法

    MFC中CTime类的功能非常强大,可以获取年.月.日.小时.分钟.秒.星期等等,最最重要的是可根据需要去格式化.下面是具体的使用方式: ① 定义一个CTime类对象 CTime time; ② 得到 ...

  3. 在网页中编辑报表的报表设计器Stimulsoft Reports Designer.Web报表控件

    Stimulsoft Reports Designer.Web报表控件是一款网页报表设计器.您想在网页中编辑您的报表吗?现在是可能的! Stimulsoft Reports Designer.Web ...

  4. XAF 框架中,自定义参数动作(Action),输入参数的控件可定义,用于选择组织及项目

    XAF 框架中,如何生成一个自定义参数动作(Action),输入参数的控件可定义? 参考文档:https://documentation.devexpress.com/eXpressAppFramew ...

  5. VS2010/MFC编程入门之五十四(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)

    上一节中鸡啄米讲了为Ribbon Bar添加控件的方法.本节教程鸡啄米将继续完善前面的实例,讲解一些稍复杂的控件的添加方法,及如何为它们添加消息处理函数. 一.为Ribbon Bar添加更多Ribbo ...

  6. 【转】VC 多线程中控制界面控件的几种方法

    原文网址:https://software.intel.com/zh-cn/blogs/2010/11/30/vc-3 为了保证界面的用户体验经常要把数据处理等放到子线程中进行,然后把结果更新到主界面 ...

  7. 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类

    转自: http://blog.csdn.net/sunguangran/article/details/6069317 非常感谢原作者,整理的这么详细. 在java中可有两种方式实现多线程,一种是继 ...

  8. PyQt学习随笔:Qt中tem Views(Model-Based)和Item Widgets(Item-Based)控件的用途和关系

    在界面程序开发中,数据的展示主要包括表格.简单列表.树状列表以及纯文本等多种方式,在Qt中将界面表格.简单列表.树状列表称为"表项视图类(item view class)",并提供 ...

  9. .NET混合开发解决方案8 WinForm程序中通过设置固定版本运行时的BrowserExecutableFolder属性集成WebView2控件

    系列目录     [已更新最新开发文章,点击查看详细] 在我的博客<.NET混合开发解决方案7 WinForm程序中通过NuGet管理器引用集成WebView2控件>中介绍了WinForm ...

随机推荐

  1. 不同操作系统上屏蔽oracle的操作系统认证方式

    windows系统上>如果不想用户通过操作系统验证方式登录,可以修改 sqlnet.ora文件,把 SQLNET.AUTHENTICATION_SERVICES=NTS 前面加#注释掉就可以了. ...

  2. 完成一段简单的Python程序,使用函数实现用来判断输入数是偶数还是奇数

    #!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,使用函数实现用来判断偶数和奇数'''def number_deal(a): if a%2==0 ...

  3. MSSQL 生成拼音码

    MSSQL 生成拼音码 /*============================================================================== 名称:fn_G ...

  4. linux IO调度

    I/O 调度算法再各个进程竞争磁盘I/O的时候担当了裁判的角色.他要求请求的次序和时机做最优化的处理,以求得尽可能最好的整体I/O性能.在linux下面列出4种调度算法CFQ (Completely ...

  5. Java 学习总结(一)

    1.     概述 1.1           dos命令行--常见的命令 l  dir : 列出当前目录下的文件以及文件夹 l  md : 创建目录 l  rd : 删除目录 l  cd : 进入指 ...

  6. Spring学习 Ioc篇(三)

    1.在注解注入方式中,首先要在xml中引入如下的红线的命名空间: <?xml version="1.0" encoding="UTF-8" ?> & ...

  7. bzoj3086: Coci2009 dvapravca

    Description 给定平面上的 N 个点, 其中有一些是红的, 其他是蓝的.现在让你找两条平行的直线, 使得在保证    不存在一个蓝色的点 被夹在两条平行线之间,不经过任何一个点, 不管是蓝色 ...

  8. ES6转换为ES5

    1.静态函数 1.什么是静态函数 静态函数最重要的就是不用创建一个实例变量就可以进行调用,在C++里面,无法访问this对象, 而在JS里面由于js的this对象支持,是可以访问this对象,只是th ...

  9. 【AT91SAM3S】英蓓特EM-SAM3S开发板例子工程中的启动文件分析

    手上一块英倍特的EM-SAM3S开发板,拿到已经有一个月了.本来是做uLoong活动使用的板子,可当初由于不熟悉这个芯片,使用了STM32F4当作了替代.最近准备抽点时间折腾下这个板子. 这个板子的资 ...

  10. Maven依赖排除 禁止依赖传递 取消依赖的方法

    大家都知道Maven的优点是依赖管理,特别是前期使用ANT的开发者都有很多感触.最近要开发一个java工程,定的要使用maven,会使用hadoop和hbase的客户端,而引入一个hadoop-cli ...