方法一:
1.使用VS2010或VS2008SP1提供的CMFCxxxx框架时,弹出菜单的调用发生了变化,但与之前使用CMenu产生弹出菜单相同的是都是响应窗口的WM_CONTEXTMENU消息中进行。
2.使用CContextMenuManager产生的弹出菜单比CMenu产生的弹出菜单漂亮。
3.不要继承或者手动实例化CContexMenuManager类,通过CWinAppEx::GetContextMenuManager()方法调用全局的CContextMenuManager对象,但使用要注意:(1)在CWinAppEx::InitInstance()中需要调用CWinAppEx::InitContextMenuManager()来初始化全局对象;(2)在CWinAppEx::ExitInstance()函数中会自动完成全局对象的清理,但如果是CWinApp::ExitInstance()未释放全局对象,就会造成内存泄露;(3)在加载菜单前需要在CWinAppEx::PreLoadState()函数中使用CContextMenuManager::AddMenu()提前加载菜单资源,之后才能调用ShowPopupMenu()或TrackPopupMenu()
4.对于ShowPopupMenu和TrackPopupMenu有如下区别:
virtual BOOL ShowPopupMenu( UINT uiMenuResId, //用资源ID进行加载, int x, int y, CWnd* pWndOwner, //指定进行菜单消息响应的父窗口指针 BOOL bOwnMessage = FALSE, //用于指定消息是否被发送到父窗口 BOOL bRightAlign = FALSE ); virtual CMFCPopupMenu* ShowPopupMenu( HMENU hmenuPopup, int x, int y, CWnd* pWndOwner, //指定进行菜单消息响应的父窗口指针 BOOL bOwnMessage = FALSE, //用于指定消息是否被发送到父窗口 BOOL bAutoDestroy = TRUE, BOOL bRightAlign = FALSE );
virtual UINT TrackPopupMenu( HMENU hmenuPopup, //通过菜单句柄加载弹出菜单 int x, int y, CWnd* pWndOwner, //菜单父窗口 BOOL bRightAlign = FALSE );
(1)ShowPopupMenu可以指定消息发送到父窗口,在父窗口中通过ON_COMMAND消息映射进行响应,而TrackPopupMenu貌似不发送消息到父窗口,通过返回值来得到用户选择的菜单项;
(2)ShowPopupMenu加载的菜单资源要求在主菜单资源下只有一个子菜单项,且需要弹出的菜单是这个子菜单项的子菜单。而TrackPopupMenu()弹出的子菜单由传入的菜单句柄决定,可以弹出整个菜单,也可以通过CMenu::GetSubMenu()弹出子菜单。
(3)一般使用ShowPopupMenu()进行子菜单弹出。
(4)使用ShowPopupMenu弹出的子菜单,如果子菜单项关联了消息响应,则菜单项是可用的,如果未关联消息响应则不可用,但是也可以使用ON_UPDATE_COMMONED_UI控制菜单项的使能,来改变菜单外观。
(5)通过ShowPopupMenu的第二个重载形式可以看出,CContextMenuManager中管理的是一个CMFCPopupMenu对象,并不是一个CMenu对象,因此使用ShowPopupMenu()来显示弹出菜单时,要控制菜单项的使能不能通过CMenu::EnableMenuItem()或是全局的::EnableMenuItem()来完成,正确的方法是通过ON_UPDATE_COMMAND_UI来实现对弹出菜单的控制。
参考:https://blog.csdn.net/u011519892/article/details/18702187
方法二:
通过CMenu的成员方法,具体可查孙鑫第六章