用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之三

接下来,我们要为IE增加一个按钮(注意不是toolbar,toolbar要复杂得多),基本这是一个注册表的魔术.打开RayBHO.rgs, 添加

Java代码 复制代码
  1. HKLM   
  2. {   
  3.     NoRemove Software   
  4.     {   
  5.         NoRemove Microsoft   
  6.         {   
  7.             NoRemove  'Internet Explorer'   
  8.             {   
  9.                 NoRemove Extensions   
  10.                 {   
  11.                     ForceRemove '{1AC31710-6759-484f-A129-A70C55485DA1}'   
  12.                     {   
  13.                         val ButtonText = s 'Hello,World'   
  14.                         val Icon = s  '%MODULE%,201'   
  15.                         val HotIcon = s  '%MODULE%,202'   
  16.                         val CLSID = s  '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'   
  17.                         val ClsidExtension = s  '{057F3E68-6C2E-40A5-A641-E8CF9D6766F3}'   
  18.                         val  'Default Visible'  = s 'yes'   
  19.                     }   
  20.                 }   
  21.             }   
  22.         }   
  23.     }   
  24. }  
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove 'Internet Explorer'
{
NoRemove Extensions
{
ForceRemove '{1AC31710-6759-484f-A129-A70C55485DA1}'
{
val ButtonText = s 'Hello,World'
val Icon = s '%MODULE%,201'
val HotIcon = s '%MODULE%,202'
val CLSID = s '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'
val ClsidExtension = s '{057F3E68-6C2E-40A5-A641-E8CF9D6766F3}'
val 'Default Visible' = s 'yes'
}
}
}
}
}
}



当然,你也可以把这一项放在HKCU(Current User)下,这样的话,该Button只对当前用户起作用.

这些注册表项说明如下:

Java代码 复制代码
  1. ForceRemove '{1AC31710-6759-484f-A129-A70C55485DA1}'  -- 该extersion的CLSID,请自己用GUID这个程序生成.   
  2.   
  3. val ButtonText = s 'Hello,World'  // 按钮上的文字说明   
  4.   
  5. val Icon = s '%MODULE%,201'  // 按钮的图标,可以是icon的绝对路径,也可以和我的例子一样从资源文件里加载.   
  6.   
  7. val HotIcon = s '%MODULE%,202' // 鼠标悬停时按钮的图标,与Icon类似.   
  8.   
  9. val CLSID = s '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'  //该CLSID意思为可执行,此值有特定含义,请小心修改.   
  10.   
  11. val ClsidExtension = s '{057F3E68-6C2E-40A5-A641-E8CF9D6766F3}'  // 这个是RayBHO的CLSID,即表示该按钮的动作连接到RayBHO这个com上,具体值有所不同,必须查询你自己的rgs文件得到.   
  12.   
  13. val 'Default Visible'  = s 'yes' //按钮可见.   
ForceRemove '{1AC31710-6759-484f-A129-A70C55485DA1}' -- 该extersion的CLSID,请自己用GUID这个程序生成.
val ButtonText = s 'Hello,World' // 按钮上的文字说明
val Icon = s '%MODULE%,201' // 按钮的图标,可以是icon的绝对路径,也可以和我的例子一样从资源文件里加载.
val HotIcon = s '%MODULE%,202'// 鼠标悬停时按钮的图标,与Icon类似.
val CLSID = s '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}' //该CLSID意思为可执行,此值有特定含义,请小心修改.
val ClsidExtension = s '{057F3E68-6C2E-40A5-A641-E8CF9D6766F3}' // 这个是RayBHO的CLSID,即表示该按钮的动作连接到RayBHO这个com上,具体值有所不同,必须查询你自己的rgs文件得到.
val 'Default Visible' = s 'yes'//按钮可见.



当然你也可以不使用COM来响应按钮的动作,另外两个键Exec和Script,可以设置响应的程序或者脚本..这个不是重点.

现在编译,然后从IE的自定义工具栏将这个按钮拖出来...如图所示:



点点看.....结果呢? 当然是不起作用!

因为除以上步骤外,该com 对象还必须实现 IOleCommandTarget接口。

IOleCommandTarget包含QueryStatus和Exec两个方法,其中QueryStatus方法会被IE调用来获得当前菜单的状态. 当工具条按钮被点击时,com 对象的 IOleCommandTarget::exec 方法被调用,此时ncmdid 的值为 1;当菜单项被点击时,ncmdid 的值为 2。这样开发者就能区分工具条按钮和菜单项这两个不同操作

首先让CRayBHO继承IOleCommandTarget接口,最后我们得到这样得一个继承树

Java代码 复制代码
  1. class  ATL_NO_VTABLE CRayBHO :   
  2.      public  CComObjectRootEx<CComSingleThreadModel>,   
  3.      public  CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,   
  4.      public  IObjectWithSiteImpl<CHelloWorldBHO>,   
  5.      public  IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldPluginLib, /*wMajor =*/  1 /*wMinor =*/  0 >,   
  6.      public  IDispEventImpl<1 ,CHelloWorldBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1 ,1 >,   
  7.      public  IOleCommandTarget  
class ATL_NO_VTABLE CRayBHO :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,
public IObjectWithSiteImpl<CHelloWorldBHO>,
public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldPluginLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispEventImpl<1,CHelloWorldBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1>,
public IOleCommandTarget



再COM_MAP里增加

Java代码 复制代码
  1. COM_INTERFACE_ENTRY(IOleCommandTarget)  
COM_INTERFACE_ENTRY(IOleCommandTarget)



最终得到

Java代码 复制代码
  1. BEGIN_COM_MAP(CHelloWorldBHO)   
  2.     COM_INTERFACE_ENTRY(IHelloWorldBHO)   
  3.     COM_INTERFACE_ENTRY(IObjectWithSite)   
  4.     COM_INTERFACE_ENTRY(IOleCommandTarget)   
  5.     COM_INTERFACE_ENTRY(IDispatch)   
  6. END_COM_MAP()  
	BEGIN_COM_MAP(CHelloWorldBHO)
COM_INTERFACE_ENTRY(IHelloWorldBHO)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY(IOleCommandTarget)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()



声明IOleCommandTarget的两个方法

Java代码 复制代码
  1. // IOleCommandTarget   
  2. STDMETHOD(Exec)( const  GUID*, DWORD nCmdID, DWORD, VARIANTARG*, VARIANTARG* pvaOut);   
  3. STDMETHOD(QueryStatus)( const  GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText);  
	// IOleCommandTarget
STDMETHOD(Exec)(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, VARIANTARG* pvaOut);
STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText);



然后实现之,基本我们的重点放在Exec方法上...所以先给出QueryStatus的实现

Java代码 复制代码
  1. STDMETHODIMP CRayBHO::QueryStatus(const  GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText)   
  2. {   
  3.     if  (cCmds == 0 return  E_INVALIDARG;   
  4.      if  (prgCmds == 0 return  E_POINTER;   
  5.     prgCmds[ 0 ].cmdf = OLECMDF_ENABLED;   
  6.        
  7.     return  S_OK;   
  8. }  
STDMETHODIMP CRayBHO::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText)
{
if (cCmds == 0) return E_INVALIDARG;
if (prgCmds == 0) return E_POINTER;
prgCmds[0].cmdf = OLECMDF_ENABLED;
return S_OK;
}




在Exce方法中,可以放入你的响应逻辑,或者更简单的,只是一个MessageBox响应. 这里我给出一段实际的Video Player的代码,这个代码可以为按钮添加下拉菜单,而这个菜单实际是保存在资源文件中的!并且你可以看到如何在Exce响应菜单上点击事件.

Java代码 复制代码
  1. STDMETHODIMP CRayBHO::Exec( const  GUID*, DWORD nCmdID, DWORD, VARIANTARG*, VARIANTARG*)   
  2. {   
  3.     if (m_spUnkSite == 0  || m_spWebBrowser == 0 return  S_OK;   
  4.     HRESULT hRes = S_OK;   
  5.   
  6.     CComPtr<IDispatch>        pDocDisp;   
  7.     CComQIPtr<IHTMLDocument2> pHtmlDoc2;   
  8.     hRes = m_spWebBrowser->get_Document(&pDocDisp);   
  9.   
  10.      if (SUCCEEDED(hRes) && pDocDisp)   
  11.     {   
  12.         hRes = pDocDisp->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);   
  13.          if (SUCCEEDED(hRes) && pHtmlDoc2)   
  14.         {   
  15.             SHANDLE_PTR nBrowser = 0 ;   
  16.             m_spWebBrowser->get_HWND(&nBrowser);   
  17.             HWND hWndParent = (HWND)nBrowser;   
  18.   
  19.             POINT pt;   
  20.             GetCursorPos(&pt);   
  21.   
  22.             HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();   
  23.   
  24.             HMENU hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU_POPUP));   
  25.             HMENU hMenuTrackPopup = GetSubMenu(hMenu, 0 );   
  26.                
  27.             if (hMenuTrackPopup && hWndParent)   
  28.             {   
  29.                 BOOL bIsChevron = FALSE;   
  30.                 HWND hWndMenuParent = NULL;   
  31.                 HWND hWndToolBar = NULL;   
  32.                    
  33.                 hWndMenuParent = hWndParent;   
  34.                 hWndToolBar = WindowFromPoint(pt);   
  35.                    
  36.                  if (m_bIsIe7)   
  37.                 {   
  38.                     HWND hWndIe7ActiveTab = hWndParent;   
  39.                     HWND hWnd = GetWindow(hWndParent, GW_CHILD);   
  40.   
  41.                      // looking for the Internet Explorer_Server window   
  42.                      // this window should be a parent for TrackPopupMenu   
  43.                      if (hWnd)   
  44.                     {   
  45.                         TCHAR szClassName[MAX_PATH];   
  46.                          while (hWnd)   
  47.                         {   
  48.                             memset(szClassName,0 ,MAX_PATH);   
  49.                             GetClassName(hWnd, szClassName, MAX_PATH);   
  50.                             if (_tcscmp(szClassName,_T("TabWindowClass" ))==0 )   
  51.                             {   
  52.                                 // the active tab should be visible   
  53.                                  if (IsWindowVisible(hWnd))   
  54.                                 {   
  55.                                     hWnd = GetWindow(hWnd, GW_CHILD);   
  56.                                      while (hWnd)   
  57.                                     {   
  58.                                         memset(szClassName,0 ,MAX_PATH);   
  59.                                         GetClassName(hWnd, szClassName, MAX_PATH);   
  60.   
  61.                                          if (_tcscmp(szClassName,_T("Shell DocObject View" ))==0 )   
  62.                                         {   
  63.                                             hWnd = FindWindowEx(hWnd, NULL, _T("Internet Explorer_Server" ), NULL);   
  64.                                              if (hWnd) hWndIe7ActiveTab = hWnd;   
  65.                                              break ;   
  66.                                         }   
  67.                                         hWnd = GetWindow(hWnd, GW_HWNDNEXT);   
  68.                                     }   
  69.                                 }   
  70.                             }   
  71.                             hWnd = GetWindow(hWnd, GW_HWNDNEXT);   
  72.                         }   
  73.                     }   
  74.   
  75.                     if (hWndIe7ActiveTab) hWndMenuParent = hWndIe7ActiveTab;   
  76.   
  77.                     //strHWndMenuParent = _ltoa(hWndMenuParent, 10);   
  78.                 }   
  79.   
  80.                  int  nIDCommand = -1 ;   
  81.                 BOOL bRightAlign = FALSE;   
  82.                 if (hWndToolBar)   
  83.                 {   
  84.                     ScreenToClient(hWndToolBar,&pt);   
  85.                      int  nButton = (int )::SendMessage(hWndToolBar, TB_HITTEST, 0 , (LPARAM)&pt);   
  86.                      if (nButton>0 )   
  87.                     {   
  88.                         TBBUTTON pTBBtn;   
  89.                         memset(&pTBBtn, 0 ,sizeof(TBBUTTON));   
  90.                          if (::SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn))   
  91.                         {   
  92.                             nIDCommand = pTBBtn.idCommand;   
  93.                             RECT rcButton;   
  94.                             if (::SendMessage(hWndToolBar,TB_GETRECT,nIDCommand,(LPARAM)&rcButton))   
  95.                             {   
  96.                                 pt.x = rcButton.left;   
  97.                                 pt.y = rcButton.bottom;   
  98.                                 ClientToScreen(hWndToolBar,&pt);   
  99.   
  100.                                 RECT rcWorkArea;   
  101.                                 SystemParametersInfo(SPI_GETWORKAREA, 0 ,(LPVOID)&rcWorkArea,0 );   
  102.                                  if (rcWorkArea.right-pt.x<150 )   
  103.                                 {   
  104.                                     bRightAlign = TRUE;   
  105.                                     pt.x = rcButton.right;   
  106.                                     pt.y = rcButton.bottom;   
  107.                                     ClientToScreen(hWndToolBar,&pt);   
  108.                                 }   
  109.                             }   
  110.                         }   
  111.                     }   
  112.                     else   
  113.                     {   
  114.                         GetCursorPos(&pt);   
  115.                         bIsChevron = TRUE;   
  116.                     }   
  117.                 }   
  118.   
  119.                 UINT nFlags = TPM_NONOTIFY|TPM_RETURNCMD|TPM_LEFTBUTTON;   
  120.                 if (bRightAlign) nFlags |= TPM_RIGHTALIGN;   
  121.                  else  nFlags |= TPM_LEFTALIGN;   
  122.   
  123.                 // draw pressed button   
  124.                  if (nIDCommand!=-1  && !bIsChevron) ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nIDCommand,  MAKELPARAM(1 ,0 ));   
  125.                  // popup the menu   
  126.                  int  nCommand = TrackPopupMenu(hMenuTrackPopup, nFlags, pt.x, pt.y, 0 , hWndMenuParent, 0 );   
  127.                  // release the button   
  128.                  if (nIDCommand!=-1  && !bIsChevron) ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nIDCommand,  MAKELPARAM(0 ,0 ));   
  129.                    
  130.                 //CStringArray* m_EvNameArr = new CStringArray();   
  131.                  //m_EvNameArr->Add(strHWndMenuParent);   
  132.   
  133.                 BOOL bFound = FALSE;   
  134.                  switch  (nCommand)   
  135.                 {   
  136.                 case  ID_CHIMP:   
  137.                     {   
  138.                         MessageBox(hWndParent,_T("Play Video" ),_T("IEVideo --Ray" ), MB_OK|MB_ICONEXCLAMATION);   
  139.                     }   
  140.                     break ;   
  141.                  case  ID_SELECT:   
  142.                     {   
  143.                         MessageBox(hWndParent,_T("Select Video" ),_T("IEVideo --Ray" ), MB_OK|MB_ICONEXCLAMATION);   
  144.   
  145.                     }   
  146.                      break ;   
  147.                  case  ID_STOP:   
  148.                     {   
  149.                         MessageBox(hWndParent,_T("Stop Video" ),_T("IEVideo --Ray" ), MB_OK|MB_ICONEXCLAMATION);   
  150.                     }   
  151.                     break ;   
  152.                  case  ID_ABOUT:   
  153.                     {      
  154.                         MessageBox(hWndParent,_T("About IEVideo" ),_T("IEVideo --Ray" ), MB_OK|MB_ICONEXCLAMATION);   
  155.                     }   
  156.                     break ;   
  157.                 }   
  158.             }   
  159.         }   
  160.     }   
  161.      return  S_OK;   



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
BHO(Browser Helper Object,浏览器辅助对象,简称BHO)   BHO是微软推出的作为浏览器对第三方程序员开放交互接口的业界标准,通过简单的代码就可以进入浏览器领域的“交互接口”(INTERACTIVED Interface)。通过这个接口,程序员可以编写代码获取浏览器的行为,比如“后退”、“前进”、“当前页面”等,利用BHO的交互特性,程序员还可以用代码控制浏览器行为,比如修改替换浏览器工具栏,添加自己的程序按钮等。这些在系统看来都是没有问题的。BHO原来的目的是为了更好的帮助程序员打造个性化浏览器,以及为程序提供更简洁的交互功能,现在很多IE个性化工具就是利用BHO的来实现。 编辑本段 技术优势   “浏览器劫持”是一种不同于普通病毒木马感染途径的网络攻击手段,而是使用各种技术(如DLL插件等)插件对用户的浏览器进行篡改。安装后,它们会成为浏览器的一部分,可以直接控制浏览器进行指定的操作,根据需要,可以让你打开指定的网站,甚至是收集你系统中的各种私密信息。最可怕的是只有当浏览器已经被劫持了,你才会发现,反应过来,原来电脑已经出现了问题。比如IE主页被改,开机就会弹出广告等等。目前,浏览器劫持已经成为Internet用户最大的威胁之一。其实“浏览器劫持”就是通过BHO的技术手段进入你的系统的,而这种技术是合法的。   从某种观点看,Internet Explorer同普通的Win32程序没有什么两样。借助于BHO,你可以写一个进程内COM对象,这个对象在每次启动时都要加载。这样的对象会在与浏览器相同的上下文中运行,并能对可用的窗口和模块执行任何行动。例如,一个BHO能够探测到典型的事件,如GoBack、GoForward、DocumentComplete等;另外BHO能够存取浏览器的菜单与工具栏并能做出修改,还能够产生新窗口来显示当前网页的一些额外信息,还能够安装钩子以监控一些消息和动作。 编辑本段 注册表位置   BHO在注册表中的位置是:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects,有兴趣的朋友可以在这里做做实验。不过一定要记住你更改的每一步,否则会出错的哦!   BHO对象依托于浏览器主窗口。实际上,这意味着一旦一个浏览器窗口产生,一个新的BHO对象实例就要生成。任何 BHO对象浏览器实例的生命周期是一致的。其次, BHO仅存在于Internet Explorer 4.0及以后版本中。   如果你在使用Microsoft Windows? 98, Windows 2000, Windows 95, or Windows NT版本4.0 操作系统的话,也就一块运行了活动桌面外壳4.71,BHO也被 Windows资源管理器所支持。 BHO是一个COM进程内服务,注册于注册表中某一键下。在启动时,Internet Explorer查询那个键并把该键下的所有对象预以加载。   迅雷中TDAtOnce_Now.dll和xunleiBHO_Now.dll为安全   如何发现BHO里面的危险模块.   首先有一个能够查看进程的软件 冰刃就不错 下面以它为例:   先打开冰刃—会看到一个BHO在这里就可以看到危险BHO进程了

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值