在应用程序中,我们很经常要实现的功能,是Open文件或保存文件对话框,让用户来选择一个或N个文件。本文我将介绍两种思路,第一种方法较为复杂,第二种方法较为简单。

方法一:老规矩

这是一种传统方法,使用GetOpenFileName或者GetSaveFileName函数,看名字就知道,前者用来打开文件,后者是保存文件,这两个函数的用法是一样的,因此,我只演示其中一个。

无论你使用哪个函数,都要涉及一个结构体——OPENFILENAME。关于它的成员,我就不一一来说了,挑几个有用的扯一扯。

lStructSize:结构的大小,弄个sizeof就行了。

lpstrFilter:设置过滤器。注意啊,这个过滤器字符串和.NET中的写法不同,.NET的写法是从VB6继承过来,可以写成“垃圾文件 | *.rbs | 老鼠文件 | *.mos”,我们这里不是用“|”来分隔的,而是用“\0”分隔,而结尾是两个NULL,即两个“\0”。

nFilterIndex:过滤器索引,设置了N个滤过的后缀,设置默认选择哪个,第一个为1,第二个为2,第三个为3,依此类推,是从1开始的,不是0。

lpstrFile:文件名,包含完整路径,当对话框关闭后,我们就是从这个成员把用户选择的文件名取出。

nMaxFile:文件名的长度,一定要足够大,不然就装不下了,对路径长度,系统是有限定的,用MAX_PATH宏就可以了,WCHAR myFilename[MAX_PATH]。

Flags:标志位。主要决定对话框应具备哪些特征和行为,如是否检查目标文件已存在。

哦,这个可能看了没感觉,看看例子代码,一目了然。

  1. OPENFILENAME opfn;
  2. WCHAR strFilename[MAX_PATH];//存放文件名
  3. //初始化
  4. ZeroMemory(&opfn, sizeof(OPENFILENAME));
  5. opfn.lStructSize = sizeof(OPENFILENAME);//结构体大小
  6. //设置过滤
  7. opfn.lpstrFilter = L"所有文件\0*.*\0文本文件\0*.txt\0MP3文件\0*.mp3\0";
  8. //默认过滤器索引设为1
  9. opfn.nFilterIndex = 1;
  10. //文件名的字段必须先把第一个字符设为 \0
  11. opfn.lpstrFile = strFilename;
  12. opfn.lpstrFile[0] = '\0';
  13. opfn.nMaxFile = sizeof(strFilename);
  14. //设置标志位,检查目录或文件是否存在
  15. opfn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  16. //opfn.lpstrInitialDir = NULL;
  17. // 显示对话框让用户选择文件
  18. if(GetOpenFileName(&opfn))
  19. {
  20. //在文本框中显示文件路径
  21. HWND hEdt = GetDlgItem(hDlg, IDC_EDTFILENAME);
  22. SendMessage(hEdt, WM_SETTEXT, NULL, (LPARAM)strFilename);
  23. }

ZeroMemory函数前面说过了,你就当作它用来初始化结构就行了。

你可能会疑问,不是说lpstrFilter的字符串是两个NULL结尾的吗,为什么代码中只有一个?因为你输入的字符串会在后面自动加了个‘\0’,所以我们加一个就OK,后面自动加上一个,就两个了。

下图是执行结果:

GetSaveFileName的用法也一样,有兴趣的朋友可以回家自己玩一下。

方法二:新规矩

这个新规矩是谁定的?哈哈,我定的。

都说知识是可以综合运用的,所以,下面的方法是灵活运用知识了。为啥?记得吧,.NET类库其实也为我们封装了,大家玩过Windows Forms开发肯定知道,在System.Windows.Forms下面的。是啊,既然有了现成的,我们干吗不拿来用呢。

首先,打开项目属性,按下图的方法,让项目支持 /clr ,然后点击“应用”。

引用需要用到的程序集。

在代码文件中引入命名空间。

  1. using namespace System;
  2. using namespace System::Windows::Forms;

然后实现打开文件的功能。

  1. if(LOWORD(wParam) == IDC_BTNOPWTCLR)
  2. {
  3. OpenFileDialog ^dlg = gcnew OpenFileDialog;
  4. dlg ->Filter = L"所有文件|*.*|图片文件|*.jpg";
  5. dlg->FilterIndex = 1;
  6. dlg->CheckFileExists = true;
  7. if (dlg ->ShowDialog() == DialogResult::OK)
  8. {
  9. //取得文件名
  10. }
  11. }

但是,当获取文件名的时候,遇到了一个严重问题了,在CLR中,我们取到的文件名是System::String ^类型的,可是我们这里的Win32程序需要wchar_t类型的字符串,这怎么办?能进行转换吗?

微软早就想到这个问题,所以,它给我们写了一个vcclr.h头文件,里面有一个PtrToStringChars函数,使用它就可以将托管的字符串转为标准字符串了。

  1. if (dlg ->ShowDialog() == DialogResult::OK)
  2. {
  3. //取得文件名
  4. pin_ptr<const WCHAR> strFileName = PtrToStringChars(dlg->FileName);
  5. HWND hEdt = GetDlgItem(hDlg, IDC_EDTFILENAME);
  6. SendMessage(hEdt, WM_SETTEXT, NULL, (LPARAM)strFileName);
  7. }

但是,问题仍未解决,运行之后你会很惊喜地收到一个异常信息。

运气真的太好了,那么这个怎么解决呢?再次打开项目属性窗口,找到“链接器”-“高级”,把CLR线程模型改为STA就可以了。

现在运行应用程序,估计没有问题了。

代码我随后上传。

好了,好了,现在大功告成了。拜拜。

最新文章

  1. @Autowired 与@Resource的区别
  2. python %s深入解析
  3. Oracle知识分类之异常
  4. 如何理解JS回调函数
  5. 颜色渐变的JS代码
  6. innerHeight,clientHeight,offsetHeight,scrollWidth等的区别和用法
  7. Linux 输出重定向&gt;和&gt;&gt;的区别
  8. mysql5.5手册读书日记(3)
  9. MVC架构杂谈
  10. Microsoft Windows Server 2008 R2 IIS7.5安装指南
  11. IDE 常用快捷键记录
  12. [置顶] 教你如何搭建RobotFramework环境
  13. php遍历目录下文件,并读取内容
  14. Flink架构、原理与部署测试
  15. Mybatis了解(配置)
  16. Centos7 Firewall
  17. 刘志梅2017710101152.《面向对象程序设计(java)》第十三周学习总结
  18. MySQL课堂小测
  19. python全栈开发 * 33 知识点汇总 * 180718
  20. answerOpenCV轮廓类问题解析

热门文章

  1. Android WIFI模块分析
  2. 程序编写安全代码——sendto和recvfrom的大坑
  3. Eclipse中设置编码的方法
  4. Understanding When to use RabbitMQ or Apache Kafka Kafka RabbitMQ 性能对比
  5. group by where having 联合使用
  6. 中国vs美国制造业公司营业额大排名,看看哪些属于美国制造业的优势产业(中美旗鼓相当,而且还有本土制造的优势)
  7. kbmMemTable关于内存表的使用,以及各种三层框架的评价
  8. 分享一个好用的函数吧,将js中的对象转成url参数
  9. HDU4280 Island Transport —— 最大流 ISAP算法
  10. YTU 2424: C语言习题 字符串比较