原文发表于
blogs.ejb.cc,版权为Ray_linn所有。
上一篇文章开发的RayBHO只是BHO的一个框架,根本不具备任何功能.
在这篇文章里,我们将使继续扩展这个BHO,让它具备更强的功能.首先我们学习如何让BHO接收IE的事件通知,接者学习为ie添加一个按钮,并让BHO对按钮做出响应.
要让BHO能接收事件通知, 它必须让处理函数与浏览器事件建立连接点. 为响应这些事件,它必须实现IDispEventImpl, ATL提供了一个默认实现,可以帮助简化这个事件处理逻辑。
在RayBHO.h添加:
#include "exdispid.h"
#include "shlguid.h"
我们的CRayBHO必须派生自IDispEventImpl,修改后的代码如下:
class ATL_NO_VTABLE CRayBHO :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CRayBHO, &CLSID_RayBHO>,
public IObjectWithSiteImpl<CRayBHO>,
public IDispatchImpl<IRayBHO, &IID_IRayBHO, &LIBID_MySolutionPluginLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispEventImpl<1,CRayBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1>
DispEventImpl为处理事件提供了一种简单安全的方法。
IDispEventImpl与事件路由表配合工作,可以将事件路由到相应的处理程序函数。在例子中,我们将"DocumentComplete"的事件交由OnDocumentComplete函数进行处理.
在public段添加路由表:
BEGIN_SINK_MAP(CHelloWorldBHO)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
上述声明中SINK_ENTRY_EX(1,...)中的"1"与接口声明中的IDispEventImpl<1,....>是对应的,在必要时可以用于区分来自不同接口的事件.
DocumentComplete将被路由到处理函数OnDocumentComplete:
void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* pDisp, VARIANT* URL);
它的参数和参数顺序与DocumentComplete事件所定义的相同,另请注意,不要试图从事件处理程序返回值,这是因为 Internet Explorer 会忽略任何从 Invoke 返回的值.
我们还声明了一个私有变量来跟踪事件映射的处理情况
BOOL m_fAdvised;
SetSite函数中必须处理事件派遣:
STDMETHODIMP CRayBHO::SetSite(IUnknown*pUnkSite)
{
if(pUnkSite!=NULL)
{
HRESULT hr;
CComPtr<IServiceProvider> sp;
hr = pUnkSite->QueryInterface(&sp);
if(SUCCEEDED(hr) && sp)
{
//缓存指向IWebBrowser2的指针
hr = sp->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&m_spWebBrowser);
if(SUCCEEDED(hr)&&m_spWebBrowser!=0)
{
//注册DWebBrowserEvents2事件。
hr=DispEventAdvise(m_spWebBrowser2);
if(SUCCEEDED(hr))
{
m_fAdvised=TRUE;
}
}
}
m_spUnkSite = pUnkSite;
this->m_bIsIe7=this->IsIE7();
//hr = sp->QueryInterface(IID_IOleCommandTarget,(void**)&m_spTarget);
//this->GetInternetExplorerVersion();
}
else
{
//取消注册事件。
if(m_fAdvised)
{
DispEventUnadvise(m_spWebBrowser);
m_fAdvised=FALSE;
}
//在此释放缓存的指针和其他资源。
m_spWebBrowser.Release();
//m_spTarget.Release();
}
//调用基类实现。
return IObjectWithSiteImpl<CRayBHO>::SetSite(pUnkSite);
}
我从网上找了一个OnDocumentComplete函数的例子并将之修改成范型,它对HTML Dom进行操作,将图像的属性设置为Display:None, 具体操作与javascript类似,不再赘述.
void STDMETHODCALLTYPE CRayBHO::OnDocumentComplete(IDispatch*pDisp,VARIANT*pvarURL)
{
HRESULT hr = S_OK;
// 查询 IWebBrowser2 接口。
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 CRayBHO::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++操作HTML并没有想象中的繁琐, 你可以开发出更有趣的东西,比如从数据库自动填表单的BHO等等.
分享到:
相关推荐
a little bit huge FUcking guy this bitch web!
欧胜微电子有限公司(伦敦股票交易所:WLF.L)日前宣布:作为世界上音效最好的音频数字模拟转换器(DAC),其AudioPlus Pure Sound高端...Akurate DS是Linn产品中的第二充分利用了欧胜WM8741优点的设计。 Linn的器件选
AT指令集 全球定位系统(GPS)系统由于性能优异,在民用上应用范围很广。其可以用于空中交通管理、大地精密测量、摄影测量、监测地壳运动、火山活动、野外调查和勘探的...本文主要介绍与短消息开发相关的GSM AT指令。
NULL 博文链接:https://raylinn.iteye.com/blog/650850
工具“l9000cassdecode”可用于对 Linn9000 和 LinnSequencer 的数据盒(磁带)格式进行解码。 根据数据盒内容,提取 Linn9000 相关文件,例如以下文件类型:DSQ、MSQ、ALL、ASQ、ADS、AMS、ALM、SND、KIT。 可选:...
根据数据盒带的内容,提取与Linn9000相关的文件,例如,使用以下文件类型:DSQ,MSQ,ALL,ASQ,ADS,AMS,ALM,SND,KIT。 可选:tar文件导出。 注意:例如,可以通过包含在项目“ linn9000fs”中的工具“ l9000fs...
NULL 博文链接:https://raylinn.iteye.com/blog/743336
NULL 博文链接:https://raylinn.iteye.com/blog/670006
NULL 博文链接:https://raylinn.iteye.com/blog/520213
linn-gaarder-js1-ca
Linn-Wilhelmsen-js1-ma1
在 Kinsky 中创建播放列表很棒,我想远程保存它们,如果您使用 Linn 的 Songbox,您可以这样做。 播放列表上的每个曲目都是一个 URI,它允许灵活地从多个媒体服务器创建播放列表,此外元数据的 URI 也与播放列表中的...
这是一个直接在Volumio系统上安装BubbleUPnP Server的帮助程序工具。 可用于流化潮汐和Qobuz(使用MDP)。 您需要的是OpenHome渲染器应用程序,例如Linn Kazoo,Lumin等。 默认情况下, BubbleUPnP服务器正在使用...
用亲和层析法从PhaseoZus lunatus Linn vel aff的种子中纯化出一种对人类A型血专一的凝集素.该凝集素的粗浸提液都只对A型血细胞凝集,而对 B、O型绝不凝集.当纯化的凝集素浓度为0.98μg/mL时,即能凝集A型血细胞,...
如果满足以下条件,则允许以源代码和二进制形式进行重新分发和使用,无论是否经过修改,都可以: 重新分发源代码必须保留上述版权声明,此条件列表和以下免责声明。 二进制形式的重新分发必须在分发随附的文档和/或...
快来体验MinGW64 for Windows 64,即x86_64-w64-mingw32,这是 GCC 在 Windows 平台上的移植,和 Cygwin 不...目前版本 4.7.0 ,该发布由我(ray_linn)编译,如发现任何问题,请到 http://mingw-w64.sf.net/上提问。
使用ANTLR之后,我在一天之内就完成了整个编译器前端的开发工作,从而能够迅速开始处理真正的业务逻辑。从那时起,我就被它强大的功能所深深吸引。简而言之,ANTLR能够解决别的工具无法解决的问题。 软件改变了...
采用乙醇浸提法对飞扬草多酚进行提取,并开展了飞扬草多酚...抗氧化性研究表明,飞扬草提取液能清除・OH自由基,在多酚质量浓度为3.759 mg/mL时,清除率约为50%,说明清除能力较强,这为飞扬草药用开发和利用奠定了理论基础。
D-Link路由器当交换机配置步骤.doc