<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    1.什么叫BHO

      Browser Helper Objects,"瀏覽器幫助者對象",以下皆簡稱BHO。

    2.支持BHO特性的系統一覽表:

    Shell版本 操作系統版本 支持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和文件瀏覽器

    3.BHO注冊表中的位置

      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\{7C260B4B-F7A0-40B5-B403-

    BEFCDC6A4C3B}
    IE啟動時候根據此項到HKEY_CLASSES_ROOT\CLSID下面找到對應BHO組件加載。

    4.基本邏輯
     
      IE將自己的IUnKnown指針傳遞給BHO,BHO需要建立一個私有的基于COM的通訊通道,目的是響應IE事件。所以BHO最重要的是實現

    IObjectWithSite 接口。IE 通過這個接口,傳遞自己的IUnknown接口,BHO存儲該接口,進一步通過調用IObjectWithSite 提供的方法。

      IE啟動時候會依次執行一些函數,把BHO自己的函數注冊到這里,書面上稱之為連接點。這樣就能調用進入 BHO自己的程序內部了。

    5.IObjectWithSite 介紹

    主要有兩個函數要實現:
     
      a).HRESULT SetSite(IUnknown* pUnkSite)  接收ie瀏覽器的IUnknown指針。典型實現是保存該指針以備將來使用。

      b).HRESULT GetSite(REFIID riid, void** ppvSite)  從通過SetSite()方法設置的場所中接收并返回指定的接口,典型實現是查詢前面保

    存的接口指針以進一步取得指定的接口。

    6.下面通過一個實例來講解下

     目標是啟動IE 訪問 http://m.tkk7.com/JAVA-HE/的時候彈出一個警告對話框。

    a) 首先啟動VC 2005 新建工程 ATL Project
     
       工程名字: HelloWorld
       Application Settings 中,Server type 選擇 Dynamic-link library (dll) 其他都不選。(簡單總結為以atl 創建dll工程)

    b) 其次在新建好的CLASS VIEW下選擇 工程 HelloWorld 右鍵 add -> class

       選擇創建ATL Simple Object ,下一步 在short name中輸入 HelloWorldBHO 其他都自動補齊不用管。
     
       下一步在options中 :

     Threading mode 選擇 Apartment ;
     Aggregation 選擇 no;
     Interface 選擇 Dual
     support 選擇 IObjectWithSite(IE object support)

    點擊Finish ,這是一個最簡單的BHO已經創建好了。

    c) 目前要做的就是添磚了

    編輯 HelloWorldBHO.h 發現系統已經為你創建了 CHelloWorldBHO類, 在類的最下行有一個public: 沒后文,這里就是系統提示你要添加的代

    碼了。

     
      CHelloWorldBHO 中SetSite 已經為你添加將瀏覽器的IUnknown 指針保存下來(見m_spUnkSite);。

      現在要做的是注冊到連接點。
     

    STDMETHOD(SetSite)(IUnknown *pUnkSite)
        {
            IObjectWithSiteImpl
    <CHelloWorldBHO>::SetSite(pUnkSite);
            RegisterEventHandler(TRUE);
            
    return S_OK;
        }

     

      繼承父類的 SetSite方法,顯示調用父類(SetSite)方法,添加一個注冊函數。(就是前面所述的,添加到連接點)
     

    HRESULT RegisterEventHandler(BOOL inAdvise)
        {
            CComPtr
    <IConnectionPoint>spCP;

            m_spWebBrowser2 
    = m_spUnkSite;

            
    if( m_spWebBrowser2 == NULL )
            {
                
    return E_FAIL;
            }

            CComQIPtr
    <IConnectionPointContainer,&IID_IConnectionPointContainer> spCPC(m_spWebBrowser2);
            
            
    if(spCPC == NULL)
            {
                
    return E_FAIL;
            }
            
            
    // 查找到連接點

            HRESULT hr 
    = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);

            
    if(FAILED(hr))
            {
                
    return hr;
            }

            
    if(inAdvise)
            {
                
    // 添加到連接點 (注冊)
                hr = spCP->Advise(reinterpret_cast<IDispatch *>(this), &mCookie);
            }
    else
            {
                
    // 反注冊
                spCP->Unadvise(mCookie);
            }
            
    return hr;
        }

     

     其中成員聲明:

     DWORD mCookie;
     連接點注冊上去的索引,方便以后反注冊使用。

     CComQIPtr<IWebBrowser2> m_spWebBrowser2;

     m_spWebBrowser2 用來將瀏覽器IUnknown 指針轉變為 IWebBrowser2 ,并保存方便后面使用。

     我們可以看到將 IDispatch 接口注冊上去了。 想想 COM組件應用(2)——IUnknown 中寫過的 QueryInterface的應用,我們就知道

    這里把IDispatch 接口注冊上去,說明瀏覽器將可以調用IDispatch 的方法了。

     查IDispatch 接口,主要核心在于實現 Invoke 函數。 

     1 STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
     2         WORD wFlags, DISPPARAMS * pDispParams,
     3         VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
     4         UINT * puArgErr)
     5     {
     6         USES_CONVERSION;
     7         if(!pDispParams)
     8         {
     9             return E_INVALIDARG;
    10         }
    11         switch(dispidMember)
    12         {
    13         case DISPID_BEFORENAVIGATE2:
    14             {
    15                 CComBSTR strUrl;
    16                 if( m_spWebBrowser2 != NULL )
    17                     m_spWebBrowser2->get_LocationURL(&strUrl);
    18 
    19                 if (strUrl == CComBSTR("http://m.tkk7.com/JAVA-HE/"))
    20                 {
    21                     ::MessageBox(NULL, _T("該網頁是我的blog!"),_T("Warning"),MB_ICONSTOP);
    22                     return S_OK;
    23                 }
    24 
    25                 break;
    26             }
    27 
    28         case DISPID_NAVIGATECOMPLETE2:
    29             break;
    30         case DISPID_DOCUMENTCOMPLETE:
    31             break;
    32         case DISPID_DOWNLOADBEGIN:
    33             break;
    34         case DISPID_DOWNLOADCOMPLETE:
    35             break;
    36         case DISPID_NEWWINDOW2:
    37             break;
    38         case DISPID_QUIT:
    39             RegisterEventHandler(FALSE);
    40             break;
    41         default:
    42             break;
    43         }
    44         
    45         return S_OK;        
    46     }


     上面是這次實例的范例代碼。有興趣的朋友可以照著敲下,下面還是講下這個函數里面的一些點:

     I.最佳反注冊時機
      case DISPID_QUIT:
       RegisterEventHandler(FALSE);

     在瀏覽器退出的時候,是最佳反注冊時機,不然可能瀏覽器退出后,你的BHO還在運行哦(有可能)

     II. 有些宏需要引入頭文件
      #include <exdisp.h >
      #include <ExDispid.h>

     III.當要使用ATL 編碼轉換時候在函數開頭引入 USES_CONVERSION; 宏,不過這里如果沒有轉換應用,可以去掉。


    根據支持BHO特性,為了不讓資源管理器加載該BHO,所以在dll main 函數里加入如下代碼判斷是否加載:
    if(dwReason == DLL_PROCESS_ATTACH)
        {
            TCHAR pszLoader[MAX_PATH];

            GetModuleFileName(NULL,pszLoader,MAX_PATH);

            _tcslwr(pszLoader);

            
    if(_tcsstr(pszLoader,_T("explorer.exe")))
            {
                
    return FALSE;

            }
        }

    posted on 2009-08-19 20:48 -274°C 閱讀(2675) 評論(0)  編輯  收藏 所屬分類: C++

    常用鏈接

    留言簿(21)

    隨筆分類(265)

    隨筆檔案(242)

    相冊

    JAVA網站

    關注的Blog

    搜索

    •  

    積分與排名

    • 積分 - 914354
    • 排名 - 40

    最新評論

    主站蜘蛛池模板: 亚洲精品国产成人99久久| 久久久久亚洲精品成人网小说| 亚洲国产美女福利直播秀一区二区 | 亚洲人成网站在线播放2019| 国产成人精品免费视| 亚洲国产成人超福利久久精品| 色老头永久免费网站| 亚洲最大天堂无码精品区| 无码一区二区三区免费视频| 亚洲国产欧洲综合997久久| 国产zzjjzzjj视频全免费| 羞羞视频在线观看免费| 亚洲午夜未满十八勿入网站2| 九九美女网站免费| 亚洲码在线中文在线观看| 成人A级毛片免费观看AV网站| 亚洲av成人一区二区三区观看在线 | www国产亚洲精品久久久日本| 边摸边吃奶边做爽免费视频99 | 一本到卡二卡三卡免费高| 亚洲色精品vr一区二区三区| 日韩免费在线观看视频| 亚洲国产精品久久网午夜| 暖暖免费高清日本一区二区三区| 国产精品亚洲片在线花蝴蝶| 久久久久噜噜噜亚洲熟女综合| 在线播放免费人成毛片乱码| 亚洲导航深夜福利| 免费一级一片一毛片| 久久青草91免费观看| 亚洲色精品三区二区一区| 国产专区一va亚洲v天堂| 99爱在线观看免费完整版| 亚洲色大成网站www尤物| 亚洲精品国产自在久久| 99热这里有免费国产精品| 亚洲日韩精品无码专区加勒比☆| 免费人成在线观看网站视频| 免费国产成人18在线观看| 亚洲另类自拍丝袜第五页| 亚洲美女又黄又爽在线观看|