BOOL GetOpenFileName( LPOPENFILENAME lpofn);

BOOL GetSaveFileName( LPOPENFILENAME lpofn);

用户关心的返回值也都通过参数传回,毕竟用户需要的还是通过显示对话框得到一个全路径和文件名。
不过OPENFILENAME结构的一堆成员都需要用户指定,对于只是一个简单的打开或保存文件对话框来说,也确实麻烦了一些。
MFC对于打开和保存文件对话框进行了封装,都包括在CFileDialog里面。MFC方式显示文件对话框,必须先构建CFileDialog对象,然后调用DoModal方法来显示对话框窗口。我们看看CFileDialog构造函数和DoModal函数原型:
CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );

virtual int DoModal( );

可见MFC将指定给OPENFILENAME结构的参数都放在了CFileDialog的构造函数中,DoModal没有参数。
通过查看MFC源代码,发现OPENFILENAME是作为CFileDialog的公共成员变量实现的。MFC还提供了虚拟函数,通过重载虚拟函数可以改变CFileDialg的行为。
MFC的封装貌似简化了操作,如将打开文件对话框和保存文件对话框封装在一个类里面,似乎达到了界面一致。但MFC方式最大的缺点是并没有把用户和底层完全隔离开来,用户还需要了解OPENFILENAME结构的成员的含义和用法。一般来说,对于文件对话框,包括多文件对话框,无非是用户希望这种GUI交互方式获取用户的输入,获得用户选择的或者要保存的文件名和路径等。一些不常用的不应该成为用户掌握基本用法的障碍。
WinX的文件对话框定义在CommonDialogs.h文件中。WinX是将单文件对话框和多文件对话框分别定义的。我们先来看看其对单文件的定义:
enum FileDialogType


...{

fdtSaveFileDialog = 0,

fdtOpenFileDialog = 1,

};

template <INT nFileDlgType>

class FileDialogT : public OPENFILENAME


...{

// ...

};

typedef FileDialogT<fdtOpenFileDialog> FileDialog;

typedef FileDialogT<fdtOpenFileDialog> OpenFileDialog;

typedef FileDialogT<fdtSaveFileDialog> SaveFileDialog;


枚举界定了文件对话框类型(打开或保存),最终表现为不同的类,OpenFileDialog和SaveFileDialog。最有意思的是(个人感觉),WinX不像MFC那样将OPENFILENAME结构作为成员变量封装,而且只是派生自这个系统结构。其实二者对象在二进制结构上没有区别,但是类里面的具体写法WinX方式就简单了,不像MFC那样还要ofn.xxx的方式来引用,WinX直接引用OPENFILENAME成员名就可以了。
当然,上面这个对最终用户基本没什么作用。用户关心的是使用是不是简单。假设你需要一个单文件打开文件对话框,就像本实战分析的教程实例中一样,只需要以下代码就可以:
winx::OpenFileDialog dlg(_T("Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0"));

if (IDOK != dlg.DoModal())
return -1;

在winx::OpenFileDialog类的构造函数中指定文件过滤器(我想一般个人都有不同的过滤器),其他参数都按照常用的默认值,最后DoModal就可以了。
我们看看winx::OpenFileDialog类构造函数和DoModal函数的原型:
FileDialogT(

IN LPCTSTR szFilter = NULL,

IN LPCTSTR szDefExt = NULL,

IN LPCTSTR szDlgTitle = NULL,

IN LPCTSTR szInitFileName = NULL,

IN UINT nInitFilterIndex = 1,

IN LPCTSTR szInitialDir = NULL);

int winx_call DoModal(

HWND hWndParent = NULL, INT dlgType = nFileDlgType, HINSTANCE hInst =GetThisModule());

初看起来和MFC相比,只是有些参数顺序和所在函数有变化而已,深层次上来讲,WinX将抽象和具体化分的更清了。构造函数里的参数都是抽象层次上的,他们都不依赖于文件对话框的类型(打开或保存)、父窗口、资源句柄,而这些具体层次上的参数都移到了DoModal里面,在对话框显示出来的前一刻指定。也就是说,你可以构造一个OpenFileDialog对象,然后将它以不同的形式显示出来,如改变父窗口,改变类型,改变资源句柄。
最后又将单一FileDialog模板定义进行分解成了三个类,这样设计的指导思想又是什么?我认为是这样,如果用户一开始对自己要使用什么对话框是清楚的(到底是打开文件对话框还是保存文件对话框),就可以直接选择自己需要的类,其他参数就可以全部采用默认的,使用简单。用户用的中间过程想改变一下对话框行为,还有机会进行修改,使用灵活。这个小问题,WinX为用户还是想得很多。
除此外还有对多文件对话框的封装,基本思想一致,有兴趣的朋友可以看看commondialogs.h的源码。
另人遗憾的是,WinX只对通用对话框中的文件对话框进行了封装。