菜单
何志丹
菜单项属性说明: ID 标识菜单的唯一常量。 Caption 菜单项标题,“&" 后面的字符为快捷键,在菜单项后的字符将加下划线。 Separator 水平线,其它属性无效。 Pop_up 有子菜单 Grayed 无效,标题以灰色显示 Inactive 无效,标题正常显示 Checked 在标题前加一个对钩 break 为None时,使它和它的兄弟们一行或一列显示。 Help 只对最上层菜单项有效,使它及后面的最上层菜单移到窗口的右上角。 Prompt 当鼠标指向它时的提示信息 多文档应用程序除了生成IDR_MAINFRAME外,还生成标识符为IDR_xxxxTYPE,其中xxxx为应用程序名。它们分别对应无文档和有文档时。 一个菜单id可以在多个类有响应函数,但只会有一个响应。 我实验得出的结果,CChildFrame,CCMenuApp,CCMenuDoc,CCMenuView,CMainFrame(我的应用程序名为CMenu)的响应顺序为: 在IDR_MAINFRAME中,CMainFrame,CCMenuApp其它三个不响应. 在IDR_XXXXTYPE 中,CCMenuView,CCMenuDoc,CChildFrame,CCMenuApp,CMainFrame. ctrl+w打开ClassWizard,选好工程,类(最常选的是xxxView),在id中选择我们要修改的菜单项。 双击COMMAND(或UPDATE_COMMAND_UI)点确定就可以了。再在成员函数中双击我们刚刚加的函数,就可以编辑函数了。 当用户单击菜单时,我们刚刚编辑的函数会执行。 如果我们双击的是UPDATA_COMMAND_UI,则响应形式类似如下: void ... OnUpdate...(CCmdUI * pCmdUI) { pCmdUI->SetCheck(true);//在菜单项前加一个对钩 pCmdUI->Enable(true);// 使菜单项能够使用 } 因为此函数往往影响到它的外形,故在它的“父亲”或“祖父”被选中时就会执行。
CWnd类中与菜单有关的几个函数。 SetMeun(CMenu *pMenu); 修改窗口的菜单,为NULL,则表示删除。 常用的还有 GetMenu(); GetSystemMenu();
CMenu的一些函数。 AppendMenu()函数指定的菜单最后附加一个新菜单项,同时可以指定菜单项的相关情况,它有两个语法。 nFlag指定状态,可以是以下四组之一或相组合而成,还可以与MF_POPUP组合表示添加的是弹出式菜单。 MF_CHECKED,MF_CHECKED MF_DISABLED,MF_ENABLED,MF_GRAYED MF_STRING,MF_OWNERDRAW,MF_SEPARATOR,MF_BITMAP菜单项是字符串,自画型,分隔线,位图。 MF_MENUBARBREAK,MF_MENUBREAK nIDNewItem 指定菜单项的id. lpszNewItem指定菜单项的内容,与nFlag有关。为MF_OWNERDRAW时,该参数为数据指针,用来传送数据,系统在发送消息WM_MEASUREITEM和WM_DRAWITEM时将该数据存入参数 的(DRAWITEMSTRUCT结构)itemData域;nFlag为MF_STRING时该参数为菜单标题。 InsertMenu nFlags指定菜单项位置和状态,状态选项参见AppendMenu()函数,位置选项为MF_BYCOMMAND,MF_BYPOSITION. nPositin若为MF_BYCOMMAND,新菜单项插在指定菜单项之前;或为MF_BYPOSITION,该参数指定新菜单项的位置,为-1插到最后。 ModifyMenu()参数与InsertMenu类似。 DeleteMenu删除菜单项 RemoveMenu移去菜单项
设置和显示浮动菜单 BOOL TrackPopupMenu(UINT nFlags,int x,int y, CWnd *pWnd,LPCRECT = NULL); nFlag浮动式菜单坐标设定方式及鼠标操作方式,有效值如下: TPM_CENTERALIGN TPM_LEFTALIGN TPM_RIGHTALIGN TPM_LEFTBUTTON TPM_RIGHTBUTTON x,y浮动式菜单坐标 pWnd指定操作菜单的窗口 lpRect指定鼠标操作范围 在客户区单击左键就会弹出快捷菜单,方法二需要在资源编辑器中编辑一个新菜单,方法三必须有主菜单。 方法一: void CHeView::OnLButtonDown(UINT nFlags, CPoint point) { CMenu PopupMenu; PopupMenu.CreatePopupMenu(); PopupMenu.AppendMenu(MF_STRING,ID_FILE_NEW,"NEW.."); //...
ClientToScreen(&point); PopupMenu.TrackPopupMenu(TPM_CENTERALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
CView::OnLButtonDown(nFlags, point); }
方法二: void CHeView::OnLButtonDown(UINT nFlags, CPoint point) {
CMenu menu; menu.LoadMenu(IDR_DUMMY); CMenu *pMenu=menu.GetSubMenu(0); ASSERT(pMenu!=NULL);
ClientToScreen(&point); pMenu->TrackPopupMenu(TPM_CENTERALIGN|TPM_RIGHTBUTTON,point.x,point.y,this); CView::OnLButtonDown(nFlags, point); }
方法三: void CHeView::OnLButtonDown(UINT nFlags, CPoint point) { CWnd *pWnd=AfxGetApp()->GetMainWnd(); CMenu * pMenu=pWnd->GetMenu(); pMenu=pMenu->GetSubMenu(0); ASSERT(pMenu!=NULL);
ClientToScreen(&point); pMenu->TrackPopupMenu(TPM_CENTERALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
} 习题: 动态菜单,用户点击“更多菜单”,增加一些菜单项。 其实,自画菜单原理不难理解.AppendMenu的风格选自画,将自画用的信息(指针)强制转化成LPCTSTR,再重
载DrawItem就行了,注意自画用的信息不要提前delete了. 示例如下: COwnerMenu.h中 class CMenuItem { public: CString m_szText; COLORREF m_color; CMenuItem(CString szText,COLORREF color) { m_szText = szText; m_color = color; }
};
#include <afxtempl.h>
class COwnerMenu : public CMenu { public: void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ); bool AppendMenu(UINT nIDNewItem,CString caption,COLORREF color); COwnerMenu();
CTypedPtrList<CPtrList,CMenuItem *> m_MenuList; virtual ~COwnerMenu();
};
COwnerMenu.cpp中 COwnerMenu::~COwnerMenu() { while(m_MenuList.GetCount()) { CMenuItem *pMenuItem = m_MenuList.GetHead(); delete pMenuItem; m_MenuList.RemoveHead(); } }
bool COwnerMenu::AppendMenu(UINT nIDNewItem, CString caption, COLORREF color) { CMenuItem * pMenuItem = new CMenuItem(caption,color); m_MenuList.AddTail(pMenuItem); return CMenu::AppendMenu(MF_OWNERDRAW,nIDNewItem,(LPCTSTR)pMenuItem); }
void COwnerMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); pDC->SetTextColor(((CMenuItem*)lpDrawItemStruct->itemData)->m_color); pDC->TextOut(0,0,((CMenuItem*)lpDrawItemStruct->itemData)->m_szText); }
在使用菜单的地方(不要忘记了加头文件): void COwnerMenuView::OnRButtonDown(UINT nFlags, CPoint point) { COwnerMenu menu; menu.CreatePopupMenu(); menu.AppendMenu(ID_1,"1",RGB(0,0,128)); ClientToScreen(&point); menu.TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,point.x,point.y,this); CView::OnRButtonDown(nFlags, point); } 
|