孙鑫C++第六堂课要点

1、要构建弹出式菜单,要将控件的属性中“Popup”由“false”改为“TRUE”;一般顶级菜单才可以

2、对于一个菜单命令消息函数响应的顺序:CView类→CDoc类→CMainFrame类→CApp类;子窗口享有最先响应的权利,如何子窗口没有,那么交由父窗口

3、消息的分类:

  1. 标准消息:除WM_COMMAND之外,所有以WM_开头的消息。从CWnd派生的类,都可以接收到这类消息。
  2. 命令消息:来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。
  3. 通告消息:由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。从CCmdTarget派生的类,都可以接收到这类消息。

4、命名消息的路由:

   

5、对于菜单栏中的菜单项可以通过ID号或者索引来访问,而对于子菜单项则通过索引来访问;

6、GetMenu返回一个指向菜单栏的指针,而GetSubMenu返回一个指向子菜单的指针

       1 GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION |MF_CHECKED); 在文件->新建前面打上标号

7、获取子菜单项的文本的宽与高:

1     CString str;
2     str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CXMENUCHECK));
3     MessageBox(str);

8、Detach的使用:Detach将一个CMenu对象和窗口的句柄断开,当程序结束时,析构函数不会析构CMenu对象,而窗口关闭时候,对象才被析构

1 SetMenu(NULL);
2 CMenu menu;
3 menu.LoadMenu(IDR_MAINFRAME);
4 SetMenu(&menu);
5 menu.Detach();

9、命令更新:(CCmdUI类)(主要用来使子菜单项能否使用或者不能使用

  1. 菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。我们可以通过手工或利用ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获CN_UPDATE_COMMAND_UI消息。
  2. 在后台所做的工作是:操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如CFrameWnd接管。它创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个成员函数DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。
  3. 更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。

10、TrackPopupMenu用来创建弹出菜单

 1 void Cmfctest11View::OnRButtonDown(UINT nFlags, CPoint point)
 2 {
 3     // TODO: 在此添加消息处理程序代码和/或调用默认值
 4     CMenu menu;
 5     menu.LoadMenu(IDR_MENU1);      //IDR_MENU1为弹出菜单的标识(ID)
 6     CMenu* pOldMenu=menu.GetSubMenu(0);
 7     ClientToScreen(&point);        //客户坐标转化到窗口坐标  
 8     pOldMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,this);//如果想要MainFrame有响应机会,必须将this改为GetParent()
 9     CView::OnRButtonDown(nFlags, point);
10 }

11、在窗口菜单栏(末尾)动态添加菜单

 1 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 2 {
 3     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
 4         return -1;
 5 
 6     if (!m_wndStatusBar.Create(this))
 7     {
 8         TRACE0("未能创建状态栏\n");
 9         return -1;      // 未能创建
10     }
11     m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
12     //在窗口菜单栏动态添加菜单
13     CMenu menu;
14     menu.CreatePopupMenu();
15     GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"weixin");
16     menu.Detach();  //不加这个会提示错误,该函数实现menu这个对象与窗口句柄的断开
17     return 0;
18 }

12、在窗口菜单栏的两个菜单之间插入新的菜单

 1 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 2 {
 3     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
 4         return -1;
 5 
 6     if (!m_wndStatusBar.Create(this))
 7     {
 8         TRACE0("未能创建状态栏\n");
 9         return -1;      // 未能创建
10     }
11     m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
12     //在窗口菜单栏的两个菜单之间插入新的菜单
13     CMenu menu;
14     menu.CreatePopupMenu();
15     GetMenu()->InsertMenu(2,MF_POPUP|MF_BYPOSITION,(UINT)menu.m_hMenu,"weixin");//插入新的菜单
16     menu.AppendMenu(MF_STRING,111,"Hello"); //在新插入菜单中,添加菜单项
17     menu.AppendMenu(MF_STRING,112,"weixin");
18     menu.AppendMenu(MF_STRING,113,"mybole");
19     menu.Detach();  //不加这个会提示错误,该函数实现menu这个对象与窗口句柄的断开
20     return 0;
21 }

13、手动添加菜单的响应函数:

  1. 添加资源标识(ID):在Resource.h中,添加标识
#define IDM_HELLO                       111

     2.  添加消息映射:

1 // 生成的消息映射函数,在MainFrm.h文件中添加
2 protected:
3     afx_msg void OnHello();
1 // CMainFrame,在MainFrm.cpp文件添加
2 
3 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
4 
5 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
6     ON_WM_CREATE()
7     ON_COMMAND(IDM_HELLO,OnHello)
8 END_MESSAGE_MAP()

  3.命令函数的实现:

1 // CMainFrame 消息处理程序
2 void CMainFrame::OnHello()
3 {
4     MessageBox("Hello!");
5     ......
6 }

14、如果窗口已经创建,而菜单栏已经发生改变,则要调用DrawMenuBar()对菜单栏的重画,CVIew中没有此函数,CMainFrame中有;Invalidate()判断是否对背景的擦除;CStringArray标识CString类的集合类(类似数组)

15、低字节序(一个四位数的前面两位),高字节序(一个四位数的后面两位),用LOWORD()来取出,

16、在CFrameWnd类中调用函数指向当前的CView类,并返回指针

CMenu2View *pView=(CMenu2View*)GetActiveView();

17、若在文件中检查出错误,如下面的

Public:
        CMenu2Doc* GetDocment();

弹出错误:missing ';' before '*'
这时要检查该头文件中有没有包含:"Menu2Doc.h"

 

posted @ 2014-10-04 21:21  龙泽一狼  阅读(196)  评论(0编辑  收藏  举报