当前位置: 首页 > news >正文

【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏-笔记

本专栏上几篇文章讲解了MFC几大机制,今天带领大家学习MFC自定义消息以及常用控件,最常用的控件请查看本专栏第一二篇文章,今天这篇文章介绍工具栏,菜单和状态栏,以及菜单创建大总结。

文章目录

  • MFC消息分类:
  • 菜单创建方法总结
      • 1.对话框上直接添加菜单资源:
      • 2. 在WM_CREATE消息处理中加载菜单,设置菜单
      • 3.框架类Create方法中创建
      • 4.使用CMenu对象创建
  • MFC范围宏:
  • 工具栏控件
  • 状态栏控件
  • 右键消息处理:
  • 总结

MFC消息分类:

  • Windows下的常用消息(标准消息)

    win32 WM_CREATE WM_PAINT

  • 在Win32消息前添加ON_

    WM_COMMAND 菜单按钮,加速键是单独处理的

  • 用户自定义消息:

    #define MY_MSG WM_USER+N
    用户自定义消息,我们在MFC中使用通配:ON_MESSAGE(ID,PFUN)也就是说:
    在消息映射中,
    BEGIN_MESSAGE_MAP(CMyFrameWdn,CFreamWnd)ON_WM_CREATE()
    END_MESSAGE_MAP()而这个消息,MFC早就帮我们写好了,我们可以自己去看一看,由于这是一个虚函数,我们也可以重写:
    在类中:
    int OnCreate(LPCRATESTRUCT cs){AfxMessageBox(L"WM_CREATE");return 0;
    }
    我们运行发现,这时候,WM_CREATE消息,处理的时候,就是我们自己写的函数了
    
  • 用户自定义消息:
    首先,我们需要去定义宏,我们自定义消息:
    #define MY_MSG WM_USER+1
    用户自定义消息,MFC已经帮我们写好了统配消息映射:ON_MESSAGE()
    接下来,我们来看看官方定义:

#define ON_MESSAGE(message, memberFxn) \{ message, 0, 0, 0, AfxSig_lwl, \(AFX_PMSG)(AFX_PMSGW) \(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \(memberFxn)) },

那么我们就可以自己定义函数:

  1. 首先,设置签名:
	afx_msg LRESULT onMyMsg(WPARAM,LPARAM);
  1. 实现:
LRESULT CMenuToolBarDlg::onMyMsg(WPARAM W,LPARAM L)
{AfxMessageBox(L"My_Msg");return 0;
}

这里就弹一个消息框
3. 我们发送消息看看:

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码AfxMessageBox(L"onCreate");SendMessage(MY_MSG, 0, 0);return 0;
}

这里是重写了Create函数,发送了我们自定义的消息

菜单创建方法总结

之前几篇文章中我们已经讲解过了好几种加载菜单的方法,今天我们来总结一下

1.对话框上直接添加菜单资源:

这种方法可谓是非常简单了,直接在对话框属性上添加菜单,MFC会自动帮我们生成代码:
首先我们创建菜单资源:
菜单资源
然后到对话框属性中设置就可以了:
设置菜单
这样就算设置好了,我们运行:
菜单
我们发现对话框已经创建好了

2. 在WM_CREATE消息处理中加载菜单,设置菜单

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码HMENU hMenu = LoadMenu((HINSTANCE)GetWindowLongPtr(m_hWnd, GWLP_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));::SetMenu(m_hWnd, hMenu);return 0;
}

这样运行之后,我们发现菜单也创建出来了

3.框架类Create方法中创建

我们前面在介绍MFC几大机制的时候,介绍了框架类,我们使用框架类的Create方法也可以创建菜单:
基本使用方法就是CFRame::Create(…);

4.使用CMenu对象创建

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码CMenu menu;menu.LoadMenuW(IDR_MENU1);this->SetMenu(&menu);return 0;
}

使用CMenu这种方法也可以创建菜单,但是创建了菜单之后,点击之后,会崩溃:
崩溃信息
(这里我创建的MFC是基于对话框的,之前在基于单文档架构的时候会崩溃)
这是应为CMenu对象被析构
解决方法:在类中声明CMenu成员,new出来,这样就不会被析构:
我们首先声明成员:CMenu* menu = new CMenu;
这样时候,我们函数这样写:

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码menu->LoadMenuW(IDR_MENU2);this->SetMenu(menu);return 0;
}

这样创建就没有问题了。

MFC范围宏:

我们在处理按钮或者菜单消息等的时候,我们有时候有这种需求:连续几个按钮,都有着相同的回调方法,这时候,我们就可以使用范围宏:

  1. 首先我们来创建这样一个菜单:
    菜单
    我们将这三个菜单ID设置为连续,我这里是32273,32274,32275
    我们到消息映射中使用范围宏来处理:
    我们首先来看一下范围宏的定义:
#define ON_COMMAND_RANGE(id, idLast, memberFxn) \{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_RANGE, \(AFX_PMSG) \(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT) > \(memberFxn)) },

我们到消息映射中添加:

ON_COMMAND_RANGE(ID_32773,ID_32775,onRangle)

然后我们定义回调函数:

void CMenuToolBarDlg::onRangle(UINT id)
{CString str;str.Format(L"按钮id = %d", id);AfxMessageBox(str);
}

这样我们就可以统一处理这三个按钮了:
范围宏处理

工具栏控件

  1. 我们到资源中创建工具栏对象:
    工具栏
  2. 然后,我们加载工具栏:
    首先我们要在类中声明CToolBar成员:
    CToolBar toolBar
    然后,到Create函数中加载工具栏:
	if (!toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS) || !toolBar.LoadToolBar(IDR_TOOLBAR1)){ AfxMessageBox(TEXT("Failed to create toolbar!"), NULL, NULL);return FALSE;}m_toolBar.EnableDocking(CBRS_ALIGN_ANY);this->EnableDocking(CBRS_ALIGN_ANY);this->DockControlBar(&m_toolBar,AFX|IDW_DOCKBAR_TOP);

很多软件的提示栏,我们鼠标移动到上面的时候,都有提示信息,我们也可以到工具栏的按钮上面添加提示信息:
比如紫色\n按钮
\n之前的信息会出现在状态栏上,之后的信息,我们鼠标移动到上面的时候,会直接显示.

状态栏控件

状态栏控件我们不需要添加资源,直接在创建窗口的时候加载就可以了:

类中添加成员
SCtatusBar statusBar;onCreate消息中:
statusBar.CreateEx(this);

我们发现状态栏只有一项,如果我们想添加,就要定义一个全局数组:
UNIT g_arr[]= {0,ID_TIME,2,};
我们再来设置:

指示器 
statusBar.SetIndicators(g_arr,3);
//ID---表示字符串
statusBar.SetPaneInfo(1,ID_TIME,SBPS_NORMAL,100);

这时候就发现可以分项了。
我们来处理一下状态栏:
我们设置系统时间到状态栏上:
消息映射:

ON_WM_TIMER()
void CMenuToolBarDlg::OnTimer(UINT_PTR id)
{SYSTEMTIME time;::GetLocalTime(&time);CString str;str.Format(L"%d-%d-%d %d:%d:%d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);staubar.SetPaneText(1, str);
}

右键消息处理:

以前我们处理右键单击消息都是通过消息来处理的,今天我来带领大家使用MFC的另一种方式:
消息映射:

N_WM_CONTEXTMENU()

处理:

void onContextMenu(CWnd*,CPoint pt){CMenu menu;menu.LoadMenu(IDR_MENU1);CMenu* pPopMenu = menu.GetSubMenu(0);::tRACKpOPUPmENU(PpOPmENU->m_hMenu,TPM_CENTERALIGN,pt.x,pt.y,0,this->hWnd,NULL);;
}

我们通常使用右键来弹出右键菜单,这里介绍一种方式,弹出右键菜单的时候,可以初始化:

void onInitMenuPopup(CMenu* pMenu,UINT,BOOL){::CheckMenuItem(pMenu->m_hMenu,ID_DEL,MF_CHECKED);
}

总结

最后总结一下容易出现的误区:

  1. 我们使用MFC消息映射的时候,很多时候都需要我们自己写函数,但是很多时候我们会写错,不知道参数该些什么,返回值该写什么,实际上,我们查看宏定义(就是消息映射上的宏)就可以看到函数名称,返回值,参数等
  2. 或者我们再定义宏的时候,可以在括号里写上消息ID和回调函数,就可以解决上述问题
    好了,今天的分享就到这里,大家如果发现有什么错误,还请及时指出来,我们大家共同进步!!!

相关文章:

【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏-笔记

本专栏上几篇文章讲解了MFC几大机制&#xff0c;今天带领大家学习MFC自定义消息以及常用控件&#xff0c;最常用的控件请查看本专栏第一二篇文章&#xff0c;今天这篇文章介绍工具栏&#xff0c;菜单和状态栏&#xff0c;以及菜单创建大总结。 文章目录 MFC消息分类&#xff1…...

Clickhouse 数据存储

一、数据分区 数据是以分区目录的形式组织的&#xff0c;每个分区独立分开存储.这种形式&#xff0c;查询数据时&#xff0c;可以有效的跳过无用的数据文件。 1.1 数据分区的规则 分区键的取值&#xff0c;生成分区ID&#xff0c;分区根据ID决定。根据分区键的数据类型不同&am…...

c语言每日一练(3)

前言&#xff1a;每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;暑假时三天之内必有一更&#xff0c;到了开学之后&#xff0c;将看学业情…...

java基础-Stream(流)、File(文件)和IO

Java中的流(Stream)提供了一个统一的接口来处理输入和输出数据&#xff0c;文件(File)提供了一种简单的方式来操作磁盘上的文件&#xff0c;而I/O则允许我们在Java程序中读写数据。 一、流Stream java中得stream是一种抽象概念&#xff0c;流可以从多种来源读取数据&#xff…...

el-table实现指定列合并

table传入span-method方法可以实现合并行或列&#xff0c;方法的参数是一个对象&#xff0c;里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组&#xff0c;第一个元素代表rowspan&#xff0c;第二个元素…...

38.利用matlab解 有约束无约束的参数估计对比(matlab程序)

1.简述 1.离散型随机变量的极大似然估计法: (1) 似然函数 若X为离散型, 似然函数为 (2) 求似然函数L(θ)的最大值点 θ, 则θ就是未知参数的极大似然估计值. 2.连续型随机变量的极大似然估计法: (1) 似然函数 若 X 为连续型, 似然函数为 (2) 求似然函数L(θ)的最大值点θ, 则…...

什么是React?React与VU的优缺点有哪些?

什么是React&#xff1f;什么是VUE&#xff1f; 维基百科上的概念解释&#xff0c;Vue.js是一个用于创建用户界面的开源MVVM前端JavaScript框架&#xff0c;也是一个创建单页应用的Web应用框架。Vue.js由尤雨溪&#xff08;Evan You&#xff09;创建&#xff0c;由他和其他活跃…...

区块链技术助力慈善,为您的善举赋予全新力量!

我们怀揣着一颗温暖的心&#xff0c;秉承着公开透明的理念&#xff0c;带着信任与责任&#xff0c;倾力打造了一套区块链技术驱动的去中心化捐赠与物资分发系统&#xff0c;通过智能生态网络&#xff08;IEN&#xff09;解决捐赠不透明问题的系统&#xff0c;让您的善举直接温暖…...

模拟实现消息队列项目(系列4) -- 服务器模块(内存管理)

目录 前言 1. 创建MemoryDataCenter 2. 封装Exchange 和 Queue方法 3. 封装Binding操作 4. 封装Message操作 4.1 封装消息中心集合messageMap 4.2 封装消息与队列的关系集合queueMessageMap的操作 5. 封装未确认消息集合waitMessage的操作 6. 从硬盘中恢复数据到内存中 7. Memo…...

STM32 LoRa源码解读

目录结构&#xff1a; SX1278 |-- include | |-- fifo.h | |-- lora.h | |-- platform.h | |-- radio.h | |-- spi.h | |-- sx1276.h | |-- sx1276Fsk.h | |-- sx1276FskMisc.h | |-- sx1276Hal.h | |-- sx1276LoRa.h | -- sx1276LoRaMisc.h – src |-- fifo.c |-- lora.c |-- …...

【BASH】回顾与知识点梳理(十)

【BASH】回顾与知识点梳理 十 十. 文件的格式化与相关处理10.1 格式化打印&#xff1a; printf10.2 awk&#xff1a;好用的数据处理工具awk 的逻辑运算字符 10.3 文件比对工具diffcmppatch 10.4 文件打印准备&#xff1a; pr 该系列目录 --> 【BASH】回顾与知识点梳理&#…...

【网络】应用层——HTTPS协议

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; HTTPS协议 &#x1f349;HTTP的不安全性&#x1f349;认识HTTPS协议&#x1f353;加密解密&#x1f35…...

Windows新版文件资源管理器经常在后台弹出的临时解决方案

禁用组策略自动刷新 运行gpedit.msc找到计算机配置->管理模板->系统->组策略找到 “关闭组策略的后台刷新”启用 参考 https://answers.microsoft.com/en-us/windows/forum/all/windows-11-most-recently-opened-explorer-window/26e097bd-1eba-4462-99bd-61597b5…...

软考高项(八)项目整合管理 ★重点集萃★

&#x1f451; 个人主页 &#x1f451; &#xff1a;&#x1f61c;&#x1f61c;&#x1f61c;Fish_Vast&#x1f61c;&#x1f61c;&#x1f61c; &#x1f41d; 个人格言 &#x1f41d; &#xff1a;&#x1f9d0;&#x1f9d0;&#x1f9d0;说到做到&#xff0c;言出必行&am…...

基于python+django开发的学生信息管理系统

基于pythondjangovue.js开发的学生信息管理系统&#xff0c;师弟的课程作业 功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;学生管理、班级管理、用户管理、日志管理、系统信息模块…...

mysql的高级查询语句

目录 一、本文前言 二、高效查询方式 1&#xff09;指定指字段进行查看 2&#xff09;对字段进行去重查看 3&#xff09;where条件查询 4&#xff09;and 和 or 进行逻辑关系的增加 5&#xff09;查询取值列表中的数据 6&#xff09;between的引用 7&#xff09;like…...

04-8_Qt 5.9 C++开发指南_QTableWidget的使用

文章目录 1. QTableWidget概述2. 源码2.1 可视化UI设计2.2 程序框架2.3 qwintspindelegate.h2.4 qwintspindelegate.cpp2.5 mainwindow.h2.6 mainwindow.cpp 1. QTableWidget概述 QTableWidget是Qt中的表格组件类。在窗体上放置一个QTableWidget 组件后,可以在 PropertyEditor…...

《golang设计模式》第二部分·结构型模式-01-适配器模式(Adapter)

文章目录 1. 概念1.1 角色1.2 应用场景1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 示例类图 1. 概念 定义一个适配器&#xff0c;帮助原本不能实现接口的类“实现”该接口 1.1 角色 目标&#xff08;Target&#xff09;&#xff1a;客户端调用的目标接口 被适配者&#xff08…...

机器学习概述及其主要算法

目录 1、什么是机器学习 2、数据集 2.1、结构 3、算法分类 4、算法简介 4.1、K-近邻算法 4.2、贝叶斯分类 4.3、决策树和随机森林 4.4、逻辑回归 4.5、神经网络 4.6、线性回归 4.7、岭回归 4.8、K-means 5、机器学习开发流程 6、学习框架 1、什么是机器学习 机器…...

识jvm堆栈中一个数据类型是否为为引用类型,目前虚拟机实现中是如何做的?

调用栈里的引用类型数据是GC的根集合&#xff08;root set&#xff09;的重要组成部分&#xff1b;找出栈上的引用是GC的根枚举&#xff08;root enumeration&#xff09;中不可或缺的一环。 要看JVM选择用什么方式。通常这个选择会影响到GC的实现。 如果JVM选择不记录任何这种…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...