`
isiqi
  • 浏览: 16001851 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

浏览器集成教学 自定义浏览器

阅读更多

本文翻译自 http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/hosting/wbcustomization.asp

自定义浏览器

本教程提供了自定义浏览器控件的行为和外观的一些方法。你将看到高级的宿主接口,IDocHostUIHandler, IDocHostUIHandler2, IDocHostShowUI, 和ICustomDoc。本文也讨论其他自定义方法,例如在宿主的IDispatch实现中处理DISPID_AMBIENT_DLCONTROL来进行下载控制;以及使用IHostDialogHelper。

本文分为如下章节

  • 前提和需求
  • 介绍
  • 浏览器自定义架构
  • IDocHostUIHandler
  • IDocHostUIHandler2
  • GetOptionKeyPath 和 GetOverrideKeyPath比较
  • 控制导航
  • IDocHostShowUI
  • 控制下载和执行
  • IHostDialogHelper
  • 控制新的窗口
  • 显示证书对话框(New!)
  • 信息栏(New!)
  • 结论

前提和需求

为了理解和使用本教程,你需要

  • 对C++和COM的深入了解
  • 熟悉活动模板库 (ATL)
  • 安装了Microsoft(R) Internet Explorer (IE)6 或更高版本
  • 开发环境具有用于IE6或更高版本的头文件和库文件;特别是Mshtmhst.h.译者注:可以在http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ 这里下载最新的Internet Development SDK

许多自定义特性是在IE5或者5.5版本就可以使用的,但是有几个特性需要IE6。一些特性需要IE6的Windows XP SP2版本。使用某个特性之前,应该检查参考文档以获得版本信息。

介绍

集成浏览器控件是快速软件开发的强有力的工具。通过成为浏览器的宿主,你可以利用便于使用的Dynamic HTML (DHTML), HTML, 和Extensible Markup Language (XML)来显示信息和开发一个用户界面。但是,浏览器控件的行为可能不确切符合你的需求。例如,默认的状态允许用户通过快捷菜单的查看源代码选项查看一个显示的页面的源代码,你可能需要禁用或者干脆去掉这个选项。你可能更进一步,需要用你自己的快捷菜单替换默认的快捷菜单。

在刚刚提到的自定义特性之外,高级宿主特性允许

  • 在显示的页面上的按钮和其他控件可以调用你的应用程序的内建方法,有效地扩展DHTML对象模型(DOM)
  • 改变拖放的行为
  • 限制浏览器的导航,例如,限制于指定的页面/域,或者站点
  • 捕获用户键入,并且在需要的时候处理。比如说,你可能需要捕获CTRL+O来阻止用户在新的IE中打开网页而不是使用你的程序打开,
  • 改变默认字体和显示设置
  • 控制下载内容,以及当下载完成之后浏览器的处理。例如,你可能禁用视频的播放,脚本的执行,点击链接时打开新的窗口,或者Microsoft(R) ActiveX 控件的下载和执行。
  • 限制查看源代码
  • 捕获搜索
  • 捕获导航错误
  • 替代/修改快捷菜单或者禁用,替代,自定义,或者添加快捷菜单项
  • 为你的应用程序改变注册表设定
  • 控制和修改浏览器控件显示的消息框
  • 控制新窗口的创建方式

在下列中,我们将会看到多数,但是不是全部的这些可能性而且讨论该如何实现他们。

浏览器自定义架构

介绍 IDocHostUIHandler , IDocHostUIHander2 , IDocHostShowUI 和 ICustomDoc

下面三个接口是浏览器控件用户界面的自定义核心:IDocHostUIHandler ,IDocHostUIHandler2 和 IDocHostShowUI。当你修改浏览器控件的时候 , 这些是你在你的应用程序中实现的接口。也有一些服务接口。 ICustomDoc 被MSHTML实现并且提供一个方法在某些情况下能够自定义浏览器控件。IHostDialogHelper提供一个方法打开可信对话框,没有像IE对话框那样为他们(译者注:在标题栏上)作标记。

除了使用这些接口,你还可以做其他件事。一,你能通过在IDispatch实现中拦截环境特性的变化来控制下载其次,你能通过在IDispatch实现中拦截DISPID_NEWWINDOW2控制窗口的创建方式

译者注:MFC7中的DHTML类,例如CHtmlView和CDHtmlDialog实现了这些接口,但是对于使用其他的类库的程序员,可能需要自己实现这些接口。

如何工作

当一个容器提供对ActiveX 控件支持时候 , 浏览器控件自定义机制被设计为被自动化。当浏览器控件被实例化的时候,如果可能的话,它尝试找来自宿主的 IDocHostUIHandler , IDocHostUIHandler2 和 IDocHostShowUI 实现浏览器控件通过调用宿主的IOleClientSite接口的一个QueryInterface方法来查找。

译者注:IE5.5有个Bug,没有查询IDocHostUIHandler2 接口的实现,这使得宿主程序不能覆盖默认的参数。需要更多信息的话,参考微软知识库文章 Q272968 BUG:IDocHostUIHandler2 没有在浏览器控件中调用。

这一个结构为一个实现一个IOleClientSite接口的应用程序自动地工作,通过调用浏览器的IOleObject::SetClientSite方法传递给浏览器控件一个IOleClientSite接口。浏览器控件的一个典型的实例化可能看起来像这样:

例子


//为了明确起见,省略错误检查

CComPtr<IOleObject> spOleObj;

//创建 WebBrowser--类成员变量 m_spWebBrowser中保存指针

CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC, IID_IWebBrowser2, (void**)&m_spWebBrowser);

// 查询WebBrowserIOleObject接口

m_spWebBrowser->QueryInterface(IID_IOleObject, (void**)&spOleObj);

//设置用户站点

spOleObj->SetClientSite(this);

//本地激活浏览器控件

RECT rcClient

GetClientRect(&rcClient);

spOleObj->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, GetTopLevelWindow(), &rcClient);

//容器拦截浏览器事件的注册

AtlAdvise(m_spWebBrowser,GetUnknown(), DIID_DWebBrowserEvents2,&m_dwCookie);

//导航到启动页

m_spWebBrowser->Navigate(L"res://webhost.exe/startpage.htm", NULL, NULL, NULL, NULL);



然而,如果你的应用程序没有一个IOleClientSite接口,你并没失去全部希望。IE提供ICustomDoc接口,这样你能自己传递你的IDocHostUIHandler接口给浏览器。你不能使用IDocHostUIHandler2和 IDocHostShowUI接口而不提供一个浏览器控件宿主的IOleClientSite接口。

译者注:

MFC7中引入的类COleControlContainer和一大堆DHTML类曾经搞得我晕头转向,最后我不得不放弃了自己对IOleClientSite的实现,而通过ICustomDoc来显式地设置IDocHostUIHandler接口。这样必须在第一个页面下载完成之后才能够开始自定义浏览器,因为暴露ICustomDoc接口的对象只有在第一个页面下载完成之后才可用。一个ICustomDoc的示例可以在CSDN文档中心找到,网址是http://www.csdn.net/develop/Read_Article.asp?Id=8813

当浏览器控件获得了对这些接口之中的任何一个的一个指针的时候,接口的方法在适当的时候在浏览器控件的生命期中被调用。举例来说, 当用户右击在浏览器控件的客户区的任何地点时,在IE显示它的默认快捷菜单之前,你的IDocHostUIHandler::ShowContextMenu的实现将会被调用。这给你一个机会显示你自己的快捷菜单而且取消IE的快捷菜单显示。

译者注:一些屏蔽快捷菜单的示例可以在CSDN文档中心找到,网址是http://www.csdn.net/develop/article/18/18541.shtm

当初始化浏览器控件的时候 ,记住几个重点。你的应用程序应该使用 OleInitialize而不是CoInitialize启动COM。OleInitialize启用剪贴簿支持,拖放,对象连接与嵌入(OLE)和本地激活。当你的应用程序结束的时候使用OleUninitialize关闭COM库。

ATL COM 向导使用 CoInitialize而不是OleInitialize打开COM库。 如果你使用这一个向导建立一个可运行的程序,你需要将 CoInitialize 和 CoUninitialize 调用换成 OleInitialize 和 OleUninitialize。对于一个微软基础类 (MFC) 应用程序, 确定你的应用程序调用 AfxOleInit, 它在它的初始化程序中调用OleInitialize。

如果你不需要在你的应用程序中支持拖放,你可以调用IWebBrowser2::RegisterAsDropTarget,传递VARIANT_TRUE(译者注:原文如此,按照接口文档,似乎应该传递VARIANT_FALSE), 避免任何在你的浏览器控件实例上的拖放操作。

一个浏览器控件宿主应用程序也需要IOleInPlaceSite的一个实现, 由于 IOleInPlaceSite派生自IOleWindow,应用程序将需要IOleWindow的一个实现。你需要这些实现使得你的应用程序具有一个窗口,显示浏览器控件,以及处理它的显示设置。

这些接口和IOleClientSite的实现在许多情况可能是最小的或不存在的。IOleClientSite的所有方法都可以返回E_NOTIMPL。 一些IOleInPlaceSite和IOleWindow的方法需要一个实现来覆盖返回值。可以在示例代码中查看IOleInPlaceSite和IOleWindow的最小实现的样例代码。

既然我们已经完成了初始化的准备,让我们看一看浏览器控件自定义的每一个接口。

IDocHostUIHandler

IDocHostUIHandler自IE5以后已经是可用的。它提供15个方法。大体上,一些较重要的方法是IDocHostUIHandler::GetExternal, IDocHostUIHandler::GetHostInfo, IDocHostUIHandler::GetOptionKeyPath, IDocHostUIHandler::ShowContextMenu, 和 IDocHostUIHandler::TranslateAccelerator。当然,方法对你的重要性将会依赖于你的应用程序。

IDocHostUIHandler::GetHostInfo

你使用IDocHostUIHandler::GetHostInfo告诉MSHTML有关你的应用程序的能力和需求。通过它你能控制很多东西, 举例来说:

  • 你能禁用浏览器的3D的边缘。
  • 你能避免滚动条或改变他们的外观
  • 你能禁用脚本
  • 你能定义双击处理的方式
  • 你能禁用浏览器的自动完成功能

IDocHostUIHandler::GetHostInfo有一个参数,被 MSHTML分配的DOCHOSTUIINFO 结构的一个指针。你的工作要将结构中填充你传给MSHTML的信息。

DOCHOSTUIINFO结构有四个成员。第一个成员是 cbSize,是结构的大小。你应该自己像下面的示例代码那样设置。第二个成员是dwFlags,由来自DOCHOSTUIFLAG枚举的数值位与组成。第三成员是dwDoubleClick,来自DOCHOSTUIDBLCLK枚举的一个数值。第四个成员是pchHostCss。你可以将pchHostCss设定为浏览器控件显示的页面中应用的全局样式表(CSS)规则的一个字符串的指针。DOCHOSTUIINFO 的最后一个成员是pchHostNs。你可以设置为你提供的分号分隔的命名空间列表字符串。在你正在浏览器控件中显示的页上使用自定义标签的时候使用这一个成员。这样你能声明一个全局的命名空间列表,而不需要在每个显示声明他们。

确定使用CoTaskMemAlloc为pchHostCss或pchHostNS分配字符串译者注:看起来调用者用CoTaskMemFree释放这些字符串)。

例子

HRESULT GetHostInfo( DOCHOSTUIINFO* pInfo)

{

WCHAR* szCSS = L"BODY {background-color:#ffcccc}";

WCHAR* szNS = L"IE;MyTags;MyTags2='www.microsoft.com'";

#define CCHMAX 256

size_t cchLengthCSS,cchLengthszNS;

HRESULT hr=StringCchLengthW(szCSS, CCHMAX,&cchLengthCSS)

//TODO: 在这里处理错误。

OLECHAR* pCSSBuffer=(OLECHAR*) CoTaskMemAlloc((cchLengthCSS+1)*sizeof(OLECHAR));

//TODO: 在这里处理错误确定内存成功地被分配

hr=StringCchLengthW(szNS, CCHMAX,&cchLengthszNS)

//TODO: 在这里处理错误。

OLECHAR* pNSBuffer=(OLECHAR*) CoTaskMemAlloc((cchLengthszNS+1)*sizeof(OLECHAR));

//TODO: 在这里处理错误确定内存成功地被分配

hr=StringCchCopyW(pCSSBuffer , cchLengthCSS+1,szCSS)

//TODO: 在这里处理错误。

hr=StringCchCopyW(pNSBuffer , cchLengthszNS+1,szNS)

//TODO: 在这里处理错误。

pInfo-> cbSize= sizeof(DOCHOSTUIINFO)

pInfo-> dwFlags= DOCHOSTUIFLAG_NO3DBORDER|DOCHOSTUIFLAG_SCROLL_NO|DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE;

pInfo-> dwDoubleClick= DOCHOSTUIDBLCLK_DEFAULT;

pInfo-> pchHostCss= pCSSBuffer;

pInfo-> pchHostNS= pNSBuffer;

return S_OK;

}

如果你没有什么需要告诉MSHTML,你可以在这个方法中返回E_NOTIMPL 。

IDocHostUIHandler::ShowContextMenu

通过实现这一个方法, 你获得一个用户右击被浏览器控件显示的快捷菜单的控制。你能通过这个方法返回S_OK 阻止IE显示它的默认快捷菜单。返回一些其他的数值 , 像S_FALSE或E_NOTIMPL,允许IE继续执行它的默认快捷菜单行为。

如果你仅仅在这个方法中返回S_OK, 你能避免任何浏览器控件的右击行为。 这可能是你在许多场合中的全部需求,但是你能做更多。通常,你使用这一个方法在返回 S_OK 之前产生并且显示你自己的快捷菜单。如果你知道浏览器控件显示的菜单的资源,而且它如何选择他们,你能也有效地自定义默认的浏览器控件快捷菜单。让我们看看它如何工作

浏览器控件由Shdoclc.dll获得它的快捷菜单资源。这个知识和一些 #define给予你一个机会操纵浏览器的菜单。让我们举例来说,假定你对默认菜单感到满意,除了你想要除去查看代码之外。下列代码载入来自Shdoclc.dll的浏览器控件快捷菜单资源,根据环境选择正确的菜单,移除IDM_VIEWSOURCE命令应的菜单项,然后显示菜单

例子

HRESULT CBrowserHost::ShowContextMenu(DWORD dwID,

POINT *ppt,

IUnknown *pcmdTarget,

IDispatch *pdispObject)

{

#define IDR_BROWSE_CONTEXT_MENU 24641

#define IDR_FORM_CONTEXT_MENU 24640

#define SHDVID_GETMIMECSETMENU 27

#define SHDVID_ADDMENUEXTENSIONS 53

HRESULT hr;

HINSTANCE hinstSHDOCLC;

HWND hwnd;

HMENU hMenu;

CComPtr<IOleCommandTarget> spCT;

CComPtr<IOleWindow> spWnd;

MENUITEMINFO mii={0};

CComVariant var, var1, var2;

hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);

hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);

hr = spWnd->GetWindow(&hwnd);

hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));

if (hinstSHDOCLC == NULL)

{

// 载入模块错误 -- 尽可能安全地失败

return;

}

hMenu=LoadMenu(hinstSHDOCLC,

MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));

hMenu=GetSubMenu(hMenu,dwID);

//获得语言子菜单

hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);

mii.cbSize = sizeof(mii);

mii.fMask = MIIM_SUBMENU;

mii.hSubMenu = (HMENU) var.byref;

//加入语言子菜单到编码上下文菜单

SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);

//插入来自注册表的快捷菜单扩展

V_VT(&var1) = VT_INT_PTR;

V_BYREF(&var1) = hMenu;

V_VT(&var2) = VT_I4;

V_I4(&var2) = dwID;

hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);

//删除查看源代码

DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);

//显示快捷菜单

int iSelection = ::TrackPopupMenu(hMenu,

TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,

ppt->x,

ppt->y,

0,

hwnd,

(RECT*)NULL);

//发送选定的快捷菜单项目指令到外

LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);

FreeLibrary(hinstSHDOCLC);

return S_OK;

}

安全警告不正确地使用LoadLibrary能载入错误的动态链接库(DLL)来威胁你的应用程序的安全关于该如何正确地用微软Windows 的不同版本载入DLL的信息,参照LoadLibrary的文档

IDocHostUIHandler::GetExternal: 扩充文档对象模型

IDocHostUIHandler 提供一个让你用在你自己的应用程序中实现你自己的对象,方法和特性扩充IE文档对象模型 (DOM)的方法。你的实现是提供给MSHTML一个IDispatch接口指针,指向你自定义的COM自动化对象,实现你自定义的对象、属性和方法。这些对象,特性和方法之后可以在浏览器控件显示的任何页面中通过文档的外部对象访问

这一个方法的实现可以是非常简单的, 假定你的IDispatch接口在实现IDocHostUIHandler的相同对象上。

HRESULT CBrowserHost::GetExternal(IDispatch **ppDispatch)

{

*ppDispatch = this;

return S_OK;

}

只要 MSHTML有对你的 IDispatch 的一个指针,MSHTML将会传递网页上对任何外部对象的调用你的应用程序的自动化方法:

<SCRIPT language="JScript">

function MyFunc(iSomeData)

{

external.MyCustomMethod("Some text", iSomeData);

}

</SCRIPT>

你也能使用这技术传递整个对象一个页。为了实现它,在你的IDispatch实现中创建一个方法,传递回你的网页可以用的对象。

<SCRIPT language="JScript">

function MyFunc(iSomeData)

{

var oCustCalendarObj;

external.GetCustomCalender(oCustCalenderObj);

oCustCalerdarObj.doStuffWithIt();

.

.

.

}

</SCRIPT>

可以看看示例代码中使用 ATLIDispatch自动化实现的一个例子 。

译者注:IE也扩展了浏览器的文档对象模型,使得你在脚本中可以通过扩展对象menuArguments属性访问当前窗口对象。

IDocHostUIHandler::GetOptionKeyPath

IDocHostUIHandler::GetOptionKeyPath是自定义浏览器控件的一个非常有力的工具。 许多浏览器控件显示行为设定被储存在注册表中HKEY_CURRENT_USER键的下面。IDocHostUIHandler::GetOptionKeyPath给你一个机会为你的浏览器控件的特定实例覆盖这些注册表设定。它通过提供一个替代的注册表位置来实现,浏览器控件将会在这里读取注册表设置

IDocHostUIHandler::GetOptionKeyPath的一个实现传递给浏览器控件读取注册表设置的位置的一个字符串。浏览器控件将会找寻在HKEY_CURRENT_USER键下面的这一个键。

例子

HRESULT CBrowserHost::GetOptionKeyPath(LPOLESTR *pchKey,

DWORD dwReserved)

{

HRESULT hr;

#define CCHMAX 256

size_t cchLength;

if (pchKey)

{

WCHAR* szMyKey = L"Software\MyCompany\MyApp";

hr = StringCchLengthW(szMyKey, CCHMAX, &cchLength);

//TODO: 在这里处理错误。

*pchKey = (LPOLESTR)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR));

if (*pchKey)

hr = StringCchCopyW(*pchKey, cchLength + 1, szKey);

//TODO: 在这里处理错误。

hr = (*pchKey) ? S_OK : E_OUTOFMEMORY;

}

else

hr = E_INVALIDARG;

return hr;

}

IDocHostUIHandler::GetHostInfo一样,确保为你的字符串使用 CoTaskMemAlloc分配内存。

告诉浏览器控件该哪里找寻你的注册表设置实际上是第一步——就程序运行来说第二步。 你的程序必须在被IDocHostUIHandler::GetOptionKeyPath告诉的位置设置一个注册表,这样浏览器控件才可以去读取。有多种方法来完成这个步骤一个方法是当应用程序被安装的时候执行一个注册表脚本。另外的一个方法当应用程序启动的时候,用代码来完成。这里是改变默认值字体,大小和颜色的一个设定。

例子

HRESULT SetSomeKeys()

{

HKEY hKey = NULL;

HKEY hKey2 = NULL;

HKEY hKey3 = NULL;

DWORD dwDisposition = NULL;

LONG lResult = NULL;

#define CBMAX 256

size_t cbLength;

RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\MyCompany\MyApp"),

NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,

NULL, &hKey, &dwDisposition);

RegCreateKeyEx(hKey, _T("Main"), NULL, NULL, REG_OPTION_NON_VOLATILE,

KEY_SET_VALUE, NULL, &hKey2, &dwDisposition);

RegSetValueEx(hKey2, _T("Use_DlgBox_Colors"), NULL, REG_SZ,

(CONST BYTE*)_T("no"), sizeof(_T("no")));

RegCloseKey(hKey2);

RegCreateKeyEx(hKey, _T("Settings"), NULL, NULL, REG_OPTION_NON_VOLATILE,

KEY_SET_VALUE, NULL, &hKey2, &dwDisposition);

RegSetValueEx(hKey2, _T("Anchor Color"), NULL, REG_SZ,

(CONST BYTE*)_T("0,255,255"), sizeof(_T("0,255,255")));

RegSetValueEx(hKey2, _T("Text Color"), NULL, REG_SZ,

(CONST BYTE*)_T("255,0,255"), sizeof(_T("255,0,255")));

RegCloseKey(hKey2);

RegCreateKeyEx(hKey, _T("International\Scripts"), NULL, NULL,

REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,

&hKey2, &dwDisposition);

BYTE bDefaultScript = 0x3;

RegSetValueEx(hKey2, _T("Default_Script"), NULL, REG_BINARY,

&bDefaultScript, sizeof(bDefaultScript));

RegCreateKeyEx(hKey2, _T("3"), NULL, NULL, REG_OPTION_NON_VOLATILE,

KEY_SET_VALUE, NULL, &hKey3, &dwDisposition);

BYTE bSize = 0x4; // Value from 0 - 4. 2 is medium.

TCHAR* szFontName = _T("Comic Sans MS");

TCHAR* szFixedFontName = _T("Courier");

HRESULT hr = StringCbLength(szFontName, CBMAX, &cbLength);

//TODO: 在这里处理错误。

RegSetValueEx(hKey3, _T("IEPropFontName"), NULL, REG_SZ,

(CONST BYTE*)szFontName, cbLength + sizeof(TCHAR));

hr = StringCbLength(szFixedFontName, CBMAX, &cbLength);

//TODO: 在这里处理错误。

RegSetValueEx(hKey3, _T("IEFixedFontName"), NULL, REG_SZ,

(CONST BYTE*)szFixedFontName, cbLength + sizeof(TCHAR));

RegSetValueEx(hKey3, _T("IEFontSize"), NULL, REG_BINARY, &bSize, sizeof(bSize));

RegCloseKey(hKey3);

RegCloseKey(hKey2);

RegCloseKey(hKey);

return S_OK;

}

IDocHostUIHandler2

IDocHostUIHandler2 只有一个方法,IDocHostUIHandler2::GetOverrideKeyPath。它运行非常类似于IDocHostUIHandler::GetOptionKeyPath的一个功能。它指出你修改自默认注册表设置的集成浏览器使用的注册表设置的位置。IDocHostUIHandler2::GetOverrideKeyPath 的一个实现看起来会很类似于IDocHostUIHandler::GetOptionKeyPath的一个实现。

GetOptionKeyPath 和 GetOverrideKeyPath 比较

你或许没看到IDocHostUIHandler::GetOptionKeyPath和IDocHostUIHandler2::GetOverrideKeyPath之间的任何不同。在他们之间的不同是微妙的, 但是重要的。如果你实现 IDocHostUIHandler::GetOptionKeyPath,你的浏览器控件实例将会忽略任何IE用户设定。这些设定被储存在注册表HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer下面。如果你实现IDocHostUIHandler2::GetOverrideKeyPath,你的浏览器控件实例将会合并任何的用户设定—字体设定,菜单扩展,诸如此类——到显示和行为中

举例说明在IDocHostUIHandler::GetOptionKeyPath和IDocHostUIHandler2::GetOverrideKeyPath之间的不同,让我们重新看看IDocHostUIHandler::ShowContextMenu那段的示例代码记住这一行:

spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);

如果你已经实现IDocHostUIHandler::GetOptionKeyPath,因为菜单扩展信息被储存在当前用户的注册表信息中,所以这一加入任何自定义项目到快捷菜单。如果你已经实现IDocHostUIHandler2::GetOverrideKeyPath, 这一个添加在HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer/MenuExt面定义的任何目前用户定义的菜单扩展, 除非你明确地在你的自定义注册信息位置提供一个空的或替代的MenuExt键。

控制导航

你可能想知道在IDocHostUIHandler那一节为什么不提到 IDocHostUIHandler::TranslateUrl,作为希望制页面导航实现方法。原因是这一个方法不是控制导航通用的技术。 除非你直接地集成MSHTML,这一个方法将没有控制导航的效果。作为替代,通过实现IDispatch::Invoke,处理DISPID_BEFORENAVIGATE2,你可以控制导航。例如,下列代码避免导航一个特别的网址,如果使用者尝试这么做,会显示 "没有允许导航" 错误页。

例子

case DISPID_BEFORENAVIGATE2:

{

CComBSTR url = ((*pDispParams).rgvarg)[5].pvarVal->bstrVal;

if (url == "http://www.adatum.com" || url == "http://www.adatum.com/")

{

CComPtr<IWebBrowser2> spBrowser;

CComPtr<IDispatch> spDisp = ((*pDispParams).rgvarg)[6].pdispVal;

spDisp->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);

spBrowser->Stop();

CComBSTR newURL = "L"res://webhost.exe/nonavigate.htm";

spBrowser->Navigate(newURL, NULL, NULL, NULL, NULL);

((*pDispParams).rgvarg)[0].boolVal = TRUE;

}

break;

}

IDocHostShowUI

这个接口给你对浏览器控件显示信息对话框和帮助的控制。它工作机理和IDocHostUIHandler和IDocHostUIHandler2一样,你实现它,这样在浏览器控件显示它自己的任何的信息或帮助之前 ,能调用你的IDocHostShowUI方法。这给你一个机会阻止浏览器控件显示任何东西,而且使你能够改为显示你自己的自定义信息或帮助。 IDocHostShowUI有两个方法,IDocHostShowUI::ShowMessage和IDocHostShowUI::ShowHelp。

IDocHostShowUI::ShowMessage

返回 S_OK禁用浏览器控件信息对话框。任何其他的返回数值,像S_FALSE或E_NOTIMPL,允许浏览器控件显示它的信息对话框

通过这个方法能做的一件事情是为你的应用程序自定义信息框标题,替代 "Microsoft Internet Explorer" 。你能通过比较lpstrCaption和储存在Shdoclc.dll中的IE使用的字符串资源来完成它。它的ID是IDS_MESSAGE_BOX_TITLE,数值是2213。下列示例代码演示你可能需要做的工作

例子

HRESULT CBrowserHost::ShowMessage(HWND hwnd,

LPOLESTR lpstrText,

LPOLESTR lpstrCaption,

DWORD dwType,

LPOLESTR lpstrHelpFile,

DWORD dwHelpContext,

LRESULT *plResult)

{

USES_CONVERSION;

TCHAR pBuffer[50];

// 窗口标题"Microsoft Internet Explorer"的资源标识

#define IDS_MESSAGE_BOX_TITLE 2213

//载入Shdoclc.dll IE消息框标题字符串

HINSTANCE hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));

if (hinstSHDOCLC == NULL)

{

// 载入模块错误 -- 尽可能安全地失败

return;

}

LoadString(hinstSHDOCLC, IDS_MESSAGE_BOX_TITLE, pBuffer, 50);

// 比较IE消息框标题字符串和lpstrCaption

// 如果相同,用自定义标题替换

if (_tcscmp(OLE2T(lpstrCaption), pBuffer) == 0)

lpstrCaption = L"Custom Caption";

// 创建自己的消息框并且显示

*plResult = MessageBox(OLE2T(lpstrText), OLE2T(lpstrCaption), dwType);

//卸载Shdoclc.dll并且返回

FreeLibrary(hinstSHDOCLC);

return S_OK;

}

安全警告不正确地使用LoadLibrary能载入错误的动态链接库(DLL)来威胁你的应用程序的安全关于该如何正确地用微软Windows的不同版本载入DLL的信息,参照 LoadLibrary的文档

IDocHostShowUI::ShowHelp

这一个方法当IE需要显示帮助时被调用,举例来说当 F1 键被按下时,而且工作方式和IDocHostShowUI::ShowMessage类似。返回S_OK覆盖IE的帮助,或另外的HRESULT值IE执行自己的帮助

控制下载和执行

浏览器控件给你它下载,显示设置和执行的控制。 为了要得到这控制,你实现你的宿主的IDispatch接口,使得它处理DISPID_AMBIENT_DLCONTROL。当浏览器控件被实例化的时候,它将会以这一个ID调用你的IDispatch::Invoke。将pvarResult设置为下列的标识的一个位与的组合,指明你的配置

  • DLCTL_DLIMAGES , DLCTL_VIDEOS 和 DLCTL_BGSOUNDS: 如果这些标识被设定图像,视频背景音乐将会被从服务器下载并且显示或播放,否则将不被下载显示。
  • DLCTL_NO_SCRIPTS 和 DLCTL_NO_JAVA: 脚本Java程序将不被运行。
  • DLCTL_NO_DLACTIVEXCTLS 和 DLCTL_NO_RUNACTIVEXCTLS: ActiveX 控件将不被下载或者运行。
  • DLCTL_DOWNLOADONLY: 网页只将会被下载,不显示。
  • DLCTL_NO_FRAMEDOWNLOAD:浏览器控件将会下载并且解析框架集页面,但是不会下载和解析框架集中单独的框架。
  • DLCTL_RESYNCHRONIZE 和 DLCTL_PRAGMA_NO_CACHE: 这些标志导致Internet缓冲的刷新。通过 DLCTL_RESYNCHRONIZE,服务器将会被请求更新状态。如果服务器指出缓存信息是最新的,将会使用 缓存文件。通过DLCTL_PRAGMA_NO_CACHE,不管文件的更新状态如何,文件都会被从服务器重新下载。
  • DLCTL_NO_BEHAVIORS: 行为不被下载并且在文件中被禁用。
  • DLCTL_NO_METACHARSET_HTML: 忽略META元素中指明的字符集
  • DLCTL_URL_ENCODING_DISABLE_UTF8 和 DLCTL_URL_ENCODING_ENABLE_UTF8: 这些标志的功能类似于IDocHostUIHandler::GetHostInfo使用DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8 DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8标志。不同是只有浏览器控件被初始化的时候,DOCHOSTUIFLAG标志才会被检查。这里的环境特性变化下载标志每当浏览器控件需要运行一个下载被检查。
  • DLCTL_NO_CLIENTPULL: 不运行客户端重定位页面操作(译者注:例如<meta http-equiv="refresh" content="30"> 的默认行为)
  • DLCTL_SILENT: 在下载期间没有用户界面显示。
  • DLCTL_FORCEOFFLINE: 浏览器控件总是在脱机模式中操作。
  • DLCTL_OFFLINEIFNOTCONNECTED 和 DLCTL_OFFLINE: 这些标志是相同的。如果不连接到英特网浏览器控件将会在脱机模式中操作。

DISPID_AMBIENT_DLCONTROL和标志数值在mshtmdid.h被定义

最初,当对IDispatch::Invoke调用开始的时候, pvarResult参数指向的VARIANTVT_EMPTY类型。 你必须为任何有效的设定设置它为VT_I4类型。你可以在VARIANT的lVal成员中存储标志数值。

大部份标志数值有否定的效果,也就是说,他们避免行为正常地发生。举例来说,如果你自定义浏览器控件行为,那么通常脚本会被执行。 但是如果你设定DLCTL_NOSCRIPTS 标志,脚本将不会在控制的那个实例中运行。然而,三标志— DLCTL_DLIMAGES , DLCTL_VIDEOS 和 DLCTL_BGSOUNDS的作用正好相反。你必须全部设置标志,使得浏览器控件以它的默认行为执行关于图像,视频和声音的处理。

下列示例代码使得一个浏览器控件实例下载并且显示图像和视频,但是不处理背景音乐,因为DLCTL_BGSOUNDS没有被明确地设定。浏览器控件显示的页上脚本运行被禁用

例子

STDMETHODIMP CAtlBrCon::Invoke(DISPID dispidMember, REFIID riid,

LCID lcid, WORD wFlags,

DISPPARAMS* pDispParams,

VARIANT* pvarResult,

EXCEPINFO* pExcepInfo,

UINT* puArgErr)

{

switch (dispidMember)

{

case DISPID_AMBIENT_DLCONTROL:

pvarResult->vt = VT_I4;

pvarResult->lVal = DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_NO_SCRIPTS;

break;

default:

return DISP_E_MEMBERNOTFOUND;

}

return S_OK;

}

IHostDialogHelper

IHostDialogHelper是一个你能根据你的爱好创建对话框的接口。这一个接口有一个方法,IHostDialogHelper::ShowHTMLDialog。这一个方法提供如同功能ShowHTMLDialog一般的服务,但是使用起来稍微比较容易一点

为了要使用IHostDialogHelper,你从头产生对话框辅助对象。在这里是你使用CoCreateInstance的方式创建它。接口和ID在 mshtmhst.h 被定义。

例子

IHostDialogHelper* pHDH;

IMoniker* pUrlMoniker;

BSTR bstrOptions = SysAllocString(L"dialogHeight:30;dialogWidth:40");

BSTR bstrPath = SysAllocString(L"c:\dialog.htm");

CreateURLMoniker(NULL, bstrPath, &pUrlMoniker);

// 创建对话框辅助对象

CoCreateInstance(CLSID_HostDialogHelper,

NULL,

CLSCTX_INPROC,

IID_IHostDialogHelper,

(void**)&pHDH);

//调用ShowHTMLDialog 创建对话框

pHDH->ShowHTMLDialog(NULL,

pUrlMoniker,

NULL,

bstrOptions,

<span style

分享到:
评论

相关推荐

    浏览器集成教学 自定义浏览器.docx

    浏览器集成教学 自定义浏览器

    myIE.rar_MyIE_浏览器

    CSDN技术中心 浏览器集成教学 自定义浏览器(Updated for Windows XP SP2).rar

    一款占用内存小,速度超快的免安装浏览器,推荐使用!

    就是因为**集成的搜索太少才用的gb,我自定义了10个搜索按钮,分别是百度、google、google(手气不错)、百度 (歌曲)、Sogua、华军软件、天空软件、金山词典、teein、百度贴吧,用着爽,一字排开十个按钮看着也爽...

    C# 浏览器完整版开发,支持视频、JS交互

    浏览器标签、HTML页面能播放视频、下载记录、JS交互(能调用原生相机、调用VLC集成能力:流视频播放)、软件更新、自定义右键菜单、F11全屏模式、F12调试模式、F5刷新、ALT+F5强制刷新、系统配置等功能、网络请求...

    115极速浏览器 v6.0.5.29.zip

    点击安装之后,安装界面仍然显示的是115浏览器而不是115极速浏览器,需要提醒各位浏览迷的是,目前还不支持自定义安装路径。 安装完成之后,初次打开默认页面为雨林木风旗下的114la网址导航(无法更改),整个...

    KobarUI:用于OBS浏览器集成的UI,具有闪亮的Web可能性

    该项目是通过引导的。...与API后端集成 节点 Ruby on Rails 在开发中代理API请求 配置代理后出现“无效的主机头”错误 手动配置代理 配置WebSocket代理 在开发中使用HTTPS 在服务器上生成动态&lt;met

    九天浏览器 v2.5.2 安卓版.zip

    丰富的安全和隐私设置,让您自定义浏览器的安全特性 - 同时支持标签页和窗口管理两种方式;支持全屏浏览模式 - 集成百度,谷歌等多个搜索引擎 - 有书签功能;可以查看访问历史和最常访问的网站;有阅读列表功能...

    几米浏览器 v1.0.10.10.zip

    3.集成国内最全的恶意网址库,网站好坏大家共同监督评价; 4.体积轻巧功能丰富(一个网页多个窗口),媲美同类多窗口浏览器; 5.支持鼠标手势、超级拖拽、地址栏自动完成等高级功能; 6.广告智能过滤、上网痕迹...

    讯浪安全浏览器 v6.2.zip

    集成 网站导航,娱乐,网上购物,休闲,影视等多个菜单让您上网休闲更轻松! 彻底告别插件安装干扰我们的视线,远离木马病毒的入侵! 讯浪安全浏览器允许在同一窗口内打开任意多个页面, 减少浏览器对系统资源的占用率, ...

    飞奔浏览器官方下载 v5.0.1.zip

    并集成了IE及FireFox的优秀功能于一体,是一款功能强大和灵活的浏览器。 飞奔浏览器使用说明 网址自动补充: 在地址栏中输入比如"baidu"后,按: Ctrl Enter:前补www.后补.com。 Alt Enter:前补www.后补.net。 ...

    飞奔浏览器 v1.0

    并集成了IE及FireFox的优秀功能于一体,是一款功能强大和灵活的浏览器。 使用说明在地址栏中输入比如"baidu"后,按前补www.后补.com。Alt+Enter前补www.后补.com.cn。本软件使用方便,内置有许多方便的快捷键可以使用...

    bpmn.js 2.0流程编辑器 搭配 Activiti 7.0 进行工作流编辑器集成开发

    BPMN 无处不在,适合所有人 在浏览器中创建、嵌入和扩展 BPMN 图。单独使用它或将其集成到您的应用...3. 集成浏览器内流程引擎、令牌模拟、自定义元素、样式或建模规则。这取决于您,因为 bpmn-js 是一个开放的工具包。

    浏览器插件火山翻译插件

    它无缝集成到浏览器中,允许用户轻松翻译网页、文档和文本片段,无需离开当前页面。插件界面简洁直观,操作简单,为用户提供高效便捷的翻译体验。 适用人群 语言学习者和翻译专业人士。 从事国际业务或与海外客户...

    傲游浏览器2,最新版

    更强的自定义能力, 更强的广告过滤功能, 无缝集成的在线收藏系统, 更完善的 Feed 阅读器, 更强的智能填表, 更快的智能加速, 更炫丽的皮肤支持, 更强的历史功能, 更强的代理功能, 独立用户帐号保护隐私, 影音文件嗅探

    网游轻舟浏览器(SlimBrowser) v8.00.005 官方版.zip

    2. 基于智能识别和自定义过滤表的弹出广告杀手 3. 快速搜索工具条使您可以直接在各大搜索引擎中搜索 4. 在需要的时候隐藏和恢复指定的页面以保护您的隐私 5. 无缝集成RoboForm表单填写器 6. 自动登录:您只要...

    浏览器插件-Web开发者助手 FeHelper

    Edge浏览器,工具集包括 JSON自动/手动格式化、JSON内容比对、代码美化与压缩、信息编解码转换、二维码生成与解码、图片Base64编解码转换、Markdown、 网页油猴、网页取色器、脑图(Xmind)等贴心工具,甚至在目前新...

    良田高拍仪摄像头插件兼容chrome含demo可直接使用

    良田高拍仪兼容chrome进行操作的demo程序,程序需要安装对应的驱动,驱动包含在资源中。控件件支持IE,Chrome,FireFox三大主流浏览器内核,支持Win7,Win8,Win8.1及Win10等操作...12.用户自定义设置 13.图片合成pdf

    lens-elife:Lens的eLife集成与自定义扩展以及官方捆绑包

    eLife镜头 在此处配置Lens的eLife版本。 滴水 您需要Node.js的版本“ 10.x”,我使用在每个项目的基础上...然后在您的Web浏览器中导航到 。 捆绑 npm install npm run bundle 您将在名为dist的文件夹中找到捆绑的版本。

    Bitly (释放链接的力量)-4.2.1.zip

    直接从浏览器复制,自定义和分享您的链接! *更新:在此版本中,我们简化了扩展程序,使标记更容易,并且由于滥用率高和固定的已知错误使用率低而删除了电子邮件共享。 *将您的浏览器内容直接保存到您的Bitly帐户 ...

    淘宝工具栏开发;自定义IE工具栏

    可自定义开发。 淘宝工具栏:为了在浏览任何网页的时候,方便随时可以通过工具栏来查找淘宝中的商品,是...并且集成了上网助手,方便用户清除因上网产生的临时文件,减少系统空间的占用,加快浏览器浏览网页时的存取。

Global site tag (gtag.js) - Google Analytics