目录
1 创建图形界面应用
在使用Visual C++开发具有图形用户界面的Windows应用程序可以采用以下三种方法之一。
(1)使用Windows API函数 (2)使用MFC (3)使用Visual C++.NET
MFC,微软基础类库。以C++类的形式封装了Windows API,并且包含了一个应用程序框架,以减少开发人员的工作量。
2 VC++数据类型
数据类型
对应的基本数据类型
说明
BOOL
bool
布尔值
BSTR
unsigned short*
16位字符指针
BYTE
unsigned char
8位无符号整数
DWORD
unsigned long
32位无符号整数,段地址和相关的偏移地址
LONG
long
32位带符号整数
LPARAM
long
作为参数传递给窗口过程或回调函数的32位值
LPCSTR
const char*
指向字符串常量的32位指针
LPSTR
char*
指向字符串的32位指针
LPVOID
void*
指向未定义的类型的32位指针
UNIT
unsigned int
32位无符号整数
WORD
unsigned short
16位无符号整数
WPARAM
unsigned int
当作参数传递给窗口过程或回调函数的32位值
VC++还提供一些宏来处理基本数据类型:
LOBYTE和HIBYTE这两个宏分别用来获取16位数值中的低位和高位字节;
LOWORD和HIWORD分别用来获取32位数值中的低16位和高16位字;
MAKEWORD则是将两个16位无符号数合成一个32位无符号数,等等。
字符串类型
字符串类型CString本质上是VC++提供的一个字符串类。
#include "altstr.h"可以利用如下方法连接字符串:
CString gray("Gray");
CString cat("Cat");
CString graycat = gray + cat; //执行后graycat的值为"GrayCat"把一个整数转化成CString类型
CString s;
s.Format("%d", total);
将char* 转化为 CString则直接可采用如下方法:
char * p = "This is a test";
CString s = p;
CString s(p);
或 CString s = "This is a test";
常用到的成员函数还包括:
LPTSTR GetBuffer(); //获得存储字符串的存储区指针
INT GetLength(); //得到字符串长度
BOOL IsEmpty(); //测试CString类对象包含的字符串是否为空。
void Empty(); //使CString类对象包含的字符串为空字符串。
TCHAR GetAt(int nIndex);//获取字符串中指定位置(由nIndex指定)的字符。
void SetAt(int nIndex,TCHAR ch);//将字符串指定的位置处的字符设定为ch。
CString Left(int nCount); //截取字符串左边nCount长度的字符串。
CString Right(int nCount); //截取字符串右边nCount长度的字符串。
字符串中的字符可以是UNICODE字符,也可以是ANSI字符。
句柄类型
句柄类型是Windows程序设计中的一种特殊数据类型,是Windows用来唯一标识应用程序所建立或使用的对象的一个32位的无符号整数值。
Windows程序中需要使用句柄标识的对象包括应用程序实例、窗口、位图、内存块,文件、任务等。
各种句柄类型的命名方式一般都是在对象名前加“H”,比如位图(BITMAP)对应的句柄类型为“HBITMAP”
句柄本质上是一种指向指针的指针
Windows系统为各应用程序预留了一些内存空间,专门用于登记各对象在内存中的地址变化,这些预留空间的地址是不变的,句柄就是指这些预留空间的地址。
在WINDOWS编程中会用到大量的句柄,比如:HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备描述表句柄),HICON(图标句柄)等。
3 UNICODE字符集
ANSI多字节字符集
ANSI编码标准都与ASCII码兼容,并且字符数目要比ASCII字符多很多,因此必需使用多个字节来表示一个字符。ANSI字符集只规定了本国或地区所使用的语言的“字符”,并未考虑其他国家或地区的ANSI码。
UNICODE字符集-UCS
Unicode是Universal Multiple-Octet Coded Character Set的缩写,中文翻译为“通用多八位编码字符集”。
Unicode字符集,其目的是将世界上绝大多数国家的文字符号都编入其中,并为每种语言的每个字符设定唯一的一个二进制编码。
UNICODE字符集:UCS-2、UCS-4UNICODE转换格式-UTF
Unicode转换格式(Unicode Transformation Format,UTF)编码:
规定了如何对UCS对应的基本多语种码点(BMP)进行编码的策略,即规定代码点在计算机中的存储方式。
目前常用的UTF编码包括UTF-8、UTF-16、UTF-16BE(Big Endian)、UTF-16LE(Little Endian)
从Unicode到UTF-8的编码方式如下:
Unicode编码(十六进制) UTF-8 字节流(二进制)
000000 - 00007F 0xxxxxxx
000080 - 0007FF 110xxxxx 10xxxxxx
000800 - 00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Visual C++ 对ANSI和Unicode两种字符集都支持,UTF-16LE是Windows默认的Unicode编码方式,默认采用小端顺序存储。
无论项目使用的是ANSI字符集还是Unicode字符集,程序中用双引号引起来的字符串常量都是单字节字符串,如果需要以双字节字符存储,则需要在字符串前加上L。
在控制台应用程中,双字节字符串与单字节字符串所使用的输入输出函数是不同的,输入、输出双字节字符数据的函数分别是wscanf()和wprintf(),这两个函数使用方法与scanf和printf类似。为了实现同样的代码既适用于宽体字符也适用于窄体字符,微软将这两套字符集的操作进行了统一,对两套字符集所使用的不同的关键字和库函数名,都定义了一致的宏来替代,并使用条件编译来控制。
例如,无论使用那种字符集,字符类型的定义符可使用TCHAR,因为如果要使用窄体字符,则不定义_UNICODE宏,此时TCHAR就是char;如果使用宽体字符,则必须定义_UNICODE宏,这时TCHAR就是wchar_t。
双引号引起的字符串常量可写为_T("Hello World!"),当定义了_UNICODE宏,就相当于L"Hello World!",没定义则相当于"Hello World!"。
相关的字符串操作函数也都有对应的替换函数,比如,tcslen()函数,在定义了_UNICODE宏时它就相当于wcslen(),没定义时则相当于strlen()。
这些宏的定义都在头文件tchar.h中,因此,在程序前面需要有编译预处理命令#include<tchar.h>。但在Visual C++ 中,通常是不需要手工添加的。
4 MFC对话框应用程序
对话框应用程序
是指主窗口样式为“对话框”的应用程序
对话框(Dialog Box)是一种简单的框架窗口,只有标题栏和边框,没有菜单条、工具条和状态条等,通常包含若干控件(Control),通过这些控件,它可以接收用户的输入和选择、向用户显示信息或者响应用户各种操作。
控件是指窗口上的编辑框(Edit Control)、命令按钮(Command Button)、下拉列表框(List Box)等具有一定输入输出功能的小部件。
控件本质上也是一种简单窗口,只不过它必须存在于一个称为其父窗口的窗口内,在对话框中,对话框窗口就是其上各种控件的父窗口。
使用Visual Stdio的应用程序向导,可以创建一个简单的对话框应用程序框架。
VC++开发环境
MFC对话框应用程序结构
MFC应用程序向导会自动生成两个类:
CTestApp,CTestDlg
CTestApp是最重要的一个类,该类派生于CWinApp类。
CWinApp是MFC的主应用程序类,用于控制应用程序的初始化、运行和终止。
MFC应用程序向导生成的应用程序必须有且仅有一个从 CWinApp 派生的类的对象,该对象在创建窗口之前构造。
CTestDlg类的声明如下:
class CTestDlg : public CDialog
它是CDialog类的派生类,而CDialog又是CWnd的派生类,因此在CTestDlg类的实现中,可以使用CDialog类以及CWnd类的所有方法。
设置对话框的属性
对话框窗口的外观和行为特性可通过修改它的属性值进行改变。
对话框窗口的属性可以通过“属性窗口”设置。(上图中右下方的属性窗口)
要设置对话框属性,首先打开“对话框资源编辑器”和“属性窗口”,在新建项目中,这两个窗口默认是被打开的。
常用的对话框属性
ID:ID是应用程序用来唯一标识该对话框资源的标识符,通常使用默认值,也可以对它进行修改。
Caption:对话框的标题,即对话框窗口标题栏显示的文字。默认值为项目名称,通常需要改为编程者认为合适的文字。
Font:在“属性窗口”中该属性的属性值编辑框后有一按钮,单击此按钮可弹出字体对话框,通过该对话框可选择对话框窗口中控件上显示的文字的字体、字形和字号。
Border:用于确定窗口的边框类型,有四个值可选,None无边框,不显示标题栏;Thin细边框,也不显示标题栏;Dialog Fram,对话框边框,程序运行时窗口大小不可改变;Resizing,可调整尺寸,程序运行时对话框窗口的大小可用鼠标拖曳调整。
System menu :该属性用于指定是否为对话框创建系统菜单。该属性值为 Bool类型,缺省值为True。
Minimize box /Maximize box:指定对话框是否有最小化/最大化按钮,这两个属性值均为 Bool类型,缺省值为False。当对话框无标题栏时,即Border属性值为None或Thin时,这两个属性无效。
5 Windows 控件
控件
控件是用于执行用户输入输出动作的一种特殊窗口。
一个完整的控件包括两部分,一是控件资源,即在其父窗口上绘出的控件的图形,另一部分则是封装有控件属性和方法的控件类。
MFC提供了众多的控件类,每一个类都封装一种控件。在对话框中创建控件后,需要为控件定义一个对应控件类的变量(对象)对它进行控制。
创建控件
控件的创建有静态创建和动态创建两种。
静态创建是指使用对话框模板创建控件,并通过属性窗口设置控件的属性,当打开对话框时,系统将自动按预设的属性创建控件。
动态创建则是指在程序的运行中根据需要,通过预先定义的控件类对象调用CreateWindow 函数创建控件。
这里只简单介绍控件的静态创建方法。
第一步是打开“对话框资源编辑器”和“工具箱”。
第二步,在“工具箱”中单击选中要创建的控件,然后将鼠标移到“对话框资源编辑器”中的对话框上,按下鼠标左键进行拖曳,在相应位置画出控件。
第三步,选中画好的控件,通过鼠标拖曳调整控件的大小和位置。
第四步,使用“属性窗口”设置控件的属性。
设置控件属性
每个控件都有一个属性集,通过设置控件的属性可以控制控件的外观和行为等。对于静态创建的控件,可以在对话框模板中打开控件的属性对话框直接设置控件的初始属性值,也可以通过程序代码动态设置控件属性值。
控件的属性往往有很多,但编程时并不是每个属性的值都需要设置,多数情况下使用默认值就可以了。不同类型的控件有不同的属性,但是也有一些属性是共有的。
属性 | 功能 |
---|---|
ID | 程序通过控件ID来访问一个控件。控件创建后系统会自动生成一个ID,可修改。除静态控件外,同一程序中的控件的ID必须互不相同。 |
Visible | 该属性决定程序运行时控件是否可见。属性值是布尔型,默认为TRUE。 |
Disabled | 设置当对话框在打开时该控件是否不可用,也是布尔类型,默认为FALSE。 |
静态控件
是指一组控件类型,包括静态文本(Static Text)控件、图片控件(Picture Control)和组框(Group Box),这些控件主要用来显示文本或图形信息。
同一应用程序中的多个静态控件可以使用相同的ID,通常是它们的默认ID——IDC_STATIC。如果需要在程序中区分和操纵各个不同的静态控件,必须重新为它们分别指定一个唯一的ID。
常用控件
静态文本(Static Text)控件:要用来显示文字,要显示的文本串为该控件的属性Caption的属性值。该属性值可以静态修改,也可以在程序中用赋值语句动态修改。
编辑控件(Edit Control):又称编辑框,通常与静态文本控件一起使用,用于数据的输入和输出。通过设置不同的属性值,编辑控件可以表现为多行编辑框、密码编辑框、只读编辑框等多种不同类型的样式。
命令按钮(Button):命令按钮在被按下时会立即执行某个命令。该命令所执行的操作,是由命令按钮的消息处理函数规定的。命令按钮上显示的文字是由Caption属性指定的,通过修改Caption属性的值可改变命令按钮上显示的文字。
列表框(List Box):常用来显示类型相同的一系列清单,如文件、字体和用户等,适用于从若干数据项中进行选择的场合。列表框是一个矩形窗口,包含若干列表项(每项为一个字符串)。
常用控件
控件名称
MFC类
功能描述
静态控件
CStatic
用来显示一些几乎固定不变的文字或图形
按钮
CButton
用来产生某些命令或改变某些选项,包括单选按钮、复选框和组框
编辑框
CEdit
用于完成文本和数字的输入和编辑
列表框
CListBox
显示一个列表,让用户从中选取一个或多个项
组合框
CComboBox
是一个列表框和编辑框组合的控件
滚动条
CScrollBar
通过滚动块在滚动条上的移动和滚动按钮来改变某些量
进展条
CProgressCtrl
用来表示一个操作的进度
滑动条
CSliderCtrl
通过滑动块的移动来改变某些量,并带有刻度指示
日期时间控件
CDateTimeCtrl
用于选择指定的日期和时间
图像列表
CImageList
一个具有相同大小的图标或位图的集合
标签控件
CTabCtrl
类似于一个文件柜上的标签,使用它可以将一个窗口或对话框的相同区域定义为多个页面
6 消息驱动与消息映射
Windows的消息驱动机制
Windows程序是通过操作系统发送的消息来处理用户输入的。所有Windows应用程序都是消息驱动的,消息处理是所有Windows应用程序的核心部分。
无论是系统产生的动作或是应用程序产生的动作,都称为事件(Events)产生的消息(Message)。
在应用程序中,通过接收消息、分发消息、处理消息来和用户进行交互。
系统中许多消息都经过了严格的定义,并且适用于所有的应用程序。
当用户单击鼠标、敲击键盘或调整窗口大小时,都将向对应的窗口发送消息。每个消息都对应于某个特定的事件,比如单击鼠标事件、双击鼠标事件、鼠标移动事件等。
Windows系统将应用程序的输入事件转换为消息,并将消息发送给应用程序的窗口,这些窗口通过调用消息处理函数来接收和处理这些消息。
消息处理函数通常是窗口类的成员函数,编写消息处理函数是编写MFC应用程序的主要任务。
Windows消息大致可分为标准Windows消息、控件通知和命令消息等类型。
标准Windows消息
通常由窗口类处理,也就是说,这类消息的处理函数通常是MFC窗口类的成员函数。
除WM_COMMAND消息外,所有以“WM_”为前缀的消息都是标准Windows消息。
标准Windows消息都有默认的的处理函数,这些函数是CWnd类的成员函数,函数的名称都是“On”开头,后跟去掉“WM_”前缀的消息名称。
命令消息
包括来自菜单选项、工具栏按钮、快捷键等用户接口界面的WM_COMMAND通知消息,属于用户应用程序自己定义的消息。
通过消息映射机制,MFC框架把命令消息按一定的路径分发给多种类型的的对象来处理,这些对象包括文档、文档模板、应用程序对象、以及窗口和试图等。
能处理消息映射的类必定是从MFC的CCmdTarget类派生的。
控件通知
是由控件传给父窗口的消息,但也有一个例外,当用户单击“命令按钮”按钮控件时,发出的BN_CLICKED消息将作为命令消息来处理。
控件消息通常也是由MFC窗口类处理的。
消息映射
应用程序运行之后,当控件的状态发生改变时,控件就会向其父窗口发送消息,这个消息称为“控件通知消息”。
Windows是通过调用相应消息处理函数来处理每一条消息的,编程时,如何让一条消息与其消息处理函数建立关联关系呢?答案是通过消息映射。
实现消息映射
MFC是通过“类向导”帮助实现消息映射的
类向导会在类的定义(头文件)里增加消息处理函数声明,并添加一行声明消息映射的宏
DECLARE_MESSAGE_MAP。
还会自动在类的实现文件(CPP文件)中添加消息映射的内容,并添加消息处理函数的实现框架(具体功能代码需要由编程者自己编写)。
一般情况下,消息处理函数的声明和实现框架均是由MFC的类向导自动添加和维护的。
7 使用控件变量访问控制控件
控件的主要功能就是完成输入输出,也就是使用户可以与程序交流信息 ;
对话框中某个控件上输入的数据可以保存到程序中的某个变量中,程序中某个变量的值也可以在对话框中的某个控件上输出显示,就是所谓控件与变量的数据交换。
对话框内的控件使用基于ID的变量映射来实现数据交换 。
通过类向导,可以将一个变量和一个控件进行关联(映射)来实现数据交换,并且可设置其数据范围。
与控件关联的变量通常都被称为“控件变量”。
变量的类别对命令按钮来说只有“Control”一种,但对于文本框则会有“Control”和“Value”两种。
“Control”类别的控件变量在程序中代表控件本身,通过该类变量可直接引用该控件类的各种方法,并可以对控件的各种属性直接操作。
只有那些用于输入数据和输出数据的控件才能关联“Value”类别的控件变量,该类控件变量只用于存放控件输出或输入的数据。
对“Control”类别的控件变量,其变量类型只有一种,即该控件对应的控件类。
而“Value”类别的变量类型则可以是任何该控件所能输入或输出的数据类型,对文本框而言,数值类型可以是CString、int、UINT、long、DWORD、float、double、BYTE、short、BOOL等。
当为一个控件添加了一个Value类别的控件变量后,可以使用CWnd::UpdateData函数实现该控件变量与控件的数据交换。该函数是CWnd类的成员函数,其原型如下:
BOOL UpdateData( BOOL bSaveAndValidate = TRUE );
该函数只有一个BOOL类型的参数,调用UpdateData(FALSE)时,数据由控件变量向控件传输,当调用UpdateData(TRUE)或不带参数的UpdateData时,数据从控件向相关联的成员变量复制。
函数执行成功则返回TRUE,否则返回FALSE。
如果为一个控件添加了一个“Control”类别的控件变量,也可以使用该“Control”类型的变量调用控件类从CWnd类继承来的成员函数SetWindowText和GetWindowText来改变或获取控件显示的文字。
如果没有为控件关联变量,可以使用GetDlgItem()得到控件的指针,来访问控件的属性。
如:GetDlgItem(IDC_BUTTON)->SetWindowTextW(_T(“Hello”));
8 用户自定义消息
Visual C++允许用户自己定义并发送消息,对自定义的消息用户也必须为其添加消息处理函数。
第一步,在 resource.h 或 stdax.h或主对话框类的定义文件中添加如下代码定义一个自己的消息:
#define WM_MY_MESSAGE WM_USER +100
其中WM_USER是为了防止用户定义的消息ID与系统的消息ID冲突Visual C++提供的一个宏,小于WM_USER的ID被系统使用,大于WM_USER的ID才可以被用户使用。因此自定义消息一般是WM_USER+XXX的形式,XXX表示任意一个正整数。
然后,打开“MFC类向导”,选择要处理消息的对话框类,选中“消息”选项卡。单击选项卡下部的“添加自定义消息”按钮,弹出 “添加自定义消息”对话框。
分别填入自定义消息和消息处理函数的名称,自定义消息一定是第一步中定义的消息,输入自定义消息后,向导会自动生成一个缺省的消息处理函数名,一般直接采用这个缺省的消息处理函数名则可,当然也可以重新命名该函数。
单击确定返回“MFC类向导”,这时在现有处理程序一列发现刚添加的自定义消息及消息处理函数。
除了函数实现代码外,类向导还在消息处理函数所在的类的头文件中添加了如下的消息处理函数的声明代码:afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
在消息处理函数所在的类的cpp文件中的消息映射添加类似下面的消息映射代码:
BEGIN_MESSAGE_MAP(ClxDlg, CDialogEx)
…
…
ON_MESSAGE(WM_MY_MESSAGE, &ClxDlg::OnMyMessage)
END_MESSAGE_MAP()
发送自定义消息
用户可以在需要的地方通过PostMessage或SendMessage函数来发送自定义消息,例如:
PostMessage(WM_MY_MESSAGE);
PostMessage只把消息放入消息队列,不管消息处理程序是否处理该函数都返回,然后继续执行,也就是说该函数是一个异步消息发送函数;
SendMessage则必须等待消息处理函数处理完了消息之后才返回调用该函数处继续执行,这是个同步消息发送函数;
PostMessage的返回值表示PostMessage函数是否正确执行,而SendMessage的返回值表示消息处理函数的返回值。
9 MFC的文件操作
在MFC中,与文件处理关系较为密切的类有两个,一个是CFile类,另一个是CFileDialog 类。
CFile类是MFC 文件类的基类,它封装了几乎所有的用于文件访问的Win32 API,提供基本的文件输入、输出操作。
CFileDialog 类并不参与文件的处理,它只是封装了应用程序中经常会使用的Windows的文件对话框。
文件对话框提供了一种简单的与Windows 标准相一致的文件打开和文件存盘的对话框功能,它只提供“选择(或输入)要打开或保存的文件路径”的功能。
CFile类
要使用CFile类操作文件,首先要构造CFile对象。
使用缺省构造函数构造 CFile类对象 :缺省构造函数仅仅构造一个没有关联文件的空CFile对象,必须使用Open成员函数来打开文件。
BOOL CFile::Open( LPCTSTR lpszFileName, UINT
nOpenFlags, CFileException* pError = NULL );
lpszFileName:带路径的文件名,指定要打开的文件。
nOpenFlags:指定的文件打开方式,nOpenFlags的取值可以是多个标志的组合,例如:
CFile::modeCreate | CFile::modeWrite。
常用的文件打开方式标志
CFile::modeCreate
调用构造函数构造一个新文件,如果文件已存在,则长度变成0。
CFile::modeNoTruncate
此值与modeCreate组合使用。如果所创建的文件已存在则其长度不变为0;若不存在则由modeCreate标志创建一个新文件。
CFile::modeRead
以只读方式打开文件。CFile::modeReadWrite
以读、写方式打开文件。
CFile::modeWrite
以只写方式打开文件。
CFile::modeNoInherit
阻止文件被子进程继承。
pError:该参数为一个指向CFileException对象的指针,指向的CFileException对象用于保存打开文件出错时抛出的异常,该参数常缺省。
例:
CFile file; //创建对象
file.Open(“d:\\a.txt”,CFile::modeRead ); //以读写方式打开文件
使用构造函数创建对象时直接打开文件
CFile(LPCTSTR lpszFileName, UINT nOpenFlags)
lpszFileName指定的文件名
nOpenFlags指定的文件打开方式
例:
CFile file("d:\\a.txt",CFile::modeRead ); //以只读方式打开D:盘根目录上的文件并构造CFile对象file。
文件读取
CFile类中读取文件的函数是Read(),该函数的格式如下:
virtual UINT Read (void* lpBuf, UINT nCount);
lpBuf:指向用户提供的缓冲区以接收从文件中读取的数据。
nCount:允许从文件中读出的字节数的最大值,对文本模式的文件,回车换行作为一个字符。
函数的返回值是实际读取到缓冲区的字节数,如果读到文件尾,则返回值可能比参数nCount指定的值小。如果函数出错,则会抛出CFileException异常。
文件写入
写文件的成员函数为Write(),该函数的格式如下:
virtual void Write(const void* lpBuf,UINT nCount);
lpBuf:指向用户提供的缓冲区,包含将写入文件中的数据。
nCount:要写入的字节数。对文本模式的文件,回车换行作为一个字符。
该函数将数据从缓冲区写入与CFile 对象相关联的文件。如果函数出错,则会抛出CFileException异常。Write 在几种情况下均产生异常,包括磁盘满的情况。
文件的读写定位
virtual LONG Seek(LONG lOff,UINT nFrom);
lOff:指定针移动的字节数。
nFrom:指针移动的模式,可为以下值之一:
CFile::begin 从文件开始,把指针向后移动lOff 字节。
CFile::current 从当前位置开始,把指针向后移动lOff 字节。
CFile::end 从文件尾开始,把指针向前移动lOff 字节。注意,此时lOff 应为负。如果为正值,则超出文件尾。
该函数在一个已打开的文件中重新定位文件位置指针。如果要求移动道德的位置合法,则返回位置指针从文件开始起的新的偏移量。否则,位置指针将不移动并抛出CFileException 异常。
用于定位文件读写位置的成员函数还有:
void SeekToBegin ();
将文件指针指向文件开始处。
DWORD SeekToEnd (); //返回文件长度(字节数)
将文件指针指向文件逻辑尾部
文件关闭
CFile类用于关闭文件的成员函数有两个,一个是Close(),一个是Abort()。
void Close ();
void Abort ();
Abort()与Close()区别在于Abort()忽略失败,不会因失败而抛出异常而Close()遇到错误则会抛出CFileException异常;
CFileDialog类
CFileDialog 类并不参与文件的处理,它只是封装了应用程序中经常会使用的Windows的文件对话框。
文件对话框提供了一种简单的与Windows 标准相一致的文件打开和文件存盘的对话框功能
只提供“选择或输入要打开或保存的文件路径”的功能,真正的实现文件打开或保存还需要编写另外的代码。
要使用CFileDialog提供的文件对话框,首先要定义一个CFileDialog类的对象。
CFileDialog类的构造函数CFileDialog(
BOOL bOpenFileDialog,
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags =OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL,
CWnd* pParentWnd = NULL
);参数说明:
bOpenFileDialg:如果为TRUE,则创建一个文件打开对话框;如果为 FALSE,则构造一个File Save As(另存为)对话框。
lpszDefExt:缺省文件扩展名,如果用户在文件名编辑框中不包含扩展名,则lpszDefExt 定义的扩展名自动加到文件名后。如果为NULL,则不添加扩展名。
lpszFileName:初始显示于文件名编辑框中的文件名,如果为NULL,则不显示初始文件名。
dwFlags:一个或多个标志的组合,使你可定制对话框。相关标志的使用请读者自己查阅相关资料。
lpszFilter:一列字符串对,指定可以应用到文件的过滤器。如果指定过滤器,仅被过滤器允许的文件显示于文件列表框中。
pParentWnd:指向文件对话框对象的父窗口或拥有者窗口。
对LpszFilter参数的进一步说明
该参数用于指定哪些类型的文件可在文件列表框中显示。 文件的类型决定于扩展名。
该参数为一字符串,可同时指定多个要显示的文件类型,每个类型由“文件类型描述”和“文件扩展名”两部分组成,“文件类型描述”和“扩展名”间用 “|” 分隔,同种类型文件的多个扩展名间可以用“;” 分割,每种文件类型间也是用“|”分隔,字符串的末尾用“ ||” 指明。
例如,Mirosoft Excel 允许用户用.XLC 扩展名(表)或.XLS(工作表)打开文件,Excel 过滤器应如下:
char szFilter[] =″Chart Files (* .xlc)|* .xlc|Worksheet Files(* .xls)|* .xls| Data Files(* .xlc;* .xls)|*.xls;*xls| All Files(* .* )|* .* ||″;
创建CFileDialog对象后通过调用DoModal() 成员函数来显示对话框,用户输入路径和文件名。
DoModal()函数格式如下:
int DoModal;
返回值为IDOK 或IDCANCEL,如果返回IDCANCEL,可调用CommDlgExtendedError 函数来判断是否是发生错误。IDOK 或IDCANCEL 是表明用户选择了OK 还是Cancel 按钮的常数。
用CFileDialog打开的文件,可以使用成员函数GetFileName(),GetFileTitle(), GetFilePath(),GetFileExt()来取得相关信息。
char szFilter[] ="数据文件 (*txt;*.dat)|*.txt,*dat| All Files(*.*)|*.*||";
CFileDialog a(true,".xls",0,0,szFilter);
int x=a.DoModal();
if(x==IDOK)
MesageBox(a.GetPathName());
else
MesageBox(“没有输入文件名”);