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] |