在应用程序中,我们很经常要实现的功能,是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就可以了。

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

代码我随后上传。

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

跟我一起玩Win32开发(19):浏览和打开文件的更多相关文章

  1. 跟我一起玩Win32开发(转自CSDN-东邪独孤)

    跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...

  2. 跟我一起玩Win32开发(17):启动和结束进程

    这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...

  3. 跟我一起玩Win32开发(18):使用对话框的两个技巧

    相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...

  4. 跟我一起玩Win32开发(20):浏览文件夹

    最近忙于一些相当无聊的事情,还没忙完,不过,博客还是要写的,不然我头顶上会多了几块砖头. 在上一篇博文中,我们浏览了文件,今天我们也浏览一下目录,如何? 浏览目录我们同样有两个规矩,用托管类库的我就不 ...

  5. 跟我一起玩Win32开发(12):使用控件——单选按钮

    今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少. 哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问 ...

  6. 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作

    我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...

  7. 跟我一起玩Win32开发(4):创建菜单

    也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...

  8. 跟我一起玩Win32开发(2):完整的开发流程

    上一篇中我给各位说了一般人认为C++中较为难的东西——指针.其实对于C++,难点当然不局限在指针这玩意儿上,还有一些有趣的概念,如模板类.虚基类.纯虚函数等,这些都是概念性的东西,几乎每一本C++书上 ...

  9. 跟我一起玩Win32开发(25):监视剪贴板

    自从郭大侠和蓉儿离开桃花岛后,最近岛比较寂静,有一种“门前冷落鞍马稀”的感觉.于是,老邪就拿出<九阴真经>认真阅读,同时用迅雷下载经典大剧<汉武大帝>晚上睡觉前看上几集,老邪一 ...

随机推荐

  1. javascript return 跟 break区别

    break是跳出当前循环,return是中止函数的执行

  2. eclipse无法启动问题记录

    几天没开eclipse,居然报错“can not unload……”,搜索答案发现没有准确的,遵从了一个多人顶赞的办法重下eclipse,把配置文件拷贝一份,结果悲剧了,虽然能够打开了,但我之前配置的 ...

  3. LeetCode(38)题解: Count and Say

    https://leetcode.com/problems/count-and-say/ 题目: The count-and-say sequence is the sequence of integ ...

  4. JasperReport 中文问题解决

    1 运行环境    1.1 JasperReport 3.5    JasperReports 是iReport的核心内容.它是一个强有力的开源报表产生工具,可以将内容输出到屏幕上.打印机或生成PDF ...

  5. BZOJ3260: 跳

    BZOJ3260: 跳 Description 邪教喜欢在各种各样空间内跳.现在,邪教来到了一个二维平面. 在这个平面内,如果邪教当前跳到了(x,y),那么他下一步可以选择跳到以下4个点: (x-1, ...

  6. springboot对传参的拦截统一处理

    在学习某网<java秒杀系统方案优化>的课程中,学到了一种springboot对传参的拦截统一处理的方式,特记录一下. 如后台方法一般需要根据token从Session中获取User对象, ...

  7. Mac开发必备工具(一)—— Homebrew

    Homebrew 简介 macOS 缺失的软件包管理器.使用 Homebrew 安装 Apple 没有预装但 你需要的东西.官网有中文说明. 安装与配置 Homebrew 的安装非常简单,将下面这条命 ...

  8. (linux)块设备驱动程序

      1.4.1  Linux块设备驱动程序原理(1) 顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例如 ...

  9. Android ADB实现解析【转】

    本文转载自:http://blog.csdn.net/u010223349/article/details/41120255   ADB是Android系统提供的调试工具,整个ADB工具由三部分组成: ...

  10. POJ3436 ACM Computer Factory —— 最大流

    题目链接:https://vjudge.net/problem/POJ-3436 ACM Computer Factory Time Limit: 1000MS   Memory Limit: 655 ...