①、两种方式的菜单:下拉式、弹出式;
②、MFC中菜单的关联类:CMenu
③、插入并编辑菜单资源;
④、让对话框显示下拉式菜单;
⑤、为菜单项添加消息响应函数:不要加错类了,否则可能不会正常的响应:
COMMAND 是事件的响应函数,也就是你点击了菜单项后,菜单如何处理;
UPDATE_COMMAND_UI 是设置菜单显示状态的响应函数 ;
⑥、为对话框添加右键弹出式菜单:
CMenu mMenu, *pMenu = NULL;
mMenu.LoadMenu(IDR_MENU1);
pMenu = mMenu.GetSubMenu(0);
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
※ point 的坐标点信息一定要基于屏幕坐标系的,否则弹出的位置会不对;
★★★ 这里面我们用的是 WM_CONTEXTMENU 消息来响应右键消息的,给大家留一个作业
响应对话框类的 WM_RBUTTONUP 消息,并在其中弹出菜单试试,看看会遇到什么问题?
⑦、菜单项的启用与禁用:EnableMenuItem
※ 一定要在菜单弹出之前进行 EnableMenuItem 操作
⑧、菜单项前面的复选框 CheckBox:CheckMenuItem
⑨、UPDATE_COMMAND_UI 消息:一般情况下用于修改菜单的状态,在菜单显示之前被调用
可用的操作:
void Enable(BOOL bOn = TRUE);
void SetCheck(int nCheck = 1); // 0, 1 or 2 (indeterminate)
void SetRadio(BOOL bOn = TRUE);
void SetText(LPCTSTR lpszText);
对话框中 UPDATE_COMMAND_UI 消息 不能正确响应的解决办法 ///
类的头文件中添加函数声明:afx_msg void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu);
类的CPP文件中添加消息映射:ON_WM_INITMENUPOPUP()
类的CPP文件中添加函数实现:
void CMFCTestDlg::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu)
{
ASSERT(pPopupMenu != NULL);
// Check the enabled state of various menu items.
CCmdUI state;
state.m_pMenu = pPopupMenu;
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pParentMenu == NULL);
// Determine if menu is popup in top-level menu and set m_pOther to
// it if so (m_pParentMenu == NULL indicates that it is secondary popup).
HMENU hParentMenu;
if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
state.m_pParentMenu = pPopupMenu; // Parent == child for tracking popup.
else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
{
CWnd* pParent = this;
// Child windows don't have menus--need to go to the top!
if (pParent != NULL &&
(hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
{
int nIndexMax = ::GetMenuItemCount(hParentMenu);
for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
{
if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)
{
// When popup is found, m_pParentMenu is containing menu.
state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
break;
}
}
}
}
state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
state.m_nIndex++)
{
state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);
if (state.m_nID == 0)
continue; // Menu separator or invalid cmd - ignore it.
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pMenu != NULL);
if (state.m_nID == (UINT)-1)
{
// Possibly a popup menu, route to first item of that popup.
state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
if (state.m_pSubMenu == NULL ||
(state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
state.m_nID == (UINT)-1)
{
continue; // First item of popup can't be routed to.
}
state.DoUpdate(this, TRUE); // Popups are never auto disabled.
}
else
{
// Normal menu item.
// Auto enable/disable if frame window has m_bAutoMenuEnable
// set and command is _not_ a system command.
state.m_pSubMenu = NULL;
state.DoUpdate(this, FALSE);
}
// Adjust for menu deletions and additions.
UINT nCount = pPopupMenu->GetMenuItemCount();
if (nCount < state.m_nIndexMax)
{
state.m_nIndex -= (state.m_nIndexMax - nCount);
while (state.m_nIndex < nCount &&
pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
{
state.m_nIndex++;
}
}
state.m_nIndexMax = nCount;
}
}
///