7.4 通用对话框

7.4.1 “打开”文件和“保存”文件对话框

请先看下面一段用于显示“打开”文件对话框的代码(07CommDlg工程):

char szFileName[MAX_PATH] = ""; 
OPENFILENAME file = { 0 }; 
file.lStructSize = sizeof(file); // 设置对话框的属性 
file.lpstrFile = szFileName; 
file.nMaxFile = MAX_PATH; 
file.lpstrFilter = "Text Files(*.txt)\0*.txt\0All Files\0*.*\0\0"; 
file.nFilterIndex = 1;  // 弹出打开文件的对话框 
if(::GetOpenFileName(&file)) 
{ 
   ::MessageBox(NULL, szFileName, "07CommDlg", MB_OK);
} 

程序运行效果如图7.9所示。选择一个文件后,系统将弹出一个对话框(MessageBox)显示所选择文件的名称(包含路径)。
在这里插入图片描述
显示“打开”文件对话框的函数是GetOpenFileName,显示“保存”文件对话框的函数是GetSaveFileName。这两个对话框可以让用户选择驱动器、目录以及文件名,但它们并不对文件进行任何操作。函数用法如下。

BOOL GetOpenFileName ( LPOPENFILENAME lpofn); 
BOOL GetSaveFileName ( LPOPENFILENAME lpofn);

lpofn是一个指向OPENFILENAME结构的指针,程序在调用函数前需要在结构中填写初始化数据。两个函数使用的结构是一样的,只是使用的初始化数据有所不同而已。OPENFILENAME结构的定义如下。

typedef struct tagOFN 
{  
     DWORD lStructSize; // 结构的长度,用户填写  
     HWND hwndOwner; // 所属窗口  
     HINSTANCE hInstance; // 所在程序的实例句柄  
     LPCTSTR lpstrFilter; // 文件筛选字符串  
     LPTSTR lpstrCustomFilter;  
     DWORD nMaxCustFilter;  
     DWORD nFilterIndex;  
     LPTSTR lpstrFile; // 全路径的文件名缓冲区  
     DWORD nMaxFile; // 全文件名缓冲区长度  
     LPTSTR lpstrFileTitle; // 不包含路径的文件名缓冲区  
     DWORD nMaxFileTitle; // 文件名缓冲区长度  
     LPCTSTR lpstrInitialDir; // 初始目录  
     LPCTSTR lpstrTitle; // 对话框标题  
     DWORD Flags; // 标志  
     WORD nFileOffset; // 文件名在字符串中的起始位置  
     WORD nFileExtension; // 扩展名在字符串中的起始位置  
     LPCTSTR lpstrDefExt; // 默认扩展名  
     LPARAM lCustData;  
     LPOFNHOOKPROC lpfnHook;  
     LPCTSTR lpTemplateName; 
} OPENFILENAME, *LPOPENFILENAME;

下面是结构中一些重要字段的含义。
(1)lpstrFilter,指定文件名筛选字符串,该字段决定了对话框中“文件类型”下拉式列表框中的内容,字符串可以由多组内容组成,每组包含一个说明字符串和一个筛选字符串,字符串的最后用两个0结束。例如,加上下面的代码后显示结果如图7.10所示。

file.lpstrFilter = "Text Files(*.txt)\0*.txt\0All Files\0*.*\0\0"; 
file.nFilterIndex = 1; // 默认选择第一个 

在这里插入图片描述
(2)lpstrInitialDir,对话框的初始化目录,这个字段可以是NULL。
(3)lpstrDefExt,指定默认扩展名,如果用户输入了一个没有扩展名的文件名,那么函数会自动加上这个默认扩展名。
(4)Flags,该字段决定了对话框的不同行为。它可以是一些标志的组合。下面是几个比较重要的标志:

OFN_ALLOWMULTISELECT     允许同时选择多个文件
OFN_CREATEPROMPT         如果用户输入了一个不存在的文件名,对话框向用户询问“是否建 立新文件”
OFN_OVERWRITEPROMPT      在“保存”文件对话框中使用的时候,当用户选择的文件存在时, 对话框会提问“是否覆盖文件”。

如果用户单击了对话框中的“确定”按钮,函数返回TRUE;如果单击了“取消”按钮,函数返回FALSE。

7.4.2 浏览目录对话框

显示浏览目录对话框的功能由SHBrowseForFolder函数实现,函数的用法如下。

LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO lpbi);

参数lpbi指向包含对话框初始数据的BROWSEINFO结构。

typedef struct _browseinfo 
{  
     HWND hwndOwner; // 对话框的父窗口  
     LPCITEMIDLIST pidlRoot; // 用来表示起始目录的ITEMIDLIST结构  
     LPTSTR pszDisplayName; // 用来接受用户选择目录的缓冲区  
     LPCTSTR lpszTitle; // 对话框中用户定义的文字  
     UINT ulFlags; // 标志  
     BFFCALLBACK lpfn; // 回调函数地址  
     LPARAM lParam; // 传给回调函数的参数  
     int iImage; // 用来接受选中目录的图像 
} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO; 

ulFlags字段用来定义对话框的风格,可以取值如下:

BIF_BROWSEINCLUDEFILES    可同时显示目录中的文件 
BIF_RETURNONLYFSDIRS      只返回文件系统中的目录 
BIF_EDITBOX               显示一个编辑框供用户输入目录 
BIF_EDITBOX               显示一个编辑框供用户输入目录 

当该函数返回时,如果用户单击的是“取消”按钮,那么函数的返回值是0,否则,函数返回指向ITEMIDLIST结构的指针,对于这个结构可以不必去深究,因为使用SHGetPathFromIDList函数可以很方便地将它转化成目录字符串。

BOOL SHGetPathFromIDList(LPCITEMIDLIST pidl, LPTSTR pszPath); 

函数执行后,字符串格式的用户选择的目录名将会返回到pszPath所指的缓冲区中。

为了今后使用方便,下面简单封装了一个CDirDialog类用于管理浏览目录对话框。这个类定义和实现代码都在DirDialog.h文件中。

// DirDialog.h文件

#ifndef __DIRDIALOG_H_
#define __DIRDIALOG_H_

#include <shlobj.h>

class CDirDialog
{
public:
	CDirDialog();
	// 显示对话框
	BOOL DoBrowse(HWND hWndParent, LPCTSTR pszTitle = NULL);
	// 取得用户选择的目录名称
	LPCTSTR GetPath() { return m_szPath; }

protected:
	BROWSEINFOA m_bi; 

	// 用来接受用户选择目录的缓冲区
	char m_szDisplay[MAX_PATH];
	char m_szPath[MAX_PATH];
};

CDirDialog::CDirDialog()
{
	memset(&m_bi, 0, sizeof(m_bi));

	m_bi.hwndOwner = NULL;	 
	m_bi.pidlRoot = NULL;		 	
	m_bi.pszDisplayName = m_szDisplay; 
	m_bi.lpszTitle = NULL;		 	
	m_bi.ulFlags = BIF_RETURNONLYFSDIRS;
	
	m_szPath[0] = '\0';
}

BOOL CDirDialog::DoBrowse(HWND hWndParent, LPCTSTR pszTitle)
{
	if(pszTitle == NULL)
		m_bi.lpszTitle = "选择目标文件夹";
	else
		m_bi.lpszTitle = pszTitle;

	m_bi.hwndOwner = hWndParent;
	LPITEMIDLIST pItem = ::SHBrowseForFolder(&m_bi);
	if(pItem != 0)
	{
		::SHGetPathFromIDList(pItem, m_szPath);
		return TRUE;
	}

	return FALSE;
}

#endif //__DIRDIALOG_H_

类的用法相当简单,例如下面的代码将打开一个浏览目录对话框。

CDirDialog dir; 
if(dir.DoBrowse(hDlg)) // hDlg是父窗口句柄 
{ 
    ::MessageBox(hDlg, dir.GetPath(), "07CommDlg", MB_OK);
} 

代码执行之后的效果如图7.11所示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值