12. MFC消息编程与控件使用教程

1.前言

在前面我们写控制台项目时,整个思路都很简单,顺着写就完了,缺啥我们就写啥。

但到了窗口程序这里就不一样了,因为它的运行机制是消息循环

所以到这里我们就得开始转化写代码的思路:需要响应什么消息,我们就写什么代码!

比如我们想要控制程序窗口的大小,那我们就得响应窗口大小变化的消息,其它的类似。

甚至可以说,MFC程序其实就是在面对消息编程。

但不用担心,这些消息并不用你记住,只需要知道有这个东西即可,需要的时候直接在MFC里面找,还是非常方便的。

2.MFC消息的使用

老规矩,还是先建一个MFC的项目吧:

image-20231208185803037

这次的名字为:day12–USE_MFC,中间的选项和上一节一样即可。

既然是面向消息编程,那我们就先来看一看有哪些消息,右键项目,可以进入类向导:

image-20231208185944374

同时注意上方的项目、类名不要选错了:

image-20231208190045723

类名为Dlg结尾的就是窗口类,而我们一般也是为窗口添加消息响应。

然后我们就可以看一看这个窗口有哪些消息:

image-20231208190202560

可以看到,这些消息基本都是WM_开头的,即Windows Message,然后后面就跟着消息的名称。

比如常用的WM_CLOSE消息,就是程序关闭时的消息,如果我们想要响应这个消息也很简单,点击一下这个消息,然后点击右上角的添加处理程序,就会自动生成该消息的处理代码:

image-20231208190254099

然后我们回到该类中,可以看到代码中添加了三个东西,首先看到的应该是实现函数:

image-20231208190338590

然后还有消息映射:

image-20231208190421996

最后是头文件中的函数声明:

image-20231208190450791

知道这些的目的是,当你不想要这个函数了,你需要亲自把它们都删除掉!

当然你也可以直接在类向导里面去删,只不过其默认是将代码都注释掉,而不是直接删除。

然后我们试着在这个函数里面写一些我们自己的函数:

image-20231208190630063

然后运行程序,点击右上角的叉关闭窗口,退出程序时就会弹出一个对话框:

image-20231208190707329

是不是发现用MFC写程序确实非常方便!

这里注意一下我写的代码:

  • AfxMessageBox是MFC自己封装的一个对话框窗口,只能MFC里面用,windows提供的对话框函数为MessageBox,可以自己查查该怎么用。
  • L"":由于MFC默认使用的宽字节字符集,所以MFC里面的函数默认都只接受宽字节字符串,如果想要用多字节字符集,可以自己在项目属性里面更改。

同时还有另外一种写法为:_T("") ,这是一种通用的写法,它会在宽字节字符集下变为L"",多字节字符集下去掉L,其本质就是定义的一个宏,可以用前面我们使用的方法自行查看!

void Cday12USEMFCDlg::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	AfxMessageBox(_T("你正在关闭对话框"));  //使用更加通用的方式_T("")
	CDialogEx::OnClose(); //调用父类的默认处理函数,用于关闭窗口
}

这里再介绍几个常用的消息:

鼠标消息 作用
WM_LBUTTONDOWN 鼠标左键按下的消息
WM_LBUTTONUP 鼠标左键松开的消息
WM_LBUTTONDBLCLK 鼠标左键双击消息
WM_RBUTTONDOWN 鼠标右键按下的消息
WM_RBUTTONUP 鼠标右键松开的消息
WM_RBUTTONDBLCLK 鼠标右键双击消息
WM_MOUSEMOVE 鼠标移动的消息

这个很好记,就是几个常用单词的缩写,左是Left,右是Right,即首字母嘛,然后button为按钮,DWON为下,UP为上,DBLdouble双倍,CLKclick点击。

窗口消息 作用
WM_DESTROY 窗口摧毁时消息,此时窗口无法复原
WM_CLOSE 窗口关闭的消息,可以通过不执行CDialogEx::OnClose();达到不关闭窗口的目的
WM_SIZE 窗口大小改变的消息

上面是一些比较常用的消息,其它更多的消息可以自己慢慢遇到了再看。

3.虚函数

前面介绍了消息,我们还可以在旁边看到虚函数这一项:

image-20231208190922916

虚函数就是前面提到过的类的成员函数,前面加了virtual关键字的。

因为我们的类都是继承于MFC的标准类,所以我们就可以重写其基类的函数。

这里注意一下用词:重载重写有区别,简单来说,函数名相同、参数不同为重载,而在父子类之间函数名与参数可以完全都相同,也就是重写。

我们这里可以看到父类标准对话框的函数还是有很多的,比如我们前面提到过的OnInitDialog函数也在里面。

这里添加一个我们可能常会用到的虚函数OnOk

image-20231208191130459

使用方法与前面的相同,这个函数主要用于退出应用程序。

注意:一定要确定自己选择的是正确的项目与对话框类,因为如果我们生成了关于对话框,那每次进入类向导时,其默认选择的对话框类就是那个关于对话框的,这会导致后面的操作无效。

OnCancel所起的作用基本相同,主要是方便我们区分用户是用哪种方式退出程序,以便于做出不同的处理。

当然,你也可以通过注释掉调用父类的函数,这样它就不会退出程序了:

void Cday12USEMFCDlg::OnOK()
{
	// TODO: 在此添加专用代码和/或调用基类
	AfxMessageBox(_T("通过Ok关闭对话框"));

	//CDialogEx::OnOK();
}

生成的三个代码地点前面提到过,这里不再多说,然后我们运行试一试:

image-20231208191602447

这里我们通过按确定,想要退出程序,但弹出一个窗口。

按了确定键却不退出,这就是因为我们注释掉了调用父类函数的代码。

其它虚函数大家也可以自己都试一试,不明白的网上搜就是了。

除了上面所说的消息与虚函数,我们还可以看到:

image-20231208191644041

命令这一项不用管,它用于生成控件消息函数的,但我们有更简便的方法,一般不用它。

然后后面的成员变量方法,就是当前我们选择的这个类中的成员变量成员函数,一般也用不到,大部分时候我们都是直接在代码文件中手写的。

当然你可能也看到了右边的删除处理程序,但它只是将代码注释起来,并没有完全删除,没有强迫症的话,你用它也行。

但消息映射它似乎不会管,反正能手动删还是建议手动删除吧。

以上就是MFC的对话框的基本使用。

4.资源

前面提到了怎么在类向导中操作窗口,但我们并没有说过如何添加一个窗口。

一般我们的程序也不可能就一个窗口,那也太单调了,所以我们还得学会如何创建一个窗口。

而创建窗口在MFC里面也是非常的简单,就两步:

  1. 创建窗口资源
  2. 为窗口资源绑定一个类

首先我们来创建窗口资源,先来到资源视图,如果你没有看到资源视图,怎么找资源视图我应该就不用多说了吧?前面提到过。

image-20231208191820116

我们可以看到这里有许多类型的资源,但这里我们只先看窗口资源,即Dialog,右键Dialog选择插入即可:

image-20231208191916505

然后就生成了一个默认的窗口,其ID为资源视图中所示的:

image-20231208192013216

首先就是改ID,不然以后窗口的ID全是一个名后面跟一串数字,那谁知道它是干嘛的对吧?

直接右键这个对话框资源点击属性(或者直接按F4):

image-20231208192102033

然后改就行了,但要注意别跟其它的ID重复:

image-20231208192216086

自此,我们第一步就完成了,接下来是第二步,为这个窗口绑定类,方法很简单,就是右键这个窗口,添加类:

image-20231208192252112

然后给这个类命名,最好符合MFC的命名规范,那就是类名前加C,类名后加类型,这里是Dlg

还有就是基类,一般我们默认即可:

image-20231208192345868

然后我们就可以看到生成了两个文件:

image-20231208192423975

这两个文件与前面提到的Dlg一样操作,因为他们都是CDialogEx的子类嘛。

但一开始,他并没有初始化函数OnInitDialog,怎么添加还记得吗?Ctrl+Ahift+X打开类向导,选择该项目,该类,然后添加相应的虚函数即可,过程就不再赘述了。

此时我们就可以在主窗口中使用这个窗口,在主窗口类中添加这个窗口的头文件:

image-20231208192715729

然后我们就可以在任意一个函数里面,实例化一个对象,然后调用DoModal函数,比如我这里是在关闭函数里面调用的:

image-20231208192808573

这时我们运行程序,点击关闭,就会发现,我们刚刚创建的窗口弹出来了,是不是用着很简单!

image-20231208192843124

但这样用着有一个问题,那就是如果我们不关闭这个弹出的对话框,那么我们就没法点击它后面的对话框。

这种对话框叫做模态对话框,与之对应的叫做非模态对话框,使用方法如下。

我们直接定义一个新窗口的成员变量:

image-20231208192933394

然后在初始化函数中创建它:

image-20231208193147016

这里调用的Create函数,传入的参数就是这个对话框资源的ID,然后在我们想要使用的地方调用ShowWindow函数即可:

image-20231208193319916

其参数就是win APi的ShowWindow的参数。

这里将后面的那段代码注释掉了,因为不注释的话,程序就直接结束了!

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux