因为同学新公司的变态要求,禁用IE右键菜单,开始我建议直接用JS实现,同学说不能修改页面源码,估计页面是其他公司的,只好用BHO实现。由于BHO会对所有页面生效,只好在BHO里判断指定页面生效(很变态_)。
- 直接创建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
是编写本程序的主要目标,重写IDocHostUIHandler
的ShowContextMenu
方法,直接返回S_OK
可屏蔽 菜单,也可以在里面弹出自定义菜单。
IDispEventImpl
是为了截获事件DISPID_DOCUMENTCOMPLETE
。
-
在
COM_MAP
中添加COM_INTERFACE_ENTRY(IDocHostUIHandler)
-
添加SINK MAP
BEGIN_SINK_MAP(CTestBHOCtrl)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
- 主要实现方法:
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'
}
}
}
}
}
}
}
}
网友评论