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