VC浏览器相关的学习(二)(BHO)
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)相关推荐
- VC浏览器相关的学习(七)(BHO捕获鼠标键盘事件)
原本想暂时将BHO放放,结果发现了IDispEventImpl 的基类 IDispEventSimpleImpl,原来真正牛逼的方法都在这里呢. 0 #include <mshtmdid.h&g ...
- VC浏览器相关的学习(四)(在BHO中获取IE版本以及获取窗体句柄)
值得注意的是IE6,IE7,IE8的窗体组织完全不一样,需要用VS自带的工具Spy++查看确定 a 获取IE版本 int CMyRock::GetIEVersion() { CComPtr<ID ...
- VC浏览器相关的学习(五)(在BHO中建立对话框)--解决CreateDialog的1813错误
1 添加一个资源Dialog IDD_DIALOG1 2 创建对话框 MyRock.h CMyRock():m_hwndDlg(0) { m_pMyRock = this; } privat ...
- VC浏览器相关的学习(六)(IDispEventImpl包装的主要方法)
IDispEventImpl包装方法对Ajax相当无力,也就是说对Flash也是没辙,娘的又走了弯路,作为几天的总结,IDispEventImpl包装的方法如下: MyRock.h // MyRock ...
- VC浏览器相关的学习(八)(截获IE网络访问)
经过上面进程的学习,已经达到截取网络访问的条件了,需要声明如下: #include <WinInet.h> #pragma comment( lib, "WinInet.lib& ...
- VC浏览器相关的学习(三)(解决IE8无法断点调试)
修改注册表,在HKEY_LOCALMACHINE -> SOFTWARE -> Microsoft -> Internet Explorer -> Main创建一个DWORD类 ...
- VC浏览器相关的学习(一)(Single document界面)
1 MFC建立一个Single document 第一步:Document/View architecture support要打勾,否则第六步不可选 第六步:BaseClass改为C ...
- 前端面试中浏览器相关问题(二):回流与重绘
前端面试中浏览器相关问题(二):回流与重绘 文章目录 前端面试中浏览器相关问题(二):回流与重绘 浏览器的渲染过程 生成渲染树 回流 重绘 何时发生回流重绘 浏览器的优化机制 减少回流和重绘 最小化重 ...
- html笔记(二)html4+css2.0(元素类型、css精灵、宽度自适应、BFC、浏览器相关概述、css统筹)
大标题 小节 一.元素类型 1. 元素分类 2. 置换和非置换元素 3. 元素类型转换 二.css精灵 三.宽高自适应 1. 宽度自适应 2. 高度自适应 3. 最小高度自适应 4. 高度塌陷及解决办 ...
最新文章
- Flask学习之路(一)--初识flask
- c++ Lambda
- mysql sshd_制作Docker镜像之mysqlkeepalivedsshd
- nginx 静态资源WEB服务
- html重绘text,使用DrawText重绘C++
- python之socket
- 云服务器的主机名是否可以修改??
- Android BroadcastReceiver之 静态广播 笔记+demo
- Python基础090:解决jupyter notebook无法自动跳转chrome浏览器的问题
- 科研党 篇一:完成一篇SCI论文必备的20+工具
- 普林斯顿微积分读本07第五章--可导性
- SDRAM 控制器(八)——FIFO控制模块
- linux svn 查看忽略文件,linux下SVN忽略文件/文件夹的方法
- 吐血总结让你的项目管理水平提升最快的19种顶级思维
- 程序员的日常工作是怎样的?
- vscode 的setting.json的配置
- hexo博客首页添加网易云音乐
- JSP中response.sendRedirect()与request.getRequestDispatcher().forward(request,respon 区别
- 39 Spring Boot Shiro权限管理【从零开始学Spring Boot】
- 关于对大一上学期的学习总结及大一下学期的规划。
热门文章
- 基于自适应反向学习的黏菌算法
- OpenGL ES 帧缓冲区位块传送(Blit)
- “金三银四“,敢不敢“试”?
- mysql 1033 Incorrect information in file 错误
- 【备份】使用ubuntu一个月,记录的问题和解决方案
- ajax跨域数据不完整,Ajax交互,浏览器接收不到服务器的Json数据(跨域问题)
- Python Basic Grammar
- 几个java小问题代码(大神不喜勿喷)
- 微信小程序学习第8天——自定义组件的数据监听器Observer小案例
- SpringBoot 默认数据库连接池 HikariCP