打印本文 打印本文 关闭窗口 关闭窗口
Internet Explorer 编程简述(六)自定义浏览器上下文菜单
作者:武汉SEO闵涛  文章来源:敏韬网  点击数1759  更新时间:2009/4/23 10:51:14  文章录入:mintao  责任编辑:mintao
C中UpdateUI的机制,遇到不认识的CommandID,浏览器就会将其状态设置为Disabled,所以我们自己添加的菜单是无法被选择的。
可以想到,如果把菜单状态设置为Enabled,并通过TPM_RETURNCMD标志调用TrackPopupMenu或TrackPopupMenuEx,再把返回的命令ID教给合适的窗口(如主框架窗口)去处理不就行了。关键点就在于如何把菜单状态设置为Enabled。

3)实现
解决的办法是截获WM_INITMENUPOPUP消息,在菜单创建以后,尚未显示之前修改菜单项状态,那浏览器就没有办法了。截获WM_INITMENUPOPUP消息则可使用子类化(subclass)的技术,前面通过IOleWindow接口我们得到了浏览器窗口的句柄hwnd,则可以这样做:

HMENU g_hPubMenu = NULL;
WNDPROC g_lpPrevWndProc = NULL;

LRESULT CALLBACK CustomMenuWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  if (uMsg == WM_INITMENUPOPUP)
  {
    if (wParam == (WPARAM) g_hPubMenu)
    {
      ::EnableMenuItem( 自定义的菜单命令ID, MF_ENABLED | MF_BYCOMMAND );
      ::CheckMenuItem( 自定义的菜单命令ID, MF_BYCOMMAND);
      return 0;
    }
  }
  return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}

HRESULT CMyHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
 LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
//浏览器菜单句柄保存在g_hPubMenu中
......
// subclass浏览器窗口
g_lpPrevWndProc = (WNDPROC)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CustomMenuWndProc);
//m_SubclassWnd.SubclassWindow( hwnd );//MFC中用此方法更简便

// Show shortcut menu
int iSelection = ::TrackPopupMenu(hSubMenu,
  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  ppt->x,
  ppt->y,
  0,
  hwnd,
  (RECT*)NULL);
// Unsubclass浏览器窗口
::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);
g_lpPrevWndProc = NULL;
//m_SubclassWnd.UnsubclassWindow();

if (iSelection == 自定义的菜单命令ID )
{
  ::SendMessage( ::AfxGetMainWnd()->m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lResult), 0x0), 0 );
}
else
{
  LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
......
}

在MFC中则更为方便,从CWnd继承一个窗口类,假设为CWebBrowserSubclassWnd,为CMyHtmlView添加一个CWebBrowserSubclassWnd类型的成员变量m_SubclassWnd,在子类化和去除子类化时调用m_SubclassWnd.SubclassWindow( hwnd )和m_SubclassWnd.UnsubclassWindow()即可。相应的WM_INITMENUPOPUP消息处理函数如下所示:

void CWebBrowserSubclassWnd::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
  CWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

  pPopupMenu->EnableMenuItem( 自定义的菜单命令ID, MF_ENABLED | MF_BYCOMMAND );
  pPopupMenu->CheckMenuItem( 自定义的菜单命令ID, MF_BYCOMMAND);
}

下面的图片显示了将“文字大小”菜单项添加到“编码”菜单项的下面的效果。

5、新的问题
看完上面的代码,我们又自然地想到浏览器编程中的另一个问题,那就是“编码”菜单。我们指定,手动建立一个“编码”菜单是比较麻烦的事,而且很难做到与浏览器上下文菜单上的“编码”菜单一样的效果。何不使用上述的方法让浏览器自己建立“编码”菜单和处理相应的命令呢?

具体实现请看下一篇文章《Internet Explorer 编程简述(七)完美的“编码”菜单》


参考资料
MSDN:Adding Entries to the Standard Context Menu
MSDN:How To Adding to the Standard Context Menus of the WebBrowser Control
MSDN:IDocHostUIHandler::ShowContextMenu Method
BeginThread.com:Custom WebBrowser Context Menus

上一页  [1] [2] 

打印本文 打印本文 关闭窗口 关闭窗口