BHO Browser Helper Objects
    1 BHO更像是浏览器的一个插件。
    2 BHO依靠于COM,所以他只对IE生效,对其他浏览器无效。

一 创建一个ATL DLL工程(RockBHO),生成的主要文件:
    RockBHO.cpp  此源文件用于实现通过 DLL 提供 COM 对象的导出
    RockBHO.idl  此源文件可用于定义自定义 COM 接口
    RockBHO.rgs  此资源文件包含注册和取消注册 DLL 时编写和删除的注册表项

二 为工程添加类 -> ATL Simple Object
    Shortname:MyRock
    Apartment: No
    Support: IObjectWithSite
    生成的主要文件
    MyRock.h   此头文件包含 BHO 的类定义
    MyRock.cpp   此源文件是项目的主文件并且包含COM对象

三 重写SetSite
    Internet Explorer 只调用此方法两次,一次用于建立连接,另一次则是在浏览器退出时。
    a MyRock.h

#include <shlguid.h> // IID_IWebBrowser2、DIID_DWebBrowserEvents2等 public: STDMETHOD(SetSite)(IUnknown *pUnkSite); // 重写接口 private: CComPtr<IWebBrowser2> m_spWebBrowser; // 定义私有变量

b MyRock.cpp

STDMETHODIMP CMyRock::SetSite(IUnknown *pUnkSite) { // 初始化期间,浏览器将传递一个对其顶层 IWebBrowser2 接口(我们对其进行缓存处理)的引用。非初始化期间,浏览器将传递 NULL。 if (pUnkSite != NULL) { // 缓存指向 IWebBrowser2 的指针。 pUnkSite->QueryInterface(IID_IWebBrowser2, (void**)&m_spWebBrowser); } else { // 在此释放缓存的指针和其他资源。 m_spWebBrowser.Release(); } // 返回基类实现 return IObjectWithSiteImpl<CMyRock>::SetSite(pUnkSite); }

四 重写DllMain

extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { // BHO 不需要线程级的跟踪,我们可以在 DLL_PROCESS_ATTACH 通知期间调用 DisableThreadLibraryCalls 以避免新线程通知的额外开销。 if (dwReason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hInstance); } return _AtlModule.DllMain(dwReason, lpReserved); }

五 注册BHO,在RockBHO.rgs的末尾加上下面代码:
    a 在注册表里添加一个双字节的NoExplorer=1的键,不让Windows Explorer加载该BHO,因此该BHO只能在ie中运行
    b 实际上下面的格式就是注册表目录结构,HKLM是HKEY_LOCAL_MACHINE的缩写
    c 我们要注册的是类的CLSID

HKLM { NoRemove SOFTWARE { NoRemove Microsoft { NoRemove Windows { NoRemove CurrentVersion { NoRemove Explorer { NoRemove 'Browser Helper Objects' { ForceRemove '{4C4B90DD-CAD8-434D-9C0D-24B99A265038}' = s 'MyRock Class' { val 'NoExplorer' = d '1' } } } } } } } }

六 简单的测试
    a MyRock.h

#include <exdispid.h> // DISPID_DOCUMENTCOMPLETE class ATL_NO_VTABLE CMyRock : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyRock, &CLSID_MyRock>, public IObjectWithSiteImpl<CMyRock>, public IDispatchImpl<IMyRock, &IID_IMyRock, &LIBID_RockBHOLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IDispEventImpl<1, CMyRock, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1> // 用于事件处理 public: void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL); BEGIN_SINK_MAP(CMyRock) SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) END_SINK_MAP() // 事件注册(完成载入) private: BOOL m_fAdvised;

b MyRock.cpp

STDMETHODIMP CMyRock::SetSite(IUnknown* pUnkSite) { if (pUnkSite != NULL) { // 缓存指向 IWebBrowser2 的指针。 HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); if (SUCCEEDED(hr)) { // 注册以从 DWebBrowserEvents2 中汇集事件。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } } else { // 取消注册事件 if (m_fAdvised) { DispEventUnadvise(m_spWebBrowser); m_fAdvised = FALSE; } // 在此释放缓存的指针和其他资源。 m_spWebBrowser.Release(); } // 调用基类实现。 return IObjectWithSiteImpl<CMyRock>::SetSite(pUnkSite); } void STDMETHODCALLTYPE CMyRock::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) { // 从站点检索顶级窗口。 HWND hwnd; HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd); if (SUCCEEDED(hr)) { // 加载页面时输出消息框。 MessageBox(hwnd, L"大家好!", L"BHO", MB_OK); } }

七 调用IE DOM(删除所有Image)
    a MyRock.h

#include <mshtml.h> // DOM 接口 private: void RemoveImages(IHTMLDocument2 *pDocument);

b MyRock.cpp

void STDMETHODCALLTYPE CMyRock::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) { // 从站点检索顶级窗口。 HWND hwnd; HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd); if (SUCCEEDED(hr)) { // 加载页面时输出消息框 // MessageBox(hwnd, L"大家好!", L"BHO", MB_OK); } CComQIPtr<IWebBrowser2> spTempWebBrowser = pDisp; // 此事件是否与顶级浏览器相关联 if (spTempWebBrowser && m_spWebBrowser && m_spWebBrowser.IsEqualObject(spTempWebBrowser)) { // 从浏览器中获取当前文档对象 CComPtr<IDispatch> spDispDoc; hr = m_spWebBrowser->get_Document(&spDispDoc); if (SUCCEEDED(hr)) { // 并查询 HTML 文档 CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc; if (spHTMLDoc != NULL) { // 最后,删除这些图像。 RemoveImages(spHTMLDoc); } } } } void CMyRock::RemoveImages(IHTMLDocument2* pDocument) { CComPtr<IHTMLElementCollection> spImages; // 从 DOM 中获取图像集。 HRESULT hr = pDocument->get_images(&spImages); if (hr == S_OK && spImages != NULL) { // 获取集合中的图像数。 long cImages = 0; hr = spImages->get_length(&cImages); if (hr == S_OK && cImages > 0) { for (int i = 0; i < cImages; i++) { CComVariant svarItemIndex(i); CComVariant svarEmpty; CComPtr<IDispatch> spdispImage; // 按索引从集合中获取图像。 hr = spImages->item(svarItemIndex, svarEmpty, &spdispImage); if (hr == S_OK && spdispImage != NULL) { // 首先,查询通用 HTML 元素接口…… CComQIPtr<IHTMLElement> spElement = spdispImage; if (spElement) { // ……然后请求样式接口。 CComPtr<IHTMLStyle> spStyle; hr = spElement->get_style(&spStyle); // 设置 display="none" 以隐藏图像。 if (hr == S_OK && spStyle != NULL) { static const CComBSTR sbstrNone(L"none"); spStyle->put_display(sbstrNone); } } } } } } }

VC浏览器相关的学习(二)(BHO)相关推荐

  1. VC浏览器相关的学习(七)(BHO捕获鼠标键盘事件)

    原本想暂时将BHO放放,结果发现了IDispEventImpl 的基类 IDispEventSimpleImpl,原来真正牛逼的方法都在这里呢. 0 #include <mshtmdid.h&g ...

  2. VC浏览器相关的学习(四)(在BHO中获取IE版本以及获取窗体句柄)

    值得注意的是IE6,IE7,IE8的窗体组织完全不一样,需要用VS自带的工具Spy++查看确定 a 获取IE版本 int CMyRock::GetIEVersion() { CComPtr<ID ...

  3. VC浏览器相关的学习(五)(在BHO中建立对话框)--解决CreateDialog的1813错误

    1 添加一个资源Dialog IDD_DIALOG1 2 创建对话框      MyRock.h CMyRock():m_hwndDlg(0) { m_pMyRock = this; } privat ...

  4. VC浏览器相关的学习(六)(IDispEventImpl包装的主要方法)

    IDispEventImpl包装方法对Ajax相当无力,也就是说对Flash也是没辙,娘的又走了弯路,作为几天的总结,IDispEventImpl包装的方法如下: MyRock.h // MyRock ...

  5. VC浏览器相关的学习(八)(截获IE网络访问)

    经过上面进程的学习,已经达到截取网络访问的条件了,需要声明如下: #include <WinInet.h> #pragma comment( lib, "WinInet.lib& ...

  6. VC浏览器相关的学习(三)(解决IE8无法断点调试)

    修改注册表,在HKEY_LOCALMACHINE -> SOFTWARE -> Microsoft -> Internet Explorer -> Main创建一个DWORD类 ...

  7. VC浏览器相关的学习(一)(Single document界面)

    1 MFC建立一个Single document     第一步:Document/View architecture support要打勾,否则第六步不可选     第六步:BaseClass改为C ...

  8. 前端面试中浏览器相关问题(二):回流与重绘

    前端面试中浏览器相关问题(二):回流与重绘 文章目录 前端面试中浏览器相关问题(二):回流与重绘 浏览器的渲染过程 生成渲染树 回流 重绘 何时发生回流重绘 浏览器的优化机制 减少回流和重绘 最小化重 ...

  9. html笔记(二)html4+css2.0(元素类型、css精灵、宽度自适应、BFC、浏览器相关概述、css统筹)

    大标题 小节 一.元素类型 1. 元素分类 2. 置换和非置换元素 3. 元素类型转换 二.css精灵 三.宽高自适应 1. 宽度自适应 2. 高度自适应 3. 最小高度自适应 4. 高度塌陷及解决办 ...

最新文章

  1. Flask学习之路(一)--初识flask
  2. c++ Lambda
  3. mysql sshd_制作Docker镜像之mysqlkeepalivedsshd
  4. nginx 静态资源WEB服务
  5. html重绘text,使用DrawText重绘C++
  6. python之socket
  7. 云服务器的主机名是否可以修改??
  8. Android BroadcastReceiver之 静态广播 笔记+demo
  9. Python基础090:解决jupyter notebook无法自动跳转chrome浏览器的问题
  10. 科研党 篇一:完成一篇SCI论文必备的20+工具
  11. 普林斯顿微积分读本07第五章--可导性
  12. SDRAM 控制器(八)——FIFO控制模块
  13. linux svn 查看忽略文件,linux下SVN忽略文件/文件夹的方法
  14. 吐血总结让你的项目管理水平提升最快的19种顶级思维
  15. 程序员的日常工作是怎样的?
  16. vscode 的setting.json的配置
  17. hexo博客首页添加网易云音乐
  18. JSP中response.sendRedirect()与request.getRequestDispatcher().forward(request,respon 区别
  19. 39 Spring Boot Shiro权限管理【从零开始学Spring Boot】
  20. 关于对大一上学期的学习总结及大一下学期的规划。

热门文章

  1. 基于自适应反向学习的黏菌算法
  2. OpenGL ES 帧缓冲区位块传送(Blit)
  3. “金三银四“,敢不敢“试”?
  4. mysql 1033 Incorrect information in file 错误
  5. 【备份】使用ubuntu一个月,记录的问题和解决方案
  6. ajax跨域数据不完整,Ajax交互,浏览器接收不到服务器的Json数据(跨域问题)
  7. Python Basic Grammar
  8. 几个java小问题代码(大神不喜勿喷)
  9. 微信小程序学习第8天——自定义组件的数据监听器Observer小案例
  10. SpringBoot 默认数据库连接池 HikariCP