您的位置:首页 > 其它

WinX教程之我的实战(八)

2007-03-27 15:08 232 查看
现代操作系统都有文件系统的概念,所以有时候程序需要用户自己指定文件。在命令行下用户可以将自己指定的文件以参数形式传递,在图形界面下用户可以采用交互选择方式。在Windows下,我们把它叫做打开文件对话框(Open File Dialog),是通用对话框的一种(通用对话框还包括了颜色选择对话框、页面设置对话框、打印对话框等等)。今天我们来实战WinX里对打开文件对话框和保存文件对话框的封装,我们暂且把他们二者统称为文件对话框。WinX共提供了两种文件对话框,包括单文件对话框和多文件对话框,让我们看看WinX的操作和API方式、MFC方式有什么不同。

我们实战的例子程序就是step008-openfiles,该例程包含两个工程:




API方式


API实现打开文件对话框主要通过一个结构(OPENFILENAME)和一个API(GetOpenFileName)实现,此外还有一些辅助函数。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; //传递给hook函数的自定义数据




LPOFNHOOKPROC lpfnHook; //hook函数




LPCTSTR lpTemplateName; //对话框模板名




} OPENFILENAME, *LPOPENFILENAME;





详细介绍请参阅MSDN。

API方式下,如果要显示打开文件对话框,就需要调用API函数GetOpenFileName,他的参数就是上面这个结构的指针;如果需要显示保存文件对话框,就需要调用API函数GetSaveFileName。二者原型如下:





BOOL GetOpenFileName( LPOPENFILENAME lpofn);




BOOL GetSaveFileName( LPOPENFILENAME lpofn);



用户关心的返回值也都通过参数传回,毕竟用户需要的还是通过显示对话框得到一个全路径和文件名。

不过OPENFILENAME结构的一堆成员都需要用户指定,对于只是一个简单的打开或保存文件对话框来说,也确实麻烦了一些。


MFC方式


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方式


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只对通用对话框中的文件对话框进行了封装。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: