[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二
生活随笔
收集整理的這篇文章主要介紹了
[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
上一篇文章開發(fā)的RayBHO只是BHO的一個(gè)框架,根本不具備任何功能.
在這篇文章里,我們將使繼續(xù)擴(kuò)展這個(gè)BHO,讓它具備更強(qiáng)的功能.首先我們學(xué)習(xí)如何讓BHO接收IE的事件通知,接者學(xué)習(xí)為ie添加一個(gè)按鈕,并讓BHO對(duì)按鈕做出響應(yīng).
要讓BHO能接收事件通知, 它必須讓處理函數(shù)與瀏覽器事件建立連接點(diǎn). 為響應(yīng)這些事件,它必須實(shí)現(xiàn)IDispEventImpl, ATL提供了一個(gè)默認(rèn)實(shí)現(xiàn),可以幫助簡(jiǎn)化這個(gè)事件處理邏輯。
在RayBHO.h添加:
Java代碼#include?"exdispid.h"?? #include?"shlguid.h"?? #include "exdispid.h"
#include "shlguid.h"
我們的CRayBHO必須派生自IDispEventImpl,修改后的代碼如下:
Java代碼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>?? 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為處理事件提供了一種簡(jiǎn)單安全的方法。
IDispEventImpl與事件路由表配合工作,可以將事件路由到相應(yīng)的處理程序函數(shù)。在例子中,我們將"DocumentComplete"的事件交由OnDocumentComplete函數(shù)進(jìn)行處理.
在public段添加路由表:
Java代碼BEGIN_SINK_MAP(CHelloWorldBHO) ?? SINK_ENTRY_EX(1,?DIID_DWebBrowserEvents2,?DISPID_DOCUMENTCOMPLETE,?OnDocumentComplete) ?? END_SINK_MAP()?? BEGIN_SINK_MAP(CHelloWorldBHO)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
上述聲明中SINK_ENTRY_EX(1,...)中的"1"與接口聲明中的IDispEventImpl<1,....>是對(duì)應(yīng)的,在必要時(shí)可以用于區(qū)分來(lái)自不同接口的事件.
DocumentComplete將被路由到處理函數(shù)OnDocumentComplete:
Java代碼void?STDMETHODCALLTYPE?OnDocumentComplete(IDispatch*?pDisp,?VARIANT*?URL);?? void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* pDisp, VARIANT* URL);
它的參數(shù)和參數(shù)順序與DocumentComplete事件所定義的相同,另請(qǐng)注意,不要試圖從事件處理程序返回值,這是因?yàn)?Internet Explorer 會(huì)忽略任何從 Invoke 返回的值.
我們還聲明了一個(gè)私有變量來(lái)跟蹤事件映射的處理情況
Java代碼BOOL?m_fAdvised;??? BOOL m_fAdvised;
SetSite函數(shù)中必須處理事件派遣:
Java代碼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) ?? ????????????{ ?? ????????????????//注冊(cè)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?? ????{ ?? ????????//取消注冊(cè)事件。 ?? ????????if(m_fAdvised) ?? ????????{ ?? ????????????DispEventUnadvise(m_spWebBrowser); ?? ????????????m_fAdvised=FALSE; ?? ????????} ?? ????????//在此釋放緩存的指針和其他資源。 ?? ????????m_spWebBrowser.Release(); ?? ????????//m_spTarget.Release(); ?? ????} ?? ????//調(diào)用基類實(shí)現(xiàn)。 ?? ????return?IObjectWithSiteImpl<CRayBHO>::SetSite(pUnkSite); ?? }?? 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)
{
//注冊(cè)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
{
//取消注冊(cè)事件。
if(m_fAdvised)
{
DispEventUnadvise(m_spWebBrowser);
m_fAdvised=FALSE;
}
//在此釋放緩存的指針和其他資源。
m_spWebBrowser.Release();
//m_spTarget.Release();
}
//調(diào)用基類實(shí)現(xiàn)。
return IObjectWithSiteImpl<CRayBHO>::SetSite(pUnkSite);
}
我從網(wǎng)上找了一個(gè)OnDocumentComplete函數(shù)的例子并將之修改成范型,它對(duì)HTML Dom進(jìn)行操作,將圖像的屬性設(shè)置為Display:None, 具體操作與javascript類似,不再贅述.
Java代碼void????STDMETHODCALLTYPE???CRayBHO::OnDocumentComplete(IDispatch*pDisp,VARIANT*pvarURL) ?? { ?? ????HRESULT?hr?=?S_OK;? ?? ????//?查詢?IWebBrowser2?接口。? ?? ????CComQIPtr<IWebBrowser2>?spTempWebBrowser?=?pDisp;? ?? ????//?此事件是否與頂級(jí)瀏覽器相關(guān)聯(lián)?? ?? ????if?(spTempWebBrowser?&&?m_spWebBrowser?&&?m_spWebBrowser.IsEqualObject(spTempWebBrowser))? ?? ????{? ?? ????????//?從瀏覽器中獲取當(dāng)前文檔對(duì)象……? ?? ????????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)?{? ?? ????????//?獲取集合中的圖像數(shù)。? ?? ????????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)? ?? ????????????????????{? ?? ????????????????????????//?……然后請(qǐng)求樣式接口。? ?? ????????????????????????CComPtr<IHTMLStyle>?spStyle;? ?? ????????????????????????hr?=?spElement->get_style(&spStyle);? ?? ????????????????????????//?設(shè)置?display="none"?以隱藏圖像。? ?? ????????????????????????if?(hr?==?S_OK?&&?spStyle?!=?NULL)? ?? ????????????????????????{? ?? ????????????????????????????static?const?CComBSTR?sbstrNone(L"none");? ?? ????????????????????????????spStyle->put_display(sbstrNone); ?? ????????????????????????} ?? ????????????????????}? ?? ????????????????}? ?? ????????????}? ?? ????????}? ?? ????}? ?? }?? void STDMETHODCALLTYPE CRayBHO::OnDocumentComplete(IDispatch*pDisp,VARIANT*pvarURL)
{
HRESULT hr = S_OK;
// 查詢 IWebBrowser2 接口。
CComQIPtr<IWebBrowser2> spTempWebBrowser = pDisp;
// 此事件是否與頂級(jí)瀏覽器相關(guān)聯(lián)?
if (spTempWebBrowser && m_spWebBrowser && m_spWebBrowser.IsEqualObject(spTempWebBrowser))
{
// 從瀏覽器中獲取當(dāng)前文檔對(duì)象……
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) {
// 獲取集合中的圖像數(shù)。
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)
{
// ……然后請(qǐng)求樣式接口。
CComPtr<IHTMLStyle> spStyle;
hr = spElement->get_style(&spStyle);
// 設(shè)置 display="none" 以隱藏圖像。
if (hr == S_OK && spStyle != NULL)
{
static const CComBSTR sbstrNone(L"none");
spStyle->put_display(sbstrNone);
}
}
}
}
}
}
}
利用VC++操作HTML并沒有想象中的繁瑣, 你可以開發(fā)出更有趣的東西,比如從數(shù)據(jù)庫(kù)自動(dòng)填表單的BHO等等.
在這篇文章里,我們將使繼續(xù)擴(kuò)展這個(gè)BHO,讓它具備更強(qiáng)的功能.首先我們學(xué)習(xí)如何讓BHO接收IE的事件通知,接者學(xué)習(xí)為ie添加一個(gè)按鈕,并讓BHO對(duì)按鈕做出響應(yīng).
要讓BHO能接收事件通知, 它必須讓處理函數(shù)與瀏覽器事件建立連接點(diǎn). 為響應(yīng)這些事件,它必須實(shí)現(xiàn)IDispEventImpl, ATL提供了一個(gè)默認(rèn)實(shí)現(xiàn),可以幫助簡(jiǎn)化這個(gè)事件處理邏輯。
在RayBHO.h添加:
Java代碼
我們的CRayBHO必須派生自IDispEventImpl,修改后的代碼如下:
Java代碼
DispEventImpl為處理事件提供了一種簡(jiǎn)單安全的方法。
IDispEventImpl與事件路由表配合工作,可以將事件路由到相應(yīng)的處理程序函數(shù)。在例子中,我們將"DocumentComplete"的事件交由OnDocumentComplete函數(shù)進(jìn)行處理.
在public段添加路由表:
Java代碼
上述聲明中SINK_ENTRY_EX(1,...)中的"1"與接口聲明中的IDispEventImpl<1,....>是對(duì)應(yīng)的,在必要時(shí)可以用于區(qū)分來(lái)自不同接口的事件.
DocumentComplete將被路由到處理函數(shù)OnDocumentComplete:
Java代碼
它的參數(shù)和參數(shù)順序與DocumentComplete事件所定義的相同,另請(qǐng)注意,不要試圖從事件處理程序返回值,這是因?yàn)?Internet Explorer 會(huì)忽略任何從 Invoke 返回的值.
我們還聲明了一個(gè)私有變量來(lái)跟蹤事件映射的處理情況
Java代碼
SetSite函數(shù)中必須處理事件派遣:
Java代碼
我從網(wǎng)上找了一個(gè)OnDocumentComplete函數(shù)的例子并將之修改成范型,它對(duì)HTML Dom進(jìn)行操作,將圖像的屬性設(shè)置為Display:None, 具體操作與javascript類似,不再贅述.
Java代碼
利用VC++操作HTML并沒有想象中的繁瑣, 你可以開發(fā)出更有趣的東西,比如從數(shù)據(jù)庫(kù)自動(dòng)填表單的BHO等等.
轉(zhuǎn)載于:https://www.cnblogs.com/jcss2008/archive/2009/05/05/1449654.html
總結(jié)
以上是生活随笔為你收集整理的[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 转载--让搜索引擎优化(SEO)更有效
- 下一篇: (转)你有所不知的HTML發佈Flash