引言:没想到2022年还有很多工业软件公司依然使用MFC,微软也一直在更新MFC的库,这次使用MFC封装的CFileDialog类,写一个获得选定文件路径,名称,扩展名的程序。
个人技术博客(文章整理+源码): https://zobolblog.github.io/LearnWinAPI/
最终效果:
1.CFileDialog的使用
CFileDialog是MFC对windows api的FileDialog的简单封装,增加了一些接口,他的构造函数只有一个:
explicit CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL, DWORD dwSize = 0, BOOL bVistaStyle = TRUE);
第1个参数bOpenFileDialog为TRUE则表示打开文件对话框,为FALSE则表示保存文件对话框。它也是我们必须填写的,其他的都有默认值。
第2个参数lpszFileName指定默认的文件扩展名。就是txt,exe这类。
第3个参数lpszFileName指定默认的文件名。一般是保存文件框用的。
第4个参数dwFlags 指明一些特定风格,比如多选对话框,可读文件,隐藏文件不显示。
第5个参数lpszFilter是过滤器意思,写法国内的博客很乱,但其实微软官方给了一种很易读的写法。
static TCHAR BASED_CODE szFilter[] = _T("Chart Files (*.xlc)|*.xlc|")
_T("Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|")
_T("*.xlc; *.xls|All Files (*.*)|*.*||");
第6个参数pParentWnd指定父窗口的指针。
第7个参数dwSize是指OPENFILENAME结构的大小,这此值取决于操作系统版本。MFC使用此参数确定要创建的适当类型的对话框。默认大小0表示MFC代码将根据运行程序的操作系统版本确定要使用的正确对话框大小。
第8个参数bVistaStyle,默认都是true。它实际上是因为微软在vs2008后,设计了新的对话框风格。所以就用一个bool类型,表示新旧风格。(微软就不考虑用宏或者枚举,万一以后又出一个第3风格版本呢。。)
2.DoModal()函数
就像QT里面的show函数一样,虽然CFileDialog dlg在内存中创造了一个对话框对象,但是显示出来给人看,还需要专门的函数DoModal()。
“Call this function to display the Windows common file dialog box and allow the user to browse files and directories and enter a filename.”调用此函数可显示Windows公用文件对话框,允许用户浏览文件和目录并输入文件名。
3.DoModal()函数的返回值IDOK和IDCANCEL
在窗口的生命周期结束后,domodal还会返回一个值,告诉我们一些情况。但是MFC的设计在这里非常的烦人,单纯的IDCANCEL只能告诉我们出现了问题。至于是什么问题还需要调用一个CommDlgExtendedError函数才可以知道。(至于这里为什么不设计成返回一个结构体,直接包含错误信息,估计是90年代开发MFC的时候,计算机性能不够?)
源码:
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,_T("All FILE|*.*|"),NULL,NULL,1); if (dlg.DoModal() != IDOK) { CommDlgExtendedError(); } else { CString filePathName = dlg.GetPathName(); CString fileName = dlg.GetFileName(); // return only filename CString fileExt = dlg.GetFileExt(); // return only ext CString fileTitle = dlg.GetFileTitle(); // return file title }
效果: