职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 505|回复: 0

WebBrowser控件的上下文菜单和快捷键控制

[复制链接]
jinchang 发表于 2011-9-26 10:35 | 显示全部楼层 |阅读模式
  在实际应用中,为了避免用户查看页面源文件或防止用户用快捷键打开当前页面的另外一个窗口,我们往往要对由WebBrowser控件提供的上下文菜单(在页面上按鼠标右键)或快捷键(如Ctrl+N打开新窗口)加以定制。
8d158aeec17f757e2df5349c.jpg
  无论是WebBrowser控件还是CHtmlView类都没有直接提供定制上述操作的方法,因而必须通过实现IDocHostUIHandler接口来完成。在该接口中,可以实现上下文菜单和快捷键控制的方法分别为ShowContextMenu()和TranslateAccelerator()。
  由于使用MFC封装类CHtmlView比直接应用WebBrowser控件更为方便,因而可以考虑把定制之后的接口支持功能集成到MFC框架内。具体实现的基本思路如下:
  创建一个新的OLE客户站并在其中实现接口IDocUIHandler
  在InitInstance()中用一个新的管理类取代缺省配置以引入该客户站
  基于以上思路,我们可以从COleControlSite创建派生类CCustomWebBrowserSite,并在派生类中实现IDocHostUIHandler。COleControlSite在VC++的mfcsrcoccimpl.h中定义,用于封装控件客户站。新的客户站定义为:
清单
  class CCustomWebBrowserSite : public COleControlSite
  {
  public:
  CCustomWebBrowserSite(COleControlContainer *pCnt):
  COleControlSite(pCnt){ }
  protected:
  DECLARE_INTERFACE_MAP();
  BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)
  STDMETHODIMP ShowContextMenu(DWORD, POINT*, IUnknown*, IDispatch*);
  STDMETHODIMP TranslateAccelerator(LPMSG, const GUID*, DWORD);
  STDMETHODIMP GetHostInfo(DOCHOSTUIINFO);
  STDMETHODIMP EnableModeless(BOOL);
  STDMETHODIMP OnDocWindowActivate(BOOL);
  STDMETHODIMP OnFrameWindowActivate(BOOL);
  STDMETHODIMP ResizeBorder(LPCRECT, IOleInPlaceUIWindow*, BOOL);
  STDMETHODIMP GetOptionKeyPath(LPOLESTR*, DWORD);
  STDMETHODIMP GetDropTarget(IDropTarget*, IDropTarget**);
  STDMETHODIMP GetExternal(IDispatch**);
  STDMETHODIMP TranslateUrl(DWORD, OLECHAR*, OLECHAR**);
  STDMETHODIMP FilterDataObject(IDataObject*, IDataObject**);
  STDMETHODIMP ShowUI(DWORD, IOleInPlaceActiveObject*,
  IOleCommandTarget*, IOleInPlaceFrame*, IOleInPlaceUIWindow*);
  STDMETHODIMP HideUI(void);
  STDMETHODIMP UpdateUI(void);
  END_INTERFACE_PART(DocHostUIHandler)
  } ;
  如上所介绍,在这个接口中我们感兴趣的方法主要有ShowContextMenu()和TranslateAccelerator()两个。以完全禁止上下文菜单显示为例,在派生类CCustomWebBrowserSite中ShowContextMenu()的实现代码为:
清单
  STDMETHODIMP CCustomWebBrowserSite::XDocHostUIHandler::ShowContextMenu(
  DWORD, POINT*, IUnknown*, IDispatch*)
  {
  METHOD_PROLOGUE(CCustomWebBrowserSite, DocHostUIHandler)
  return S_OK; // 禁止菜单显示
  }
  用类似的方法可以关闭由控件直接响应的快捷键:
清单
  STDMETHODIMP CustomWebBrowserSite::XDocHostUIHandler::TranslateAccelerator(LPMSG lpMsg,const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID)
  {
  METHOD_PROLOGUE(CCustomWebBrowserSite, DocHostUIHandler)
  return S_OK; // 关闭快捷键
  }
  在IDocHostUIHandler接口实现之后,我们还需要一个管理类CCustomOccManager来支持CCustomWebBrowserSite,新的管理类CCustomOccManager从COccManager派生,COccManager也在mfcsrcoccimpl.h中定义:
清单
  class CCustomOccManager : public COccManager
  {
  public:
  CCustomOccManager() { }
  COleControlSite* CreateSite(COleControlContainer* pCC)
  {
  CCustomWebBrowserSite *pSite = new CCustomWebBrowserSite(pCC);
  return pSite;
  }
  } ;
  到此为止,我们可以使用新的控件管理类CCustomOccManager了。在应用程序类的InitInstance()中找到AfxEnableControlContainer()调用,将它替换为:
清单
  CCustomOccManager *pMgr = new CCustomOccManager;
  AfxEnableControlContainer(pMgr);
  CHtmlView::Create()函数将再次调用AfxEnableControlContainer(),这个调用使得我们原先对控件客户站的声明无效。我们可以在派生类中将CHtmlView::Create()代码拷贝一份,并删除对AfxEnableControlContainer()的调用:
清单
  BOOL CHtmlViewEx::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
  DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,
  UINT nID, CCreateContext* pContext)
  {
  m_pCreateContext = pContext;
  if (!CView::Create(lpszClassName, lpszWindowName,
  dwStyle, rect, pParentWnd, nID, pContext))
  {
  return FALSE;
  }
  RECT rectClient;
  GetClientRect(&rectClient);
  if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, lpszWindowName,
  WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST))
  {
  DestroyWindow();
  return FALSE;
  }
  LPUNKNOWN lpUnk = m_wndBrowser.GetControlUnknown();
  HRESULT hr = lpUnk- > QueryInterface(IID_IWebBrowser2, (void**) &m_pBrowserApp);
  if (!SUCCEEDED(hr))
  {
  m_pBrowserApp = NULL;
  m_wndBrowser.DestroyWindow();
  DestroyWindow();
  return FALSE;
  }
  return TRUE;
  }
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-25 07:33 , Processed in 0.150566 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表