MFC 之 对话框编程入门
前言
如果您已经是MFC高手,那么这篇文章不适合您;如果您写过MFC程序,那么这篇文章可能对您意义不大;如果您是位MFC菜鸟,那么该文章就比较适合您了。本文章是叙述的是通过实例来详细解释如何使用MFC开发应用程序的。笔者选用的开发环境是Visual Studio 2008(简称VS9)专业版中的Visual C++ 2008(VC9),此文章中的主要内容也同样适用于使用Visual C++ 6.0的读者。若问为什么笔者要选择Microsoft(MS)的这款产品,因为笔者认为MS的工具最大优点就在细节上设计非常好,用户用着非常舒服,具体优点会在以后提到。由于笔者此次是第一次写教程,所以有疏略之处,还请读者见谅。
笔者的E-Mail是:lightning_0721@163.com。
绪论
MFC对话框程序,是一种以MFC为框架的Windows窗体程序,开发MFC对话框属于WIN32开发,WIN32开发与16位程序开发不同,除了源文件外,还需有资源文件,在编译时,源文件和资源文件会分别被编译为*.obj和*.res文件,链接时再组合到一起。在资源文件中,描述了应用程序的图标、版本、图像、字符串等信息。在资源文件中一般还会包含resource.h文件,在这个头文件中定义了一些宏,如定义控件的ID值等。
让我们先了解一下什么是对话框:
http://baike.baidu.com/view/119316.htm
以上文字选取百度百科的“对话框”词条。
一、创建项目
上面说了那么多,对于刚刚学习Windows程序开发的读者来说,可能有些摸不着头脑,不过没有关系,接下来笔者将会一起通过一个实例来学习MFC对话框。
使用VS9开发Windows应用程序,第一部是创建一个VC项目(其实VS9的一个开发单元是解决方案,在VC++6.0及以下版本称为工作区),系统会自动生成一个与新建项目同名的解决方案。
在文件菜单中选择“新建”,新建一个项目。在弹出的新建项目对话框中选择MFC应用程序,并在为项目起一个名称,HelloWorld(如果在同一个目录中,已经有一个项目与你要创建的项目同名,那么则会创建失败),点击确定按钮。
然后出现的是MFC应用程序向导,VC将会根据程序员在向导中的设置自动生成一个应用程序框架。首先出现的是一个概述,这个我们不用管他,下一步。
在这步中,设置我们要创建MFC程序的类型,选择“基于对话框”,在最底处,有一个使用Unicode库,关于这个Unicode,我们会在今后的论述中提到,此时不要管它,保持默认选中状态。在右侧设置MFC的使用方法,其中“在共享DLL中使用MFC”是让你编译的程序通过调用动态链接库的方式来运行MFC程序,如果目标机器没有安装VS9或没有VC9的MFC运行库文件的话,那么生成的程序将无法在这种机器上运行,所以程序员要根据具体情况来选择。由于我们是学习目的,所以保持此项默认状态即可,下一步。
在这一步中,向导要求我们设置用户界面(UI)功能。不用管它,保持默认,下一步。
接下来的这一步要设置高级功能,在此只解释Windows套接字选项的含义:如果程序员要开发网络应用程序,那么选择该选项后,系统会自动添加Socket初始化语句(Socket是用于开发网络应用程序的一个模型,具体资料读者可以到网上查阅)。继续下一步。
这是应用程序向导的最后一步,在这一步中,向导问我们列出了将要生成的类的列表(类名可以修改)。好,点击完成按钮,应用程序向导设置完成。
向导运行结束后,开发界面就出现了,左侧的是解决方案的文件资源树(包含一个项目,以及属于该项目的文件),右侧是一个UI设计窗口,在VS9中,这些需要程序员设计的部分默认都是选项卡的形式。
在这个UI设计器上的对话框就是我们的程序界面,此时可以按下F5键或点击工具栏上的绿色箭头按钮来启动调试这个MFC程序了,因为前面已经说过,MFC程序的框架已经由系统为我们搭建完成,这个框架已经是可以编译执行的源代码了,我们只需要在其基础上完成修改和扩充。程序启动后,这个程序的界面就出现在我们面前了。点“取消”或“确定”来结束次对话框程序,对应也可一按键盘上的Esc或Enter键来达到同样效果。如果由于程序员编写的代码有问题导致程序无法响应,那么可以点击VS9调试工具栏上的“停止调试”来终止程序的调试。
如果程序员只想测试程序UI的话,那么可以点击“对话框编辑器”工具栏中的“测试对话框按钮”。
注意在启动调试这个“绿箭头”按钮旁有一个列表框(默认Debug),如果这个程序在开发中,建议保持Debug,如果要发布那么选择Release,读者可以分别用Debug和Release两种模式编译程序,我们可以发现,在Release下生成的程序要比Debug下生成的程序小很多,这是因为系统在Debug模式下生成的程序要包含调试时需要的种种信息
下面我们来设计这个程序的UI,首先在“视图”菜单中选择“工具箱”,这个工具箱窗口中,列出了很多常用的Windows控件(如按钮、复选框、编辑框、标签等),点击一个控件,此时鼠标变为十字型,像使用画图工具一样在设计器上绘出该控件,也可以同过拖拽的方法将控件直接拖到UI设计器中的对话框上,还可以直接双击工具栏中的控件。
在UI设计器上的静态标签“TODO: 在此放置对话框控件。”可以将其删掉。按照上述方法在对话框上绘制一个按钮控件,右击此控件,选择“属性”会出现属性窗口,在这个窗口中,左侧是控件的一种属性,右侧是该属性的当前值,在属性窗口的低端是属性的具体含义。对于按钮控件,我们现在关注Caption属性,即按钮上显示的文字,我们将其设为“Hello World”,输入完毕后按回车键确定。在UI设计器上的那个按钮已经变为“Hello World”了。在看一下按钮的ID属性,这个ID表示对话框每个控件唯一的标识(注意ID为IDC_STATIC的控件代表该控件为静态的,在程序运行时不可以动态的改变改控件的属性,如标签控件。但我们亦可以通过,修改标签的ID改为非IDC_STATIC值,这样这个控件就转为动态控件了,此种控件可以用IDC_STATIC来标识,IDC_STATIC没有唯一的限制,),我们一般需要将该属性值改为更有意义的,如IDC_HELLOWORLD。
下面我们为按钮控件编写事件响应代码,右击Hello World按钮,选择“添加事件处理程序”,依然弹出了一个向导对话框,在消息类型中选择选择按钮要响应的消息,在这个程序中我们是要响应按钮的单击事件(其实在一般情况下,按钮就是用来单击的),所以保持默认“BN_CLICKED”,在类列表中说明了响应代码是作为哪个类的成员函数,默认选择那个以“Dlg”结尾的类,这个类是继承于CDialog类的一个派生类。程序员可以设置自己的“函数处理程序名称”。完成后点击“添加编辑”按钮,进入代码编辑器编辑代码(对于按钮这种简单控件,我们要添加其响应代码,一般在UI设计器中直接双击这个控件即可直接进入到代码编辑器中编辑响应默认消息的函数)。
系统为我们自动在CHelloWorldDlg类中添加了OnBnClickedHelloworld()函数,该函数的声明部分在HelloWorldDlg.h文件中,在VS9开发环境的右侧“解决方案资源管理器”中双击该文件,或在HelloWorldDlg.cpp文件中右击,在弹出菜单中选择“转到头文件”。让我们来看一下这个MFC框架是如何构成的。
在这个头文件的头部有一行“#pragma once”,这是条编译命令,功能是让次头文件(Header)在编译时只被编译一次,因为同一个头文件可能被包含(include)过多次。在这个头文件中定义了CHelloWorld类,在这个类中声明了一个HICON类型的m_hIcon成员变量,这是个描述该应用程序图标的变量。如果你不了解HICON这个非标准类型,可以在代码的HICON处右击鼠标,然后选择“转到声明”或“转到定义”,这是VS9会自动定位光标到HICON的声明或定义代码处,笔者认为这是一个非常体贴的功能,为团队开发提供了很大的便利。
这里,我们顺便来简单谈谈MFC采用的“匈牙利标识符命名法”,这是一个约定,可以增加代码的可读性。如果你声明或定义了一个类,那么这个类可以一“C”(class)为前缀,如CHelloWorldDlg类,如果要定义一个无符号型的局部变量,那么可以用“u”(unsigned)为前缀,如UINT uPort; ULONG uFlags;如果是int或long类型的变量则以“n”为前缀,DWORD类型的变量前缀为“dw”,字符数组以“sz”作为前缀,CString类的对象以“str”作为前缀,指针以“lp”或“p”(long pointer或pointer,在WIN32环境下这两种指针并没有什么差别)作为前缀,引用以“r”为前缀,布尔型变量以“b”为前缀,句柄型的变量以“h”(handle)作为前缀。如果变量是全局的,那么以“g_”(global)开头,如BOOL g_bFlags;如果是类的成员变量则以“m_”(member)开头,如HICON m_hIcon;。
讨论完MFC的命名规则,让我们继续看这个头文件,在此类中声明了一个标准构造函数CHelloWorldDlg(CWnd* pParent = NULL);可选形参CWnd* pParent指定此对话框的父窗口。
代码enum { IDD = IDD_HELLOWORLD_DIALOG };的意思是MFC巧妙的将ID为IDD_HELLOWORLD_DIALOG的对话框资源与CHelloWorldDlg类绑定在一起。