1.前言
本章继续介绍MFC的剩余内容,如:菜单、工具栏、状态栏等等我们会经常用到的东西。
内容有点繁琐,但其实你只需要掌握其基本用法即可,除非你需要其它特殊的用法,否则不必深入研究。
首先还是老规矩,在解决方案里面建立一个MFC项目,基于对话框,其它默认即可,项目名为:day15-res
,设置为启动项。
2.资源
首先我们还是来想想资源是什么,通过前面的使用,大家应该也已经有了点概念。
本质来说,资源其实就是一堆二进制组成的图像,而所谓对话框本质也是图像罢了,只是它特殊点:可以绑定代码,响应系统消息。
所以总的来说,资源就是方便我们进行界面开发的工具。
它有着自己独立的编译器(一般名字为rc.exe
),将每一个资源都与对应的ID
绑定,然后我们就可以在代码中通过ID
来直接使用这个资源。
前面我们已经用过了两种资源,一种是对话框资源,一种是Bmp
图片资源。
这些都可以在资源视图里面直接进行操作,如果当前界面看不到视图资源的,需要从视图->其它窗口->资源视图 调出来。
可以看到,这里面首先就是该解决方案中的所有项目,然后我们点开本章的项目资源:
这里已经自动生成了几种资源的文件夹,根据它们的名字你应该也能猜出一二,下面分别介绍。
3.对话框资源
这个资源前面用到的次数应该是最多的,使用方法相信大家已经会了,这里再深入的介绍一下:
除了前面一直用的直接插入外,这里还可以选择添加资源,然后可以看到,其实除了前面我们使用的默认对话框资源,还有很多其它用途的资源:
但这些资源一般我并不常用,因为这些对话框你完全可以通过调整标准对话框完成。
最常见的用法就是先生成一个标准对话框,然后自己需要啥,就调整属性,自己拖一拖控件之类的就行了。
4.Bitmap
Bitmap
是一种原生的图片格式,图片中每一点颜色的值用RGB
表示,这个值都可以直接在图片的二进制数据中找到。
如果你对BMP图片格式感兴趣,可以看看本站的另一篇文章:BMP图片格式详解
而其它我们非常常见的jpg
与png
等图片格式,基本都是通过压缩bmp
格式实现的,但它们里面的数据格式就会复杂很多。
也正是因为bmp
这种图片的格式简单,可以直接读取显示在屏幕上,所以MFC
里面就支持了BMP
格式。
但这也是比较难受的点,因为现在大部分都是jpg
格式与png
格式的图片,如果想要在mfc中使用这些格式的图片,你还得自己用其它库来将其转换为BMP
格式。
它的使用方法很简单,你可以在VS里面新建,自己画,不过并不推荐,VS这一方面做的并不好,里面画笔之类的工具也不好用。
另一种更好的方式是,直接从外部导入图片,比如从PS里面P好图片,导出为Bmp
格式,然后VS导入即可。
它会自动给该资源分配ID,然后在代码中我们就可以通过ID
,来使用这张图片,这个前文已经聊过了。
5.Accerlerator
翻译过来为加速器,但其实它就是一个快捷键资源。
上一章介绍的Hot Key
控件,曾经提到过如何注册快捷键,相比之下,上一种方法要简便一些,这里通过添加资源的方式,并不常用。
但这里还是简单介绍一下它的使用流程,首先我们需要先拖一个控件,比如一个按钮,双击它就会快速生成响应点击的函数:
这里就弹出个框表示按下了按钮,然后我们添加一下该资源:
然后进行修改:
这里有几个属性:
- ID:为按钮的ID,表示与按钮相互关联
- 修饰符:快捷键的修饰符,即我们平时使用的
Ctrl+C
快捷键的Ctrl
- 键:快捷键的键,即我们平时使用的
Ctrl+C
快捷键的C - 类型:快捷键类型,默认即可
上面的ID
我写的是刚才添加的那个按钮的ID,也就是默认生成的ID,我并没有对其进行修改。
然后我们就可以到初始化函数中,通过函数LoadAccelerators
加载这个资源,并将它的返回值保存在了成员变量中::
代码如下:
hAccel=LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
第一个参数是应用程序实例,我们通过调用MFC的AfxGetInstanceHandle
函数来获取这个参数。
第二个参数为资源ID字符串,我们通过宏MAKEINTRESOURCE
来将加速键资源的ID转换为字符串,ID知道怎么看吧?也就是在资源页面中它的名字。
至于这个宏在win API
编程中比较常用,有兴趣的可以去看看它的原理,并不难。
然后我们还需要重载这个对话框基类的虚函数:
目的是翻译我们这个加速键资源的消息:
这里调用了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(); //调用函数