1.前言
在前面我们写控制台项目时,整个思路都很简单,顺着写就完了,缺啥我们就写啥。
但到了窗口程序这里就不一样了,因为它的运行机制是消息循环。
所以到这里我们就得开始转化写代码的思路:需要响应什么消息,我们就写什么代码!
比如我们想要控制程序窗口的大小,那我们就得响应窗口大小变化的消息,其它的类似。
甚至可以说,MFC程序其实就是在面对消息编程。
但不用担心,这些消息并不用你记住,只需要知道有这个东西即可,需要的时候直接在MFC里面找,还是非常方便的。
2.MFC消息的使用
老规矩,还是先建一个MFC的项目吧:
这次的名字为:day12–USE_MFC,中间的选项和上一节一样即可。
既然是面向消息编程,那我们就先来看一看有哪些消息,右键项目,可以进入类向导:
同时注意上方的项目、类名不要选错了:
类名为Dlg
结尾的就是窗口类,而我们一般也是为窗口添加消息响应。
然后我们就可以看一看这个窗口有哪些消息:
可以看到,这些消息基本都是WM_
开头的,即Windows Message
,然后后面就跟着消息的名称。
比如常用的WM_CLOSE
消息,就是程序关闭时的消息,如果我们想要响应这个消息也很简单,点击一下这个消息,然后点击右上角的添加处理程序,就会自动生成该消息的处理代码:
然后我们回到该类中,可以看到代码中添加了三个东西,首先看到的应该是实现函数:
然后还有消息映射:
最后是头文件中的函数声明:
知道这些的目的是,当你不想要这个函数了,你需要亲自把它们都删除掉!
当然你也可以直接在类向导里面去删,只不过其默认是将代码都注释掉,而不是直接删除。
然后我们试着在这个函数里面写一些我们自己的函数:
然后运行程序,点击右上角的叉关闭窗口,退出程序时就会弹出一个对话框:
是不是发现用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
为上,DBL
为double
双倍,CLK
为click
点击。
窗口消息 | 作用 |
---|---|
WM_DESTROY | 窗口摧毁时消息,此时窗口无法复原 |
WM_CLOSE | 窗口关闭的消息,可以通过不执行CDialogEx::OnClose(); 达到不关闭窗口的目的 |
WM_SIZE | 窗口大小改变的消息 |
上面是一些比较常用的消息,其它更多的消息可以自己慢慢遇到了再看。
3.虚函数
前面介绍了消息,我们还可以在旁边看到虚函数这一项:
虚函数就是前面提到过的类的成员函数,前面加了virtual
关键字的。
因为我们的类都是继承于MFC的标准类,所以我们就可以重写其基类的函数。
这里注意一下用词:重载
与重写
有区别,简单来说,函数名相同、参数不同为重载,而在父子类之间函数名与参数可以完全都相同,也就是重写。
我们这里可以看到父类标准对话框的函数还是有很多的,比如我们前面提到过的OnInitDialog
函数也在里面。
这里添加一个我们可能常会用到的虚函数OnOk
:
使用方法与前面的相同,这个函数主要用于退出应用程序。
注意:一定要确定自己选择的是正确的项目与对话框类,因为如果我们生成了关于对话框,那每次进入类向导时,其默认选择的对话框类就是那个关于对话框的,这会导致后面的操作无效。
与OnCancel
所起的作用基本相同,主要是方便我们区分用户是用哪种方式退出程序,以便于做出不同的处理。
当然,你也可以通过注释掉调用父类的函数,这样它就不会退出程序了:
void Cday12USEMFCDlg::OnOK()
{
// TODO: 在此添加专用代码和/或调用基类
AfxMessageBox(_T("通过Ok关闭对话框"));
//CDialogEx::OnOK();
}
生成的三个代码地点前面提到过,这里不再多说,然后我们运行试一试:
这里我们通过按确定,想要退出程序,但弹出一个窗口。
按了确定键却不退出,这就是因为我们注释掉了调用父类函数的代码。
其它虚函数大家也可以自己都试一试,不明白的网上搜就是了。
除了上面所说的消息与虚函数,我们还可以看到:
命令这一项不用管,它用于生成控件消息函数的,但我们有更简便的方法,一般不用它。
然后后面的成员变量与方法,就是当前我们选择的这个类中的成员变量与成员函数,一般也用不到,大部分时候我们都是直接在代码文件中手写的。
当然你可能也看到了右边的删除处理程序,但它只是将代码注释起来,并没有完全删除,没有强迫症的话,你用它也行。
但消息映射它似乎不会管,反正能手动删还是建议手动删除吧。
以上就是MFC的对话框的基本使用。
4.资源
前面提到了怎么在类向导中操作窗口,但我们并没有说过如何添加一个窗口。
一般我们的程序也不可能就一个窗口,那也太单调了,所以我们还得学会如何创建一个窗口。
而创建窗口在MFC里面也是非常的简单,就两步:
- 创建窗口资源
- 为窗口资源绑定一个类
首先我们来创建窗口资源,先来到资源视图,如果你没有看到资源视图,怎么找资源视图我应该就不用多说了吧?前面提到过。
我们可以看到这里有许多类型的资源,但这里我们只先看窗口资源,即Dialog
,右键Dialog
选择插入即可:
然后就生成了一个默认的窗口,其ID为资源视图中所示的:
首先就是改ID,不然以后窗口的ID全是一个名后面跟一串数字,那谁知道它是干嘛的对吧?
直接右键这个对话框资源点击属性(或者直接按F4
):
然后改就行了,但要注意别跟其它的ID重复:
自此,我们第一步就完成了,接下来是第二步,为这个窗口绑定类,方法很简单,就是右键这个窗口,添加类:
然后给这个类命名,最好符合MFC的命名规范,那就是类名前加C
,类名后加类型,这里是Dlg
。
还有就是基类,一般我们默认即可:
然后我们就可以看到生成了两个文件:
这两个文件与前面提到的Dlg
一样操作,因为他们都是CDialogEx
的子类嘛。
但一开始,他并没有初始化函数OnInitDialog
,怎么添加还记得吗?Ctrl+Ahift+X
打开类向导,选择该项目,该类,然后添加相应的虚函数即可,过程就不再赘述了。
此时我们就可以在主窗口中使用这个窗口,在主窗口类中添加这个窗口的头文件:
然后我们就可以在任意一个函数里面,实例化一个对象,然后调用DoModal
函数,比如我这里是在关闭函数里面调用的:
这时我们运行程序,点击关闭,就会发现,我们刚刚创建的窗口弹出来了,是不是用着很简单!
但这样用着有一个问题,那就是如果我们不关闭这个弹出的对话框,那么我们就没法点击它后面的对话框。
这种对话框叫做模态对话框,与之对应的叫做非模态对话框,使用方法如下。
我们直接定义一个新窗口的成员变量:
然后在初始化函数中创建它:
这里调用的Create
函数,传入的参数就是这个对话框资源的ID
,然后在我们想要使用的地方调用ShowWindow
函数即可:
其参数就是win APi的ShowWindow
的参数。
这里将后面的那段代码注释掉了,因为不注释的话,程序就直接结束了!