• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

            BHO開發(fā)基礎(chǔ)

            在Windows操作系統(tǒng)上,我們最常見的瀏覽器有兩種:文件瀏覽器(exploer.exe,應(yīng)用于文件系統(tǒng))和Internet瀏覽器 (iexplore.exe,應(yīng)用于互聯(lián)網(wǎng)資源)。由于這兩個(gè)瀏覽器功能強(qiáng)大,而且又與Windows操作系統(tǒng)捆綁銷售,最終也就成為了瀏覽器的標(biāo)準(zhǔn)。但 有時(shí)候,為了給瀏覽器加入一些新的特性,我們往往會(huì)重新設(shè)計(jì)一個(gè)自己的瀏覽器。新的瀏覽器模仿標(biāo)準(zhǔn)瀏覽器的大部分功能,同時(shí)加入新特性。這種做法最直觀, 但實(shí)際上也是相對(duì)于微軟的重復(fù)勞動(dòng),且工作量比較大。其實(shí),使用BHO插件,一切都變得很簡(jiǎn)單。

            BHO(Browser Help Objects),是實(shí)現(xiàn)了特定接口的COM組件。開發(fā)好的BHO插件在注冊(cè)表特定的位置注冊(cè)好后,每當(dāng)微軟的瀏覽器啟動(dòng),BHO實(shí)例就會(huì)被創(chuàng)建。在瀏覽 器工作的工程中,BHO會(huì)接收到很多事件,比如瀏覽器瀏覽新的地址、前進(jìn)或后退、生成新的窗口、瀏覽器退出等等;BHO可以在這些事件的響應(yīng)中實(shí)現(xiàn)與瀏覽 器的交互。

            下面,我們首先來介紹一下BHO的工作原理。上面我們已經(jīng)提到,BHO是COM組件,而且一定實(shí)現(xiàn)了IObjectWithSite接口。這些組件除了在 注冊(cè)表中注冊(cè)為COM Server外,還必須將它們的CLSID在HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CurrentVersionExplorerBrowser Helper Objects下注冊(cè)為子鍵。微軟在設(shè)計(jì)瀏覽器的時(shí)候,已經(jīng)給這些組件預(yù)留了空間。每當(dāng)瀏覽器啟動(dòng)時(shí),瀏覽器會(huì)首先在上述注冊(cè)表位置查看是否有注冊(cè)的 BHO CLSID;如果有則分別創(chuàng)建一個(gè)實(shí)例,并對(duì)BHO實(shí)例進(jìn)行初始化,建立交互連接。(注:BHO實(shí)例只有在創(chuàng)建它的瀏覽器窗口銷毀時(shí)才被釋放。)下圖演示 了BHO的創(chuàng)建過程:
            說明 createbho.jpg

            成功創(chuàng)建的BHO,不僅可以得到各種標(biāo)準(zhǔn)的瀏覽器操作事件,并做出響應(yīng);還可以定制瀏覽器的菜單、工具條等界面元素;更或者可以安裝鉤子函數(shù),監(jiān)視瀏覽器 的一舉一動(dòng)。值得注意的是,使用BHO插件,Internet瀏覽器要求在4.0以上版本;如果是文件瀏覽器,操作系統(tǒng)要求是Windows 95/98/2000或Window NT 4.0以上版本,并且Shell的版本在4.71以上。下面是支持BHO特性的系統(tǒng)一覽表:

            Shell版本 操作系統(tǒng)版本 支持BHO
            4.00 Windows 95 and Windows NT 4.0(IE版本為 4.0) 僅IE4.0
            4.71 Windows 95 and Windows NT 4.0(IE版本為 4.0) IE和文件瀏覽器
            4.72 Windows 98 IE和文件瀏覽器
            5.00   Windows 2000 IE和文件瀏覽器

            接下去,筆者就來介紹一下如何開發(fā)BHO插件,開發(fā)環(huán)境為VC6.0(使用ATL),安裝Platform SDK中的Internet Development SDK。首先,啟動(dòng)VC的ATL COM AppWizard,生成一個(gè)項(xiàng)目名為BhoPlugin,其余均采用默認(rèn)設(shè)置。接著,我們就來分步詳細(xì)闡述。
            第一步,增加一個(gè)ATL Object到該項(xiàng)目中。VC菜單Insert->New ATL Object…,在彈出的對(duì)話框中選擇“Internet Explorer Object”,輸入COM類名(在Short Name后輸入EyeOnIE,其它各項(xiàng)會(huì)自動(dòng)生成)。完成后,我們可以看到CEyeOnIE類有一個(gè)基類IObjectWithSiteImpl,這個(gè) 就是實(shí)現(xiàn)IObjectWithSite接口的模版類。
            第二步,實(shí)現(xiàn)IObjectWithSite的接口方法。在這之前,我們要先定義幾個(gè)成員變量:CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> mWebBrowser2,(需要加入#include "ExDisp.h"),用以保存瀏覽器組件的指針;DWORD mCookie,用以保存與瀏覽器的連接ID。IObjectWithSite有兩個(gè)接口方法:SetSite和GetSite。我們只需重載 SetSite就行了。在EyeOnIE.h中增加函數(shù)聲明STDMETHOD(SetSite)(IUnknown *pUnkSite),在EyeOnIE.cpp實(shí)現(xiàn)如下:
            STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
            {
            USES_CONVERSION;

            if (pUnkSite)
            {
            mWebBrowser2 = pUnkSite;
            if (mWebBrowser2)
            {
            return RegisterEventHandler(TRUE);
            }
            }
            return E_FAIL;
            }

            HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
            {
            CComPtr<IConnectionPoint> spCP;
            // Receives the connection point for WebBrowser events
            CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPC(mWebBrowser2);
            HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
            if (FAILED(hr))
            return hr;

            if (inAdvise)
            {
            // Pass the event handlers to the container
            hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
            }
            else
            {
            spCP->Unadvise(mCookie);
            }
            return hr;
            }
            我們可以看到,SetSite的參數(shù)實(shí)際上指向的是瀏覽器組件。在SetSite實(shí)現(xiàn)中,我們首先保存瀏覽器組件指針,然后將該BHO向?yàn)g覽器注冊(cè)為事件處理器。
            第三步,實(shí)現(xiàn)IDispatch接口方法。事件處理也就在IDispatch::Invoke中實(shí)現(xiàn)(各個(gè)事件的ID在ExDispID.h中定義)。 BHO可能會(huì)接收到很多事件,但我們只需要響應(yīng)我們感興趣的那一部分。首先在EyeOnIE.h中增加該函數(shù)的聲明,在EyeOnIE.cpp的實(shí)現(xiàn)中, 筆者試著響應(yīng)瀏覽器瀏覽一個(gè)地址之前發(fā)出的事件 STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
            WORD wFlags, DISPPARAMS * pDispParams,
            VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
            UINT * puArgErr)
            {
            USES_CONVERSION;

            if (!pDispParams)
            return E_INVALIDARG;

            switch (dispidMember)
            {
            //
            // The parameters for this DISPID are as follows:
            // [0]: Cancel flag - VT_BYREF|VT_BOOL
            // [1]: HTTP headers - VT_BYREF|VT_VARIANT
            // [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
            // [3]: Target frame name - VT_BYREF|VT_VARIANT
            // [4]: Option flags - VT_BYREF|VT_VARIANT
            // [5]: URL to navigate to - VT_BYREF|VT_VARIANT
            // [6]: An object that evaluates to the top-level or frame
            // WebBrowser object corresponding to the event.
            //
            case DISPID_BEFORENAVIGATE2 :
            {
            LPOLESTR lpURL = NULL;
            mWebBrowser2->get_LocationURL(&lpURL);
            char * strurl;
            if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
            {
            CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
            varURL.ChangeType(VT_BSTR);
            strurl = OLE2A(varURL.bstrVal);
            }
            if (strstr(strurl, "girl.com"))
            {
            *pDispParams->rgvarg[0].pboolVal = TRUE;
            ::MessageBox(NULL, _T("該網(wǎng)頁已被禁止!"),_T("Warning"),MB_ICONSTOP);
            return S_OK;
            }
            break;
            }

            case DISPID_NAVIGATECOMPLETE2:
            break;
            case DISPID_DOCUMENTCOMPLETE:
            break;
            case DISPID_DOWNLOADBEGIN:
            break;
            case DISPID_DOWNLOADCOMPLETE:
            break;
            case DISPID_NEWWINDOW2:
            break;
            case DISPID_QUIT:
            RegisterEventHandler(FALSE);
            break;
            default:
            break;
            }

            return S_OK;
            }
            我們看到,當(dāng)用戶瀏覽的新地址包含"girl.com"字符的時(shí)候,瀏覽器就會(huì)彈出一個(gè)警告對(duì)話框,并且停止進(jìn)一步的動(dòng)作。另外值得注意的是,在DISPID_QUIT事件(瀏覽器將要退出)的響應(yīng)中,我們將BHO事件處理器進(jìn)行了注銷。
            第四步,因?yàn)锽HO可能會(huì)被文件瀏覽器加載。如果我們不想這樣,我們就要在DllMain中對(duì)加載者進(jìn)行判斷,參考如下:
            extern "C"
            BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
            {
            if (dwReason == DLL_PROCESS_ATTACH)
            {
            // Check who's loading us.
            // If it's Explorer then "no thanks" and exit...
            TCHAR pszLoader[MAX_PATH];
            GetModuleFileName(NULL, pszLoader, MAX_PATH);
            _tcslwr(pszLoader);
            if (_tcsstr(pszLoader, _T("explorer.exe")))
            return FALSE;

            _Module.Init(ObjectMap, hInstance, &LIBID_BHOPLUGINLib);
            DisableThreadLibraryCalls(hInstance);
            }
            else if (dwReason == DLL_PROCESS_DETACH)
            _Module.Term();
            return TRUE; // ok
            }
            最后,別忘了修改注冊(cè)表文件,追加BHO的注冊(cè)信息。在EyeOnIE.rgs文件的下面增加如下代碼:
            HKLM
            {
            SOFTWARE
            {
            Microsoft
            {
            Windows
            {
            CurrentVersion
            {
            Explorer
            {
            'Browser Helper Objects'
            {
            {6E28339B-7A2A-47B6-AEB2-46BA53782379}
            }
            }
            }
            }
            }
            }
            }
            注意,{6E28339B-7A2A-47B6-AEB2-46BA53782379}是筆者這個(gè)BHO的CLSID,如果你自己開發(fā)BHO,這里應(yīng)該正確填寫你的CLSID。

            BHO插件可以實(shí)現(xiàn)的功能還有很多,比如網(wǎng)頁內(nèi)容分析、IE界面定制等等。作為總結(jié),筆者還要提醒讀者一點(diǎn)的是,如果不想讓BHO起作用了,可以注銷該插 件,如下格式:regsvr32 /u yourpathyourbho.dll,或者直接在注冊(cè)表中將“Browser Helper Objects”目錄下注冊(cè)的CLSID刪掉。

            posted on 2007-07-29 14:59 旅途 閱讀(1908) 評(píng)論(0)  編輯 收藏 引用 所屬分類: BHO

            久久精品无码专区免费| 久久久精品2019免费观看| 亚洲欧美日韩精品久久| 国产99久久久国产精免费| 精品久久久一二三区| 中文字幕无码免费久久| 欧美精品一本久久男人的天堂| 武侠古典久久婷婷狼人伊人| 国产美女久久久| 久久久久久久精品成人热色戒| 久久r热这里有精品视频| 久久精品免费网站网| 亚洲综合熟女久久久30p| 伊人色综合久久| 少妇精品久久久一区二区三区| 中文字幕无码久久精品青草 | 无码精品久久久久久人妻中字| 久久久精品人妻一区二区三区蜜桃| 99热成人精品免费久久| 久久久久久久波多野结衣高潮 | 热综合一本伊人久久精品| 久久久久亚洲AV无码专区体验| 久久综合色之久久综合| 国产精品伦理久久久久久| 色综合久久无码五十路人妻| 久久影视综合亚洲| 久久久精品日本一区二区三区| AAA级久久久精品无码片| 精品无码久久久久国产| 伊人伊成久久人综合网777| 99久久精品免费看国产| 久久99精品国产99久久| 狠狠色婷婷久久一区二区三区| 久久国产免费直播| 久久亚洲AV无码精品色午夜麻豆 | 亚洲欧美日韩精品久久| avtt天堂网久久精品| 91精品国产高清久久久久久io| 99久久精品免费国产大片| 99精品国产在热久久| 久久国产精品-久久精品|