[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二
生活随笔
收集整理的這篇文章主要介紹了
[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一篇文章開發的RayBHO只是BHO的一個框架,根本不具備任何功能.
在這篇文章里,我們將使繼續擴展這個BHO,讓它具備更強的功能.首先我們學習如何讓BHO接收IE的事件通知,接者學習為ie添加一個按鈕,并讓BHO對按鈕做出響應.
要讓BHO能接收事件通知, 它必須讓處理函數與瀏覽器事件建立連接點. 為響應這些事件,它必須實現IDispEventImpl, ATL提供了一個默認實現,可以幫助簡化這個事件處理邏輯。
在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為處理事件提供了一種簡單安全的方法。
IDispEventImpl與事件路由表配合工作,可以將事件路由到相應的處理程序函數。在例子中,我們將"DocumentComplete"的事件交由OnDocumentComplete函數進行處理.
在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,....>是對應的,在必要時可以用于區分來自不同接口的事件.
DocumentComplete將被路由到處理函數OnDocumentComplete:
Java代碼void?STDMETHODCALLTYPE?OnDocumentComplete(IDispatch*?pDisp,?VARIANT*?URL);?? void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* pDisp, VARIANT* URL);
它的參數和參數順序與DocumentComplete事件所定義的相同,另請注意,不要試圖從事件處理程序返回值,這是因為 Internet Explorer 會忽略任何從 Invoke 返回的值.
我們還聲明了一個私有變量來跟蹤事件映射的處理情況
Java代碼BOOL?m_fAdvised;??? BOOL m_fAdvised;
SetSite函數中必須處理事件派遣:
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) ?? ????????????{ ?? ????????????????//注冊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); ?? }?? 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類似,不再贅述.
Java代碼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); ?? ????????????????????????} ?? ????????????????????}? ?? ????????????????}? ?? ????????????}? ?? ????????}? ?? ????}? ?? }?? 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等等.
在這篇文章里,我們將使繼續擴展這個BHO,讓它具備更強的功能.首先我們學習如何讓BHO接收IE的事件通知,接者學習為ie添加一個按鈕,并讓BHO對按鈕做出響應.
要讓BHO能接收事件通知, 它必須讓處理函數與瀏覽器事件建立連接點. 為響應這些事件,它必須實現IDispEventImpl, ATL提供了一個默認實現,可以幫助簡化這個事件處理邏輯。
在RayBHO.h添加:
Java代碼
我們的CRayBHO必須派生自IDispEventImpl,修改后的代碼如下:
Java代碼
DispEventImpl為處理事件提供了一種簡單安全的方法。
IDispEventImpl與事件路由表配合工作,可以將事件路由到相應的處理程序函數。在例子中,我們將"DocumentComplete"的事件交由OnDocumentComplete函數進行處理.
在public段添加路由表:
Java代碼
上述聲明中SINK_ENTRY_EX(1,...)中的"1"與接口聲明中的IDispEventImpl<1,....>是對應的,在必要時可以用于區分來自不同接口的事件.
DocumentComplete將被路由到處理函數OnDocumentComplete:
Java代碼
它的參數和參數順序與DocumentComplete事件所定義的相同,另請注意,不要試圖從事件處理程序返回值,這是因為 Internet Explorer 會忽略任何從 Invoke 返回的值.
我們還聲明了一個私有變量來跟蹤事件映射的處理情況
Java代碼
SetSite函數中必須處理事件派遣:
Java代碼
我從網上找了一個OnDocumentComplete函數的例子并將之修改成范型,它對HTML Dom進行操作,將圖像的屬性設置為Display:None, 具體操作與javascript類似,不再贅述.
Java代碼
利用VC++操作HTML并沒有想象中的繁瑣, 你可以開發出更有趣的東西,比如從數據庫自動填表單的BHO等等.
轉載于:https://www.cnblogs.com/jcss2008/archive/2009/05/05/1449654.html
總結
以上是生活随笔為你收集整理的[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之二的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转载--让搜索引擎优化(SEO)更有效
- 下一篇: Tab菜单切换效果