首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >VC++6.0入门——第六讲 菜单编程

VC++6.0入门——第六讲 菜单编程

原创
作者头像
Arya
发布2024-11-20 13:57:43
发布2024-11-20 13:57:43
4500
举报
文章被收录于专栏:后端开发专栏后端开发专栏

在文章开始之前,推荐一篇值得阅读的好文章!感兴趣的也可以去看一下,并关注作者!

题目:Text to image论文精读Adma-GAN:用于文本到图像生成的属性驱动内存增强型GAN Attribute-Driven Memory Augment

好事文章地址:https://cloud.tencent.com/developer/article/2467598

作为一项具有挑战性的任务,文本到图像生成旨在根据给定的文本描述生成照片级真实感和语义一致的图像。现有的方法主要是从一个句子中提取文本信息来表示图像,文本表示对生成图像的质量影响很大。然而,在一句话中直接利用有限的信息会遗漏一些关键的属性描述,而这些属性描述是准确描述图像的关键因素。为了缓解上述问题,我们提出了一种有效的带有属性信息补充的文本表示方法。

引出


VC++6.0入门——第六讲 菜单编程

第6讲 菜单编程

菜单栏、工具栏和状态栏是组成Windows程序图形界面的三个主要元素。大多数 Windows应用程序都提供了菜单,作为用户与应用程序之间交互的一种途径。本章主要讲解与菜单相关的编程知识。

在VC++集成开发环境中,单击左边窗格中的Resource View选项卡,可以看到Menu项下有一个名为IDR_MAINFRAME的菜单资源,它就是刚才我们在Menu应用程序界面中所看到的菜单。这是MFC AppWizard为Menu这个单文档程序自动创建的一个主菜单。双击这个菜单资源名称,即可在VC++开发界面的右边窗格中打开菜单编辑器。如图所示。

在CMainFrame中捕获

消息响应捕获顺序

因为CMenuApp类和CMenuDoc类都不是从CWnd类派生的,所以,它们都没有 MessageBox成员函数。我们可以使用全局的MessageBox函数,或者使用应用程序框架的函数:AfxMessageBox,这里,我们使用后者。AfxMessageBox函数的原型声明如下:

int AfxMessageBox(LPCTSTR IpszText,UINT nType MB_OK,UINT nIDHelp =0 )

根据上述试验,可以得知,响应【Test】菜单项命令的顺序依次是:视类、文档类、框架类,最后才是应用程序类。

插曲:删除函数的方法

消息分类

实际上,菜单命令也是一种消息,在Windows中,消息分为以下三类:

  • 标准消息

除WM_COMMAND之外,所有以WM开头的消息都是标准消息。从CWnd派生的类,都可以接收到这类消息。

  • 命令消息

来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND形式呈现。在MFC中,通过菜单项的标识(D)来区分不同的命令消息:在SDK中,通过消息的 wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。

  • 通告消息

由控件产生的消息,例如按钮的单击、列表框的选择等都会产生这类消息,目的是为了向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现的。从CCmdTarget派生的类,都可以接收到这类消息。

通过MSDN提供的MFC类层次结构图,可以发现CWnd类实际上派生于CCmdTarget类。也就是说,凡是从CWd派生的类,它们既可以接收标准消息,也可以接收命令消息和通告消息。而对于那些从CCmdTarget派生的类,则只能接收命令消息和通告消息,不能接收标准消息。

CWnd派生的类既可以接收命令消息,也可以接收标准消息

下面,我们以Menu这个程序为例,来看看菜单命令消息路由的具体过程:当点击某个菜单项时,最先接收到这个菜单命令消息的是框架类。框架类将把接收到的这个消息交给它的子窗口,即视类,由视类首先进行处理。视类首先根据命令消息映射机制查找自身是否对此消息进行了响应,如果响应了,就调用相应响应函数对这个消息进行处理,消息路由过程结束:如果视类没有对此命令消息做出响应,就交由文档类,文档类同样查找自身是否对这个菜单命令进行了响应,如果响应了,就由文档类的命令消息响应函数进行处理,路由过程结束。如果文档类也未做出响应,就把这个命令消息交还给视类,后者又把该消息交还给框架类。框架类查看自已是否对这个命令消息进行了响应,如果它也没有做出响应,就把这个菜单命令消息交给应用程序类,由后者来进行处理。这就是菜单命令的路由过程。

菜单的结构

文件下的整个部分是一个子菜单

创建标记菜单

比如在文件下面加一个标记菜单

指向整个菜单的指针

指向子菜单的指针

代码语言:java
复制
	// 获取指向CMenu对象的指针

	// 1.按照索引访问
	GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);

	// 2.按照id号访问 ID_FILE_NEW
	GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);

创建缺省菜单

加粗显示

代码语言:java
复制
	// setDefaultItem 
	// 通过索引设置粗体
	GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);

	// 通过 id号 设置粗体
    GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);

创建图形菜单

代码语言:java
复制
	// 定义一个位图菜单
	m_bitmap.LoadBitmap(IDB_BITMAP1);
	GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);

图形标记的尺寸,17x17

代码语言:java
复制
	CString str;
	str.Format("x= %d, y= %d", GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
	MessageBox(str);

	// 定义一个位图菜单
	m_bitmap.LoadBitmap(IDB_BITMAP1);
	GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);

菜单项不允许使用

没有生效

表示自己决定

这时所有菜单项是否可以使用,都要由自己来决定

代码语言:java
复制
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
	// TODO: add member initialization code here
	// 设置enable
	m_bAutoMenuEnable = FALSE;
	
}
代码语言:java
复制
	GetMenu()->GetSubMenu(0)->EnableMenuItem(3,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);

如何整个菜单取消

在程序中,如果想要移除一个菜单的话,可以利用CWnd类提供的SetMenu成员函数来实现,该函数的声明形式如下所示:

调用Detach,将句柄和C++对象断开

为了解决这个问题,可以把上述所示代码中的CMenu对象定义为CMainFrame类的一个成员变量。这里,再介绍另一种解决方式。仍把这个菜单对象定义为局部对象,但在调用SetMenu函数把此对象设置为窗口的菜单之后,立即调用CMenu类的另一个成员函数Detach,以便把菜单句柄与这个菜单对象分离。SetMenu函数会把窗口的菜单设置为其参数指定的新菜单,导致窗口重绘,以反映菜单的这种变化,同时也将该菜单对象的所有权交由给窗口对象。而随后的Detach函数会把菜单句柄与这个菜单对象分离,这样,当这个局部菜单对象的生命周期结束时,它不会去销毁一个它不再具有拥有权的菜单。这个菜单在窗口销毁时会自动销毁。因此,我们在上述例6-12所示代码的最后,再添加对菜单对象的Detach函数的调用。

命令更新模式

如果用索引可能会出现问题,最好采用id号设置

右键弹出菜单功能

添加方式

方式一:通过 工程---增加到工程--- , 进行添加

方式二:自己手动添加

显示位置

捕获鼠标右键点击事件

位置不对的原因是:坐标体系不一样,获取的是用户view窗口,而显示的屏幕坐标

代码语言:java
复制
void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	// menu对象,加载资源
	CMenu menu;
	menu.LoadMenu(IDR_MENU1);
	CMenu *pPopup = menu.GetSubMenu(0);

	// 坐标转换
	ClientToScreen(&point);

	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);


	CView::OnRButtonDown(nFlags, point);
}

定义事件

为Menu程序添加快捷菜单上各菜单项命令的响应函数。可以在Resource View选项卡上双击DR_MENU1菜单资源,使其在资源编辑窗口中打开。然后在【显示】菜单项上用单击鼠标右键,从出现的快捷菜单中选择【Class Wizard..】命令,这时会出现如图所示的对话框。该对话框询问是否为DR_MENU1这个资源创建一个新类或者选择一个已有类。可以不用对此做出处理,单击【Cancel】)按钮取消此对话框即可。

分别在CMainFrame和 CMainView中添加command

删除view类中的函数,右键没有反应,是因为

代码语言:java
复制
void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	// menu对象,加载资源
	CMenu menu;
	menu.LoadMenu(IDR_MENU1);
	CMenu *pPopup = menu.GetSubMenu(0);

	// 坐标转换
	ClientToScreen(&point);

	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
		GetParent()); // 用框架类指针


	CView::OnRButtonDown(nFlags, point);
}

动态添加

中间插入

添加菜单项

在原有的最后增加

在原有的中间插入

删除菜单

删除菜单里面的项

定义响应

不会写就先添加一个,然后照猫画虎写


总结

VC++6.0入门——第六讲 菜单编程

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引出
  • 第6讲 菜单编程
    • 在CMainFrame中捕获
    • 消息响应捕获顺序
      • 插曲:删除函数的方法
    • 消息分类
    • 菜单的结构
    • 创建标记菜单
    • 创建缺省菜单
    • 创建图形菜单
    • 菜单项不允许使用
    • 如何整个菜单取消
    • 命令更新模式
    • 右键弹出菜单功能
      • 添加方式
      • 显示位置
      • 定义事件
    • 动态添加
      • 定义响应
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档