第6课 菜单

1 顶层菜单默认都是Pop-up,即弹出式菜单,不能响应命令。

2. 当对某菜单添加消息响应函数时,  4个类的消息响应优先次序分别是: 1.View;2.CDOC;3.CMainFrame.4.CWinAPP. 为什么?请参阅《深入浅出》

3. 消息分类:
a; 标准消息(以  WM_开头的消息,但不包括WM_COMMAND);从CWnd派生的类,可以接受这类消息。 
b; 命令消息  ON_COMMAND(IDM_PHONE1, OnPhone1),菜单和工具栏的消息。从CCmdTarget派生的类,可以接受这类消息。  
c. 通告消息:按钮,列表框发出的消息。 从CCmdTarget派生的类,可以接受这类消息。   
CCmdTarget 只能接受命令消息和通告消息。而从  CCmdTarget派生的CWnd 可以能接受命令消息和通告消息,也可以接受标准消息。

4. 确定菜单的索引号,注意从  0开始, 分隔符也算数。
GetMenu() 获取一个菜单指针(菜单栏对象)
GetSubMenu()获取子菜单的指针
一个子菜单只能有一个缺省菜单(粗体字体显示)。 //GetMenu()->GetSubMenu(0)->SetDefaultItem(5,TRUE);
SetMunuItemBitmaps() 将指定位图与菜单项关联起来,即菜单项前面显示图形。
图形标记菜单项上显示的位图的大小是13x13
 str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),  GetSystemMetrics(SM_CYMENUCHECK));//  获得系统的菜单的位图的大小。
EnableMenuItem() 禁用菜单项
SetMenu(NULL);//  移除当前菜单 

CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
menu.Detach();//  增加菜单,此处 detach(),如果是局部变量。

5.UPDATE_COMMAND_UI消息响应设置菜单项的状态
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
{
 if(2==pCmdUI->m_nIndex)
  pCmdUI->Enable();//  当此菜单显示时,设为可用。
}

6. 右键弹出菜单功能的实现方法有两个:
  a.Project->Add to Project->component and controls->  文件夹VC components->Popup Menu OK
  b. TrackPopupMenu()  实现。
 CMenu menu;
 menu.LoadMenu(IDR_MENU1);
 CMenu *pPopup=menu.GetSubMenu(0);
 ClientToScreen(&point);//客户区坐标转换成屏幕坐标
 pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, GetParent());//注意, TrackPopupMenu的参数的x,y都是屏幕坐标。

7. 动态创建菜单的方法:  CMenu menu;
 menu.CreatePopupMenu();
// GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
 GetMenu()->InsertMenu(2,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
 menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello");
 menu.AppendMenu(MF_STRING,112,"Weixin");
 menu.AppendMenu(MF_STRING,113,"Mybole");
 menu.Detach();
 GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");
 GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
   MF_BYCOMMAND | MF_STRING,115,"  维新");
// GetMenu()->DeleteMenu(1,MF_BYPOSITION);
// GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);

8. 为动态创建的菜单增加消息响应的步骤
  a. resource.h  中增加#define IDM_HELLO 123
  b. MainFrm.h  中加入afx_msg void OnHello();
  c.MainFrm.cpp  中加入ON_COMMAND(IDM_HELLO,OnHello)
  d. 最后加入
void CMainFrame::OnHello()
{
 MessageBox("Hello!");
}

9. 动态增加电话号码本步骤
  a. 处理 WM_Char  消息。如果回车,则清空字符串,窗口重绘 invalidate,将人名加入到菜单中,将字符串保存集合类 CStringArray, 用的是成员函数 Add方法。
  b. 取出动态创建的菜单的数据的方法。
    1  )创建一个弹出菜单,弹出菜单下面有 4个子菜单。将子菜单的ID号连续。
    2  )在resource.h中添加 #define IDM_PHONE1 123....
    3  )添加其消息响应函数。注意注释中的文字
BEGIN_MESSAGE_MAP(CMenu2View, CView)
 //{{AFX_MSG_MAP(CMenu2View)
 ON_WM_CHAR()
 ON_COMMAND(ID_EDIT_COPY, OnEditCopy)//  下面的4句代码原来在此处。
 //}}AFX_MSG_MAP
 // Standard printing commands
 ON_COMMAND(IDM_PHONE1, OnPhone1)//  一定要这 4句代码移到此处。
 ON_COMMAND(IDM_PHONE2, OnPhone2)
 ON_COMMAND(IDM_PHONE3, OnPhone3)
 ON_COMMAND(IDM_PHONE4, OnPhone4)
 ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
 ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
 ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
    4  )填写代码

10. 如何在 MainFrame  中拦截OnCommand消息?答,在它增加 OnCommand的消息处理函数即可。

11. 错误调试方法: Missing ";" before "*"
 CMenu2Doc* GetDocument();//  因为CMenu2Doc是个不认识的变量,将其头文件包含进即可。

12 在CMainFrame类中重绘菜单栏  DrawMenuBar();//重绘菜单栏

猜你喜欢

转载自blog.csdn.net/zhang_zxk/article/details/52401893