[MFC]公用对话框介绍、CFileDialog

1. 公用对话框:

    1) 在使用Windows时有些对话框可能用得太频繁了,以至于并不是所有应用程序都愿意重复开发这些使用如此频繁的对话框,像打开文件的对话框、设置字体的对话框等等;

    2) MFC为这些对话框封装了专门的类,使得用户可以非常方便地在程序中建立这样的对话框来减轻开发负担;

    3) 这里列举几个非常常用的公用对话框类:

CFileDialog:Open和Save As对话框,这个使用实在是太频繁了;

CPrintDialog:Print和Print Setup对话框,打印和打印设置对话框使用也非常频繁;

CPageSetupDialog:Page Setup对话框,即页面设置对话框;

CFindReplaceDialog:Find和Replace对话框;

CColorDialog:Color对话框,里面有调色板可以设置颜色;

CFontDialog:Font对话框,用来设置字体,里面的列表框可以显示系统安装的字体;

!!我们重点介绍CFileDialog对话框类;


2. CFileDialog的创建:

    1) 该类型对话框的属性和行为基本都是由构造函数的参数决定的,但是不妨先看一下普通的CFileDialog对话框的一些基本元素;

[MFC]公用对话框介绍、CFileDialog_第1张图片

    2) 观察一下该种类型对话框的几个重要的元素:

         i. 文件列表框、打开、取消按钮自然不用说了,这些部件在CFileDialog中都已经实现了,无需用户关心;

         ii. 其次是文件名这一编辑框,刚打开时里面就有默认的文件名存在了,该默认文件名就是其构造函数的第三个参数lpszFileName决定的;

         iii. 之后就是一个文件类型的下拉列表框,里面含有文件列表中只能显示的文件类型,里面的每一项都称为一个文件过滤器,比如当前过滤器的类型是.phn文件,因此只能在文件列表中显示.phn文件;

!!但是无论使用何种过滤器都能显示文件夹(即目录文件),因为你要查找的文件有可能是包含在某个文件夹中的,所以不管查找何种类型的文件都是会显示文件夹的;

    3) 接下来我们看一下CFileDialog的构造函数,将上面所说的一些元素和构造函数的参数对应起来:

         i. 函数原型:

CFileDialog::CFileDialog( 
	BOOL bOpenFileDialog,
	LPCTSTR lpszDefExt = NULL,
	LPCTSTR lpszFileName = NULL,
	DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
	LPCTSTR lpszFilter = NULL,
	CWnd* pParentWnd = NULL
); 
         ii. bOpenFileDialog:如果为TRUE就是Open对话框,FALSE代表Save As对话框;

         iii. lpszDefExt:即Defualt Extension的意思,即默认扩展名,该字符串将决定了,如果上面的文件名编辑框中用户没有写文件后缀(只写了文件名但无后缀)则会默认添加的后缀,比如"txt",无需加点(即".txt"),最后会将添加过后缀的文件名保存在对话框的数据结构中;

         iv. lpszFileName:即文件名编辑框中初始的默认文件名,如果为NULL则为空;

         v. dwFlags:为组合位掩码,决定了对话框具体行为和属性;

         vi. lpszFilter:即过滤器字符串,它将决定文件类型列表中的过滤器,它具有特定的书写格式,主要是以字符串对的形式出现,一个字符串对是这样定义的,格式为"显示文本|*.过滤后缀",比如"Text files(*.txt)|*.txt",前面的"Text files(*.txt)"字符串将出现在过滤器列表项的文本中显示给用户,在实际程序中不起到作用,后面的字符串"*.txt"将决定过滤器的类型,该字符串会导致文件列表中只显示后缀为.txt的文件,而*只是一种通配符,代表任何字符串,即前一个字符串是纯文本,后一个字符串包含特殊意义和功能的字符;

!!因此前一个字符串叫做文本字符串,后一个字符串叫做过滤字符串;

!!其次,文件类型中可能会包含多个过滤器,比如word的Open对话框中可能就包含.doc、.docx等多个过滤器,那前面讲过一个过滤器用一个字符串对表示,那么多个过滤器就要用多个字符串对来表示,那各个对之间还是使用|作为分隔符,并且最后一个字符串对结尾要用||作为结束符,例如:

"Text files(*.txt)|*.txt|Document files(*.doc)|*.doc|Data files(*.dat)|*.dat||"

!这里就定义了三个过滤器,分别是.txt、.doc和.dat三种过滤器,一定要注意最后一个字符串对的结尾要用双||结束!

    4) 在用构造函数创建完对象之后可以直接使用对象的DoModal()来显示对话框了,一般公用对话框都是模态的,非模态的公用对话框通常比较少见;

    5) 当对话框关闭后对象中成功获取了用户输入的文件名,此时可以使用CFileDialog的相关函数来获取文件名有关的信息:

         i. CString CFileDialog::GetPathName() const; // 获取文件完整的绝对路径名

         ii. CString CFileDialog::GetFileName() const; // 获取文件名,不包含路径,但是包含后缀

         iii. CString CFileDialog::GetFileTitle() const; // 获取文件的标题,即不包含路径不包含后缀的文件名;

         vi. 例如:

if (dlg.DoModal() == IDOK) {
    strFileName = dlg.GetFileName();
...


3. CFileDialog的属性:

    1) 其属性主要是由构造函数的dwFlags决定的,所以我们来看一下有哪些常用的重要的属性;

    2) 这些标记都以OFN_作为前缀,即Open File Name的缩写,即该对话框是一种“打开”类型的对话框,而其本质的含义在CFileDialog的底层实现,CFileDialog的所有部件、属性等都定义在一个OPENFILENAME结构成员当中,该结构成员的名字是m_ofn,其类型就是OPENFILENAME结构体,而构造函数的dwFlags最终会复制到m_ofn.Flags域内;

    3) 常用的标记:

首先看一下两个默认的标记:

OFN_HIDEREADONLY:隐藏“只读”复选框

OFN_OVERWRITEPROMPT:这个很重要,即“重名提示”,有时候保存文件时可能取的文件名和当前路径下某个文件的文件名相同,如果没有该标记则保存时将会直接覆盖同名文件,但是有了该标记再发生重名的情况,则会在按下保存按钮时弹出警告框提示存在重名文件,并询问是否覆盖,这就不会导致不必要的数据损失;

错误检查相关的标记:

OFN_PATHMUSTEXIST:用户输入的文件路径必须存在,否则会弹出消息框警告;

OFN_FILEMUSTEXIST:用户输入的文件必须存在否则会弹出消息框警告,该标记中包含了OFN_PATHMUSTEXIST

    4) 多选文件列表框:如果要对话框中的文件列表框可以多选,则必须要在flags里添加OFN_ALLOWMULTISELECT标记

         i. 用户可以在多选列表框中选中多个文件并按OK退出对话框,退出后选中的多个文件的文件名会保存在m_ofn.lpstrFile域指示的缓冲区中;

         ii. 想要逐个读取选中文件的文件名,则可以使用CFileDialog的GetStartPosition和GetNextPathName遍历所有的文件名;


4. 更深入地修改CFileDialog的属性:

    1) 因为有些属性不能在构造函数中指定(构造函数只是为了方便给出了一些常用的属性让用户设置),因此只能到m_ofn中修改;

    2) 像有些属性,像对话框标题、初始选中的文件过滤器等只能在m_ofn中修改;

    3) 修改的时机就是在构造函数构造完之后,在DoModal调用之前动手;

    4) 示例:将默认对话框标题“Open”改成“Select File(s)”,还有就是将关闭时选中的文件过滤器记忆下来,下次打开对话框时默认选中该过滤器

CFileDialog dlg(...);

dlg.m_ofn.lpstrTitle = _T("Select Files(s)"); // 修改标题用lpstrTitle域
if (dlg.DoModal() == IDOK) {
	filterIndex = dlg.m_ofn.nFilterIndex; // 将选中的过滤器的索引(nFilterIndex域内)回写到程序的数据域中
	...
}



你可能感兴趣的:(mfc,CFileDialog,公用对话框)