WinX教程之我的实战(八)

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


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




  • API方式

API实现打开文件对话框主要通过一个结构(OPENFILENAME)和一个APIGetOpenFileName)实现,此外还有一些辅助函数。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; 


枚举界定了文件对话框类型(打开或保存),最终表现为不同的类,OpenFileDialogSaveFileDialog。最有意思的是(个人感觉),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只对通用对话框中的文件对话框进行了封装。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值