科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件利用MFC实现浏览器的定制与扩展

利用MFC实现浏览器的定制与扩展

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

由于本人在开发中经常要在程序中嵌入浏览器,为了符合自己的需求经常要对浏览器进行扩展和定制。

作者:李汉鹏 来源:VCKBASE 2007年10月19日

关键字: MFC 浏览器 定制 扩展

  • 评论
  • 分享微博
  • 分享邮件
前言

  由于本人在开发中经常要在程序中嵌入浏览器,为了符合自己的需求经常要对浏览器进行扩展和定制, 解决这些问题需在网上找资料和学习的过程,我想可能很多开发者或许会遇到同样的问题,特写此文,以供大家参考。

  在MFC中使用浏览器

  在MFC中微软为我们提供了CHtmlView、CDHtmlDialog类让我们的程序很方便的嵌入浏览器和进行浏览器的二次开发,这比直 接使用WebBrowser控件要方便很多,所以本文中讨论的浏览器的问题都是针对CHtmlView来讨论的。文中将提到一个类CLhpHtmlView, 它是CHtmlView的派生类,文中提及的扩展或定制都将在CLhpHtmlView类(或派生类)上实现。

  怎样扩展或定制浏览器

  浏览器定义了一些扩展接口(如IDocHostUIHandler可以定制浏览器界面有关的行为),以便开发者进行定制和扩展。浏览 器会在需要的时候向他的控制站点查询这些接口,在控制站点里实现相应的接口就可以进行相应的扩展。在MFC7.01类 库中,CHtmlView使用的控制站点是CHtmlControlSite的,在CHtmlControlSite类中 只实现了接口IDocHostUIHandler, 而要实现更多的扩展接口,必须用自定义的控制站类来取代CHtmlControlSite,在下文中提及的类CDocHostSite即为自定义 的控制站类。
  如何使自定义的控制站点来替换默认的控制站点呢?在MFC7.0中只需重载CHtmlView的虚函数CreateControlSite即可: 
BOOL CLhpHtmlView::CreateControlSite(COleControlContainer * pContainer, 
COleControlSite ** ppSite, UINT /*nID*/, REFCLSID /*clsid*/){ *ppSite = new CDocHostSite(pContainer, this);

// 创建自己的控制站点实例 return (*ppSite) ? TRUE : FALSE;}

  VC6.0要替换控制站要复杂的多,这里就不讨论了。

  定制鼠标右键弹出出菜单

  要定制浏览器的鼠标右键弹出菜单,必须在自定义的控制站点类中实现IDocHostUIHandler2接口,并且IE的 版本是5.5或以上。在接口IDocHostUIHandler2的ShowContextMenu方法中调用浏览器类的OnShowContextMenu虚函数,我们 在浏览器类的派生类重载此虚函数即可实现右键菜单的定制,参见代码
HRESULT CDocHostSite::XDocHostUIHandler::ShowContextMenu(DWORD dwID, 
                                                         POINT * ppt, 
                                                        IUnknown * pcmdtReserved, 
                                                         IDispatch * pdispReserved) 
{ 
 METHOD_PROLOGUE(CDocHostSite, DocHostUIHandler); 
 return pThis->m_pView->OnShowContextMenu( dwID, ppt, pcmdtReserved,pdispReserved ); 
} 

HRESULT CLhpHtmlView::OnShowContextMenu(DWORD dwID,  
                                        LPPOINT ppt, 
                                        LPUNKNOWN pcmdtReserved,  
                                        LPDISPATCH pdispReserved) 
{ 
 HRESULT result = S_FALSE; 

 switch(m_ContextMenuMode) 
 { 
 case NoContextMenu:   // 无菜单 
  result=S_OK; 
  break; 
 case DefaultMenu:    // 默认菜单 
  break; 
 case TextSelectionOnly:   // 仅文本选择菜单 
  if(!(dwID == CONTEXT_MENU_TEXTSELECT || dwID == CONTEXT_MENU_CONTROL)) 
   result=S_OK; 
  break; 
 case CustomMenu:    // 自定义菜单 
  if(dwID!=CONTEXT_MENU_TEXTSELECT) 
   result=OnShowCustomContextMenu(ppt,pcmdtReserved,pdispReserved); 
  break; 
 } 

 return result; 
}  
在CLhpHtmlView中定义的枚举类型CONTEXT_MENU_MODE举出了定制右键弹出菜单的四种类型
enum CONTEXT_MENU_MODE  // 上下文菜单 
{ 
 NoContextMenu,  // 无菜单 
 DefaultMenu,  // 默认菜单 
 TextSelectionOnly,  // 仅文本选择菜单 
 CustomMenu  // 自定义菜单 
}; 
  通过CLhpHtmlView的函数SetContextMenuMode来设置右键菜单的类型。如果设定的右键弹出菜单是“自定义菜单”类型, 我们只要在CLhpHtmlView的派生类中重载OnShowCustomContextMenu虚函数即可,如下代码 CDemoView是CLhpHtmlView的派生类
HRESULT CDemoView::OnShowCustomContextMenu(LPPOINT ppt, LPUNKNOWN pcmdtReserved,LPDISPATCH pdispReserved) 
{ 
 if ((ppt==NULL)||(pcmdtReserved==NULL)||(pcmdtReserved==NULL)) 
  return S_OK; 

 HRESULT hr=0; 
 IOleWindow *oleWnd=NULL; 
     hr=pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&oleWnd); 
 if((hr != S_OK)||(oleWnd == NULL)) 
  return S_OK; 

 HWND hwnd=NULL; 
 hr=oleWnd->GetWindow(&hwnd); 
 if((hr!=S_OK)||(hwnd==NULL)) 
 { 
  oleWnd->Release(); 
  return S_OK; 
 } 

 IHTMLElementPtr pElem=NULL; 
 hr = pdispReserved->QueryInterface(IID_IHTMLElement, (void**)&pElem); 
 if(hr != S_OK) 
 { 
  oleWnd->Release(); 
  return S_OK; 
 } 

 IHTMLElementPtr pParentElem=NULL; 

 _bstr_t tagID; 
 BOOL go=TRUE; 

 pElem->get_id(&tagID.GetBSTR()); 
  
 while(go && tagID.length()==0) 
 { 
  hr=pElem->get_parentElement(&pParentElem); 
  if(hr==S_OK && pParentElem!=NULL) 
  { 
   pElem->Release(); 
   pElem=pParentElem; 
   pElem->get_id(&tagID.GetBSTR()); 
  } 
  else 
   go=FALSE; 
 }; 
 if(tagID.length()==0) 
  tagID="no id"; 

 CMenu Menu,SubMenu; 
 Menu.CreatePopupMenu(); 
  
 CString strTagID = ToStr(tagID); 

 if(strTagID == "red") 
  Menu.AppendMenu(MF_BYPOSITION, ID_RED, "您点击的是红色"); 
 else if(strTagID == "green") 
  Menu.AppendMenu(MF_BYPOSITION, ID_GREEN, "您点击的是绿色"); 
 else if(strTagID == "blue") 
  Menu.AppendMenu(MF_BYPOSITION, ID_BLUE, "您点击的是蓝色"); 
 else 
  Menu.AppendMenu(MF_BYPOSITION, ID_NONE, "你点了也白点,请在指定的地方点击"); 
   
 int MenuID=Menu.TrackPopupMenu(TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,ppt->x, ppt->y, this); 
 switch(MenuID) 
 { 
 case ID_RED: 
  MessageBox("红色"); 
  break; 
 case ID_GREEN: 
  MessageBox("红色"); 
  break; 
 case ID_BLUE: 
  MessageBox("红色"); 
  break; 
 case ID_NONE: 
  MessageBox("haha"); 
  break; 
 } 

 oleWnd->Release(); 
 pElem->Release(); 

 return S_OK; 
}  
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章