c++ 笔记007 动态的创建菜单并关联消息处理函数

一 在CMainFrameOnCreate中动态的创建菜单

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("未能创建工具栏\n");
        return -1;      // 未能创建
    }

    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("未能创建状态栏\n");
        return -1;      // 未能创建
    }
    m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

    // TODO: 如果不需要可停靠工具栏,则删除这三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);
    
/*创建一个弹出菜单,并把菜单附加到主菜单末尾*/ CMenu menu;
//创建一个CMenu对象,内部有一个数据成员 m_hMenu,保存了这个菜单的句柄 menu.CreatePopupMenu(); //创建一个弹处菜单,并与menu对象关联 CMenu *pMenu = GetMenu(); //获取与CMainFrame相关联的菜单指针(主菜单)对象 pMenu->AppendMenuW(MF_POPUP, (UINT_PTR)menu.m_hMenu,_T("TestPopupMenu")); //创建的菜单附加到现有菜单上。如果第一个参数是MF_POPUP,则第二个参数是要弹处来那个menu菜单的句柄 menu.Detach(); //将menu对象与句柄断开。不断开关联,能正常显示,但是如果单击,将导致内存泄漏,所以这个是必须的。因为menu是一个局部变量 return 0; }

创建完的界面如下:

如果要在指定位置增加一个菜单,需要InsertMenu(),函数声明如下

BOOL InsertMenuW(
   UINT nPosition, //索引号或ID根据 nFlags参数设置
   UINT nFlags,    //如果nFlags设置为 MF_BYCOMMAND,则nPosition设置为ID,如果设置nFlags为MF_BYPOSITION,则nPosition为索引号 0,1...
   UINT_PTR nIDNewItem = 0,   //通过创建的CMenu对象获取到 m_hMenu 并转型为UNIT_PTR或UNIT
   LPCTSTR lpszNewItem = NULL //菜单的名字
);
BOOL InsertMenuW(
   UINT nPosition, //索引号或ID根据 nFlags参数设置
   UINT nFlags,    //如果nFlags设置为 MF_BYCOMMAND,nPosition设置为ID,如果设置nFlags为MF_BYPOSITION,则nPosition为索引号 0,1...
   UINT_PTR nIDNewItem, //通过创建的CMenu对象获取到 m_hMenu 并转型为UNIT_PTR或UNIT
   const CBitmap* pBmp 
);

在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)  return 0;语句前增加如下代码

    //插入菜单
    CMenu menu;                                                        
    menu.CreatePopupMenu();                                            
    CMenu *pMenu = GetMenu();                                        
    pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单
    menu.Detach();  
    return 0;

为创建好的弹处式菜单增加弹处项

    //插入菜单,增加三个弹出项
    CMenu menu;                                                        
    menu.CreatePopupMenu();                                            
    CMenu *pMenu = GetMenu();
    //pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("Test"));
    pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单
    menu.AppendMenuW(MF_STRING, 3344U, _T("子菜单1"));
    menu.AppendMenuW(MF_STRING, 3345U, _T("子菜单2"));
    menu.AppendMenuW(MF_STRING, 3346U, _T("子菜单3"));
    menu.Detach();  

在现有菜单上增加菜单项

    //插入菜单Test
    CMenu menu;                                                        
    menu.CreatePopupMenu();                                            
    CMenu *pMenu = GetMenu();
    //pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("Test"));
    pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单
    menu.AppendMenuW(MF_STRING, 3344U, _T("子菜单1"));
    menu.AppendMenuW(MF_STRING, 3345U, _T("子菜单2"));
    menu.AppendMenuW(MF_STRING, 3346U, _T("子菜单3"));
    menu.Detach(); 
    //在[文件]菜单的尾部附加一个菜单项,在打印设置后插入一个菜单项
    CMenu *ppMenu = GetMenu(); //获取主菜单
    CMenu *pFileMenu=ppMenu->GetSubMenu(0);                  //从主菜单中拿到第一个子菜单,索引号从0开始
    pFileMenu->AppendMenuW(MF_STRING, 3347U, _T("附加菜单"));  //在拿到的子菜单(文件)的菜单项末尾附加一个菜单
    pFileMenu->InsertMenuW(8, MF_BYPOSITION | MF_STRING, (UINT)menu.m_hMenu, _T("打印到PDF")); //在打印设置后增加一个"打印到PDF",分隔条也需要占用一个索引,所以是8

    //删除菜单操作
    GetMenu()->DeleteMenu(4,MF_BYPOSITION); //从左往右索引号为4的整个菜单删除,再运行,帮助菜单被删除了
    GetMenu()->GetSubMenu(0)->DeleteMenu(7, MF_BYPOSITION); //删除文件菜单中的 打印设置

二 菜单的响应函数

弹处菜单不能用来响应命令比如顶级菜单、文件、编辑、视图、帮助。如果非要用来响应命令,则在某个菜单的属性 外观栏一栏中 把Popup的值改为False,这样杂项里面ID由之前无法编辑ID变为ID可以输入状态。在帮助后面增加一个Caption:NewTest的顶级菜单,默认Popup:True,ID:无法编辑ID,此时修改Popup:False,ID:ID_NEWTEST(这个单击ID值那里,自动生成了),可以将修改一下ID值: IDM_NEWTES(表示菜单的ID)保存。

在类视图上CMainFrame右键,类向导->命令 搜索栏输入IDM自动定位到 IDM_NEWTEST

单击确定后 在类向导对话框页面右边,单击编辑代码,自动转到OnNewtest函数中

为动态增加的按钮关联消息处理函数

步骤一:   在Resource.h头文件中定义弹出菜单项的ID

#define IDM_SUB1                    4455
#define IDM_SUB2                    4456
#define IDM_SUB3                    4457

           在CMainFrame.h头文件中,声明消息响应函数的原型

    afx_msg void OnSubMenu1();
    afx_msg void OnSubMenu2();
    afx_msg void OnSubMenu3();

步骤二:   建立消息映射 MainFrame.cpp文件中

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_WM_CREATE()
    ON_COMMAND( IDM_SUB1, &CMainFrame::OnSubMenu1)
    ON_COMMAND( IDM_SUB2, &CMainFrame::OnSubMenu2)
    ON_COMMAND( IDM_SUB3, &CMainFrame::OnSubMenu3)
END_MESSAGE_MAP()

//消息响应函数
void CMainFrame::OnSubMenu1()
{
    MessageBox(_T("Sub1菜单"));
}
void CMainFrame::OnSubMenu2()
{
    MessageBox(_T("Sub2菜单"));
}
void CMainFrame::OnSubMenu3()
{
    MessageBox(_T("Sub3菜单"));
}

步骤三:MainFrame.cpp文件中,OnCreate()函数中

    //增加一个顶级菜单
    CMenu menu;
    menu.CreatePopupMenu();   //创建弹出式菜单
    CMenu *pMenu = GetMenu(); //获取主菜单
    pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("动态增加菜单"));  //把Caption:动态增加菜单  的菜单附加到主菜单尾部
    menu.AppendMenuW(MF_STRING, IDM_SUB1, _T("动态子菜单1"));
    menu.AppendMenuW(MF_STRING, IDM_SUB2, _T("动态子菜单2"));
    menu.AppendMenuW(MF_STRING, IDM_SUB3, _T("动态子菜单3"));
    menu.Detach();

猜你喜欢

转载自www.cnblogs.com/zhou8744/p/10438693.html