【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和回调函数,就可以解决上述问题
    好了,今天的分享就到这里,大家如果发现有什么错误,还请及时指出来,我们大家共同进步!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/89500.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XUbuntu22.04之快速切换Terminal与Chromium窗口(一百八十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

24届近5年南京工业大学自动化考研院校分析

今天给大家带来的是南京工业大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、南京工业大学 学校简介 南京工业大学&#xff08;Nanjing Tech University&#xff09;&#xff0c;简称“南工”&#xff0c;位于江苏省南京市&#xff0c;由国家国防科技工业局、住…

Java多线程编程:实现并发处理的高效利器

Java多线程编程&#xff1a;实现并发处理的高效利器 作者&#xff1a;Stevedash 发表于&#xff1a;2023年8月13日 20点45分 来源&#xff1a;Java 多线程编程 | 菜鸟教程 (runoob.com) ​ 在计算机领域&#xff0c;多线程编程是一项重要的技术&#xff0c;可以使程序同时执…

Idea 反编译jar包

实际项目中&#xff0c;有时候会需要更改jar包源码来达到业务需求&#xff0c;本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为&#xff1a;idea安装路径/plugins/java-decompiler/lib 3、…

【Sklearn】基于K邻近算法的数据分类预测(Excel可直接替换数据)

【Sklearn】基于K邻近算法的数据分类预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理模型原理&#xff1a;数学模型&#xff1a; 2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 K最近邻&#xff08;K-Nearest Neighbors&#xff0c…

搭建网站并内网穿透实现公网访问本地SQL Server数据库【无公网IP内网穿透】

文章目录 前言1. 安装网站运行和发布必备软件2. 安装PHPStudy3. 安装wordpress4. 进入wordpress安装程序&#xff0c;进行网页编辑和设置5. 安装URL插件6. 安装Cpolar7. 创建自己的数据隧道 前言 在普通电脑用户看来&#xff0c;建立自己的网站总是一件高大上的事情&#xff0…

软件测试四年,总结下功能测试用例设计思路

我们为什么要写好一份测试用例呢&#xff1f;测试同学应该都知道测试用例的重要性&#xff0c;测试用例就是我们测试的依据&#xff0c;也是测试过程中不能缺少的测试文档。 一、用例编写规范目的&#xff1a; 1、提高测试用例的可读性&#xff0c;可执行性、合理性。 2、测…

SpringBoot对一个URL通过method(GET、POST、PUT、DELETE)实现增删改查操作

目录 1. rest风格基础2. 开启方法3. 实战练习 1. rest风格基础 我们都知道GET、POST、PUT、DELETE分别对应查、增、改、删除 虽然Postman这些工具可以直接发送GET、POST、PUT、DELETE请求。但是RequestMapping并不支持PUT和DELETE请求操作。需要我们手动开启 2. 开启方法 P…

CSS 盒模型是什么?它包含哪些属性?标准盒模型/怪异盒模型

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 盒模型⭐ 标准盒模型⭐ 怪异盒模型⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感…

微服务Eureka注册中心

目录 一、Eureka的结构和作用 二、搭建eureka-server 三、服务注册 四、服务发现 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 存在的问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址…

关于APP备案、小程序备案的问题,如何备案?

近日&#xff0c;工信部发布了关于开展移动互联网应用程序备案工作的通知。为落实相关法律法规要求&#xff0c;促进互联网行业规范健康发展&#xff0c;进一步做好移动互联网信息服务管理&#xff0c;现组织开展移动互联网应用程序&#xff08;以下简称 APP&#xff09;备案工…

Python Opencv实践 - 图像平移

import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR)#图像平移 #cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) # M是仿射变换矩阵&#xff0c;对于平移来说M是一…

微信小程序实现双向滑动快捷选择价格(价格区间)

实现样子 提示&#xff1a;效果可以自己自定义&#xff0c;自己将文字样式更改为自己项目属性即可 实现达到方法 1、左边为最低价&#xff0c;右边为最高价格&#xff0c;可以拖动左边最低价选择价格。拖动右边为最高价。 2、当两个价格重合时&#xff0c;继续拖动&#xff0…

OPENCV C++(十)gramm矫正+直方图均衡化

两者都是只对单通道使用&#xff0c;对多通道的话 就需要分离通道处理再合并通道 两种方法&#xff0c;第一个要运算次数太多了&#xff0c;第二个只需要查表 伽马矫正函数&#xff0c;这里用第二种方法&#xff0c;且写法有点高级 int gammaCorrection(cv::Mat srcMat, cv::…

RedisDesktopManage

RDM 简介下载安装 简介 RedisDesktopManager&#xff08;RDM&#xff09;是一个开源的跨平台图形界面工具&#xff0c;用于管理和操作 Redis 数据库。它提供了一个用户友好的界面&#xff0c;使用户能够轻松地连接、浏览、查询和修改 Redis 数据&#xff0c;而无需使用命令行界…

数据结构入门:队列

目录 文章目录 前言 1.队列 1.1 队列的概念及结构 1.2 队列的实现 1.2.1 队列的定义 1.2.2队列的初始化 1.2.3 入队 1.2.4 判空 1.2.5 出队 1.2.6 队头队尾数据 1.2.7 队列长度 1.2.8 队列销毁 总结 前言 队列&#xff0c;作为一种重要的数据结构&#xff0c;在计算机科学中扮演…

Web菜鸟教程 - Swagger实现自动生成文档

如果是一个人把啥都开发了&#xff0c;那用不到Swagger-UI&#xff0c;但一般情况是前后端分离的&#xff0c;所以就需要告诉前端开发人员都有哪些接口&#xff0c;传入什么参数&#xff0c;怎么调用&#xff0c;返回什么。有了Swagger-UI就能把这部分文档编写的业务给省去了。…

Android学习之路(2) 设置视图

一、设置视图宽高 ​ 在Android开发中&#xff0c;可以使用LayoutParams类来设置视图&#xff08;View&#xff09;的宽度和高度。LayoutParams是一个用于布局的参数类&#xff0c;用于指定视图在父容器中的位置和大小。 ​ 下面是设置视图宽度和高度的示例代码&#xff1a; …

[保研/考研机试] KY235 进制转换2 清华大学复试上机题 C++实现

题目链接&#xff1a; KY235 进制转换2 https://www.nowcoder.com/questionTerminal/ae4b3c4a968745618d65b866002bbd32 描述 将M进制的数X转换为N进制的数输出。 输入描述&#xff1a; 输入的第一行包括两个整数&#xff1a;M和N(2<M,N<36)。 下面的一行输入一个数…

面试攻略,Java 基础面试 100 问(十二)

如何将字符串转换为基本数据类型&#xff1f; 调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应基本类型&#xff1b; 如何将基本数据类型转换为字符串&#xff1f; 一种方法是将基本数据类型与空字符串&#xff08;””&#xff09;连…