BHO

作者: bingo_hzy | 来源:发表于2019-02-21 17:35 被阅读0次

    因为同学新公司的变态要求,禁用IE右键菜单,开始我建议直接用JS实现,同学说不能修改页面源码,估计页面是其他公司的,只好用BHO实现。由于BHO会对所有页面生效,只好在BHO里判断指定页面生效(很变态_)。

    1. 直接创建ATL工程TestBHO,添加类TestBHOCtrl,
    class ATL_NO_VTABLE CTestBHOCtrl :
          public CComObjectRootEx<CComSingleThreadModel>,
          public CComCoClass<CTestBHOCtrl, &CLSID_TestBHOCtrl>,
          public IObjectWithSiteImpl<CTestBHOCtrl>,
          public IDispatchImpl<ITestBHOCtrl, &IID_ITestBHOCtrl, &LIBID_TestBHOLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
          public IDocHostUIHandler,
          public IDispEventImpl <1, CTestBHOCtrl, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
    

    接口说明:
    IObjectWithSiteImpl是ATL对IObjectWithSite的简单封装,一般需重写SetSite,IE在打开和关闭页面时都会调用此接口。
    IDocHostUIHandler是编写本程序的主要目标,重写IDocHostUIHandlerShowContextMenu方法,直接返回S_OK可屏蔽 菜单,也可以在里面弹出自定义菜单。
    IDispEventImpl 是为了截获事件DISPID_DOCUMENTCOMPLETE

    1. COM_MAP中添加COM_INTERFACE_ENTRY(IDocHostUIHandler)

    2. 添加SINK MAP

    BEGIN_SINK_MAP(CTestBHOCtrl) 
          SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) 
    END_SINK_MAP()
    
    1. 主要实现方法:
    void STDMETHODCALLTYPE CTestBHOCtrl::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) 
    { 
        if  (m_spWebBrowser)  
        {  
            CComPtr <IDispatch>  spDoc;  
            m_spWebBrowser->get_Document(&spDoc);  
    
            if  (spDoc)  
            {  
                CComQIPtr <ICustomDoc,  &IID_ICustomDoc>  spCustomDoc(spDoc);  
                if  (spCustomDoc)  
                    spCustomDoc->SetUIHandler(this); //关键 设置我们自己实现的IDocHostUIHandler接口 
            }  
        }  
    
    } 
    
    HRESULT STDMETHODCALLTYPE CTestBHOCtrl::SetSite(IUnknown *pUnkSite)
    {
        ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::SetSite/n"));
        m_spUnkSite = pUnkSite;
    
        if (pUnkSite != NULL) 
        { 
            // Cache the pointer to IWebBrowser2. 
            HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); 
            if (SUCCEEDED(hr)) 
            { 
                // Register to sink events from DWebBrowserEvents2. 
                hr = DispEventAdvise(m_spWebBrowser); 
                if (SUCCEEDED(hr)) 
                { 
                    m_fAdvised = TRUE; 
                } 
            } 
        } 
        else 
        { 
            // Unregister event sink. 
            if (m_fAdvised) 
            { 
                DispEventUnadvise(m_spWebBrowser); 
                m_fAdvised = FALSE; 
            } 
    
            // Release cached pointers and other resources here. 
            m_spWebBrowser.Release(); 
        }
        return S_OK;
    }
    
    HRESULT STDMETHODCALLTYPE CTestBHOCtrl::ShowContextMenu( 
        /* [in] */ DWORD dwID,
        /* [in] */ POINT *ppt,
        /* [in] */ IUnknown *pcmdtReserved,
        /* [in] */ IDispatch *pdispReserved)
    {
        return S_OK; //关键 这里返回S_OK菜单将不会弹出,也可以在这弹出自定义菜单
    }
    

    最后写完,碰到一个问题,就是BHO死活不能被IE加载,因为第一次写,Baidu了一阵,发现需要在rgs文件里添加注册表内容,注册BHO。
    添加以下内容之后,重新生成,一切OK(注:D35AEDEE-555B-46A8-B186-D2AC99A032A4是需要改成自己的CLSID)。

    HKLM 
    {
        NoRemove SOFTWARE
        {
            NoRemove Microsoft 
            {  
                NoRemove Windows 
                {
                    NoRemove CurrentVersion 
                    {
                        NoRemove Explorer 
                        {
                            NoRemove 'Browser Helper Objects' 
                            {
                                ForceRemove '{D35AEDEE-555B-46A8-B186-D2AC99A032A4}' = s 'TestBHO' 
                                {
                                    val 'NoExplorer' = d '1'
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:BHO

          本文链接:https://www.haomeiwen.com/subject/aqjdyqtx.html