MFC学习笔记(4)—— 菜单

本文介绍了在MFC中如何创建和管理菜单,包括在资源视图中添加菜单,替换应用程序的默认菜单,以及处理菜单事件。对于大量菜单项,文章推荐使用MFC的批处理方法,通过switch语句根据菜单ID进行处理。同时,还讲解了如何在视图类中实现右键菜单弹出,并处理相关消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

菜单就是红圈圈住的那一部分,而每一个选项是一个子菜单

例如这个


几乎每一个应用程序都需要自己的菜单(除了对话框程序),所以学习如何制作自己的菜单还有相应的响应事件就变得很重要了


菜单的创建:

    找到资源视图下的Menu部分,右键添加自己的菜单就可以了。


把应用程序的菜单替换成自己的菜单:

    菜单的出现是在框架创建完以后,所以我们需要在框架的

        int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
这个函数里设置我们自己的菜单。

   如果不需要菜单:

        SetMenu(NULL);

如果要加载自己的菜单:

	CMenu menu;                    //定义菜单
	menu.LoadMenu(IDR_MENU1);       //载入在资源里创建好的菜单
	SetMenu(&menu);                 //设置当前窗口的菜单
	menu.Detach();                  //分离资源菜单和定义的菜单
           为什么会有最有一句分离呢? 这跟变量的生命周期有关。如果不分离,大括号结束,因为这两个量有关联,所以这个menu变量被回收,菜单自然也就不见了。但是分离以后,菜单已经显示在框架上了,所以有没有这个menu也是无所谓。


为自己的菜单添加事件处理:

          最基本的方法就是在资源视图里,给你要添加事件的菜单项添加一个事件处理,这种方法简单粗暴,只适合少量菜单的程序。

          万一我的菜单项很多,我是不是要添加很多事件处理?不,这样程序会很乱。下面介绍一种MFC提供的批处理方法:

        ON_COMMAND_RANGE(ID_MENU_MAX,ID_MENU_EXIT,&CMenuView::OnMyMenu)      //消息映射
        void OnMyMenu(UINT nID);                                             //函数的声明
          批处理就是对于一些范围的ID,响应同一个函数。批处理发出的消息是ON_COMMAND_RANGE,特别注意,这些ID必须是连续,如果不是连续的,需要自己手动修改,注意也不要重复。

          在实现函数里直接switch传进来的nID就可以了。


怎样实现这样的功能?

     首先要记下是按下了哪个菜单项,我是在view类里添加的批处理,所以在view类里添加了一个成员变量

UINT m_nID:

在进入批处理函数

void CMenuView::OnMyMenu(UINT nID)
的时候,我让

	m_nID = nID;

这时便知道了是哪个菜单项被按下

要想知道哪个菜单项被选中,就得在第二次按菜单的时候才能看出来,这里还是有一个消息

ON_UPDATE_COMMAND_UI_RANGE(ID_MENU_MAX,ID_MENU_EXIT, &CMainFrame::OnMenuOnMy)     //消息映射

afx_msg void OnMenuOnMy(CCmdUI *pCmdUI);                                         //函数声明

ON_UPADTE_COMMAND_UI_RANGE 也是一个批处理消息,是更新用户界面处理的消息

//点击哪个菜单项哪个打对勾
void CMainFrame::OnMenuOnMy(CCmdUI *pCmdUI)
{
	CMenuView* pID = (CMenuView*)GetActiveView();               //定义一个视图类的指针获取当前活动视图(因为我这个update写在了框架里)
	if (pCmdUI->m_nID == pID->getID())                          //pCmdUI这个结构体的m_nID是否和我们点击的ID相同
	{
		pCmdUI->SetCheck();                                //相同就打对勾
	}
	else
	{
		pCmdUI->SetCheck(0);                                 
	}
}

为什么要写成这样呢?因为我们每点击一次菜单,这个更新函数就会走我们菜单项那么多的次数。记录点击的ID,在和传进来的ID做比较,就能在刷新的时候设置好对勾的选项了。


如何在点击视图的时候右键弹出一个菜单?

           首先在视图添加一个右键按下的消息,然后

第一种方法:

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CMenu *menu = AfxGetMainWnd()->GetMenu()->GetSubMenu(0);                          //定义个menu的指针,获得当前框架菜单的第一个子菜单
	ClientToScreen(&point);                                                           //更换传进来左边点的左边,做到跟踪弹出
	menu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTBUTTON,point.x,point.y,this);         //让这个menu弹出一个menu,最后一个参数最好填框架类的指针
	menu->Detach();                                                                    //分离菜单和资源
	
        CView::OnRButtonDown(nFlags, point);
}

第二种方法:

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

        ClientToScreen(&point);
	GetParent()->GetMenu()->GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTBUTTON,point.x,point.y,this);  

	CView::OnRButtonDown(nFlags, point);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值