15. MFC资源使用详解

1.前言

本章继续介绍MFC的剩余内容,如:菜单、工具栏、状态栏等等我们会经常用到的东西。

内容有点繁琐,但其实你只需要掌握其基本用法即可,除非你需要其它特殊的用法,否则不必深入研究。

首先还是老规矩,在解决方案里面建立一个MFC项目,基于对话框,其它默认即可,项目名为:day15-res,设置为启动项。

2.资源

首先我们还是来想想资源是什么,通过前面的使用,大家应该也已经有了点概念。

本质来说,资源其实就是一堆二进制组成的图像,而所谓对话框本质也是图像罢了,只是它特殊点:可以绑定代码,响应系统消息。

所以总的来说,资源就是方便我们进行界面开发的工具。

它有着自己独立的编译器(一般名字为rc.exe),将每一个资源都与对应的ID绑定,然后我们就可以在代码中通过ID来直接使用这个资源。

前面我们已经用过了两种资源,一种是对话框资源,一种是Bmp图片资源。

这些都可以在资源视图里面直接进行操作,如果当前界面看不到视图资源的,需要从视图->其它窗口->资源视图 调出来。

可以看到,这里面首先就是该解决方案中的所有项目,然后我们点开本章的项目资源:

image-20231211080240635

这里已经自动生成了几种资源的文件夹,根据它们的名字你应该也能猜出一二,下面分别介绍。

3.对话框资源

这个资源前面用到的次数应该是最多的,使用方法相信大家已经会了,这里再深入的介绍一下:

image-20231211080324290

除了前面一直用的直接插入外,这里还可以选择添加资源,然后可以看到,其实除了前面我们使用的默认对话框资源,还有很多其它用途的资源:

image-20231211080431961

但这些资源一般我并不常用,因为这些对话框你完全可以通过调整标准对话框完成。

最常见的用法就是先生成一个标准对话框,然后自己需要啥,就调整属性,自己拖一拖控件之类的就行了。

4.Bitmap

Bitmap是一种原生的图片格式,图片中每一点颜色的值用RGB表示,这个值都可以直接在图片的二进制数据中找到。

如果你对BMP图片格式感兴趣,可以看看本站的另一篇文章:BMP图片格式详解

而其它我们非常常见的jpgpng等图片格式,基本都是通过压缩bmp格式实现的,但它们里面的数据格式就会复杂很多。

也正是因为bmp这种图片的格式简单,可以直接读取显示在屏幕上,所以MFC里面就支持了BMP格式。

但这也是比较难受的点,因为现在大部分都是jpg格式与png格式的图片,如果想要在mfc中使用这些格式的图片,你还得自己用其它库来将其转换为BMP格式。

它的使用方法很简单,你可以在VS里面新建,自己画,不过并不推荐,VS这一方面做的并不好,里面画笔之类的工具也不好用。

另一种更好的方式是,直接从外部导入图片,比如从PS里面P好图片,导出为Bmp格式,然后VS导入即可。

它会自动给该资源分配ID,然后在代码中我们就可以通过ID,来使用这张图片,这个前文已经聊过了。

5.Accerlerator

翻译过来为加速器,但其实它就是一个快捷键资源。

上一章介绍的Hot Key控件,曾经提到过如何注册快捷键,相比之下,上一种方法要简便一些,这里通过添加资源的方式,并不常用。

但这里还是简单介绍一下它的使用流程,首先我们需要先拖一个控件,比如一个按钮,双击它就会快速生成响应点击的函数:

image-20231211080900963

这里就弹出个框表示按下了按钮,然后我们添加一下该资源:

image-20231211080946237

然后进行修改:

image-20231211081103557

这里有几个属性:

  1. ID:为按钮的ID,表示与按钮相互关联
  2. 修饰符:快捷键的修饰符,即我们平时使用的Ctrl+C快捷键的Ctrl
  3. :快捷键的键,即我们平时使用的Ctrl+C快捷键的C
  4. 类型:快捷键类型,默认即可

上面的ID我写的是刚才添加的那个按钮的ID,也就是默认生成的ID,我并没有对其进行修改。

然后我们就可以到初始化函数中,通过函数LoadAccelerators加载这个资源,并将它的返回值保存在了成员变量中::

image-20231211081443428

代码如下:

hAccel=LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));

第一个参数是应用程序实例,我们通过调用MFC的AfxGetInstanceHandle函数来获取这个参数。

第二个参数为资源ID字符串,我们通过宏MAKEINTRESOURCE来将加速键资源的ID转换为字符串,ID知道怎么看吧?也就是在资源页面中它的名字。

至于这个宏在win API编程中比较常用,有兴趣的可以去看看它的原理,并不难。

然后我们还需要重载这个对话框基类的虚函数:

image-20231211081759697

目的是翻译我们这个加速键资源的消息:

image-20231211081833465

这里调用了TranslateAccelerator函数,它的前面有两个冒号,前面提到过,::一般是用于命名空间的。

	if (::TranslateAccelerator(GetSafeHwnd(), hAccel, pMsg)) {
		return true;
	}

但这个函数::前面咋没有命名空间呢?这其实就代表这里使用的全局函数,考虑下面这个例子:

#include<iostream>
using namespace std;
void fun() {
	cout << "全局";
}
class Test {
public:
	void fun() {
		cout << "内部";
	}
	void Print() {
		fun();  //调用函数
作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux