当前位置: 首页 > 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选择不记录任何这种…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...