跟我一起玩Win32开发(19):浏览和打开文件
在应用程序中,我们很经常要实现的功能,是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:标志位。主要决定对话框应具备哪些特征和行为,如是否检查目标文件已存在。
哦,这个可能看了没感觉,看看例子代码,一目了然。
- OPENFILENAME opfn;
- WCHAR strFilename[MAX_PATH];//存放文件名
- //初始化
- ZeroMemory(&opfn, sizeof(OPENFILENAME));
- opfn.lStructSize = sizeof(OPENFILENAME);//结构体大小
- //设置过滤
- opfn.lpstrFilter = L"所有文件\0*.*\0文本文件\0*.txt\0MP3文件\0*.mp3\0";
- //默认过滤器索引设为1
- opfn.nFilterIndex = 1;
- //文件名的字段必须先把第一个字符设为 \0
- opfn.lpstrFile = strFilename;
- opfn.lpstrFile[0] = '\0';
- opfn.nMaxFile = sizeof(strFilename);
- //设置标志位,检查目录或文件是否存在
- opfn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
- //opfn.lpstrInitialDir = NULL;
- // 显示对话框让用户选择文件
- if(GetOpenFileName(&opfn))
- {
- //在文本框中显示文件路径
- HWND hEdt = GetDlgItem(hDlg, IDC_EDTFILENAME);
- SendMessage(hEdt, WM_SETTEXT, NULL, (LPARAM)strFilename);
- }
ZeroMemory函数前面说过了,你就当作它用来初始化结构就行了。
你可能会疑问,不是说lpstrFilter的字符串是两个NULL结尾的吗,为什么代码中只有一个?因为你输入的字符串会在后面自动加了个‘\0’,所以我们加一个就OK,后面自动加上一个,就两个了。
下图是执行结果:
GetSaveFileName的用法也一样,有兴趣的朋友可以回家自己玩一下。
方法二:新规矩
这个新规矩是谁定的?哈哈,我定的。
都说知识是可以综合运用的,所以,下面的方法是灵活运用知识了。为啥?记得吧,.NET类库其实也为我们封装了,大家玩过Windows Forms开发肯定知道,在System.Windows.Forms下面的。是啊,既然有了现成的,我们干吗不拿来用呢。
首先,打开项目属性,按下图的方法,让项目支持 /clr ,然后点击“应用”。
引用需要用到的程序集。
在代码文件中引入命名空间。
- using namespace System;
- using namespace System::Windows::Forms;
然后实现打开文件的功能。
- if(LOWORD(wParam) == IDC_BTNOPWTCLR)
- {
- OpenFileDialog ^dlg = gcnew OpenFileDialog;
- dlg ->Filter = L"所有文件|*.*|图片文件|*.jpg";
- dlg->FilterIndex = 1;
- dlg->CheckFileExists = true;
- if (dlg ->ShowDialog() == DialogResult::OK)
- {
- //取得文件名
- }
- }
但是,当获取文件名的时候,遇到了一个严重问题了,在CLR中,我们取到的文件名是System::String ^类型的,可是我们这里的Win32程序需要wchar_t类型的字符串,这怎么办?能进行转换吗?
微软早就想到这个问题,所以,它给我们写了一个vcclr.h头文件,里面有一个PtrToStringChars函数,使用它就可以将托管的字符串转为标准字符串了。
- if (dlg ->ShowDialog() == DialogResult::OK)
- {
- //取得文件名
- pin_ptr<const WCHAR> strFileName = PtrToStringChars(dlg->FileName);
- HWND hEdt = GetDlgItem(hDlg, IDC_EDTFILENAME);
- SendMessage(hEdt, WM_SETTEXT, NULL, (LPARAM)strFileName);
- }
但是,问题仍未解决,运行之后你会很惊喜地收到一个异常信息。
运气真的太好了,那么这个怎么解决呢?再次打开项目属性窗口,找到“链接器”-“高级”,把CLR线程模型改为STA就可以了。
现在运行应用程序,估计没有问题了。
代码我随后上传。
好了,好了,现在大功告成了。拜拜。
跟我一起玩Win32开发(19):浏览和打开文件的更多相关文章
- 跟我一起玩Win32开发(转自CSDN-东邪独孤)
跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...
- 跟我一起玩Win32开发(17):启动和结束进程
这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...
- 跟我一起玩Win32开发(18):使用对话框的两个技巧
相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...
- 跟我一起玩Win32开发(20):浏览文件夹
最近忙于一些相当无聊的事情,还没忙完,不过,博客还是要写的,不然我头顶上会多了几块砖头. 在上一篇博文中,我们浏览了文件,今天我们也浏览一下目录,如何? 浏览目录我们同样有两个规矩,用托管类库的我就不 ...
- 跟我一起玩Win32开发(12):使用控件——单选按钮
今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少. 哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问 ...
- 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作
我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...
- 跟我一起玩Win32开发(4):创建菜单
也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...
- 跟我一起玩Win32开发(2):完整的开发流程
上一篇中我给各位说了一般人认为C++中较为难的东西——指针.其实对于C++,难点当然不局限在指针这玩意儿上,还有一些有趣的概念,如模板类.虚基类.纯虚函数等,这些都是概念性的东西,几乎每一本C++书上 ...
- 跟我一起玩Win32开发(25):监视剪贴板
自从郭大侠和蓉儿离开桃花岛后,最近岛比较寂静,有一种“门前冷落鞍马稀”的感觉.于是,老邪就拿出<九阴真经>认真阅读,同时用迅雷下载经典大剧<汉武大帝>晚上睡觉前看上几集,老邪一 ...
随机推荐
- layer弹层
获得 layer 文件包后,解压并将 layer 整个文件夹(不要拆分结构) 存放到你项目的任意目录,使用时,只需引入 layer.js 即可. 注意:引入layer.js前必须先引入jquery1. ...
- Spark 学习笔记:(三)Spark SQL
参考:https://spark.apache.org/docs/latest/sql-programming-guide.html#overview http://www.csdn.net/arti ...
- Java网络编程知识点(1)
怎样将一个String对象转换成InputStream对象? ByteArrayInputStream inputStream = new ByteArrayInputStream(str.getBy ...
- apt仓库以及apt-get分析
1 debian repository 参考:https://wiki.debian.org/DebianRepository 1.1 版本代号 sid,still in development,该版 ...
- .Net之路(十四)com组件、OLEDB导入EXCEL
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/chenfanglincfl/article/details/30546777 .NET com组件 ...
- 在无代码文件的aspx文件中添加类、函数和字段的方法
大家都知道,在开始WebForm程序时,一个WebForm由.cs代码文件与.aspx页面文件组成.在aspx文件中可以嵌入C#代码,但无法在aspx的嵌入C#代码中定义类,函数和字段等.这样,就限制 ...
- C/S与B/S架构 区别·与优点
C/S和B/S,是再普通不过的两种软件架构方式,都可以进行同样的业务处理,甚至也可以用相同的方式实现共同的逻辑.既然如此,为何还要区分彼此呢?那我们就来看看二者的区别和联系. 一.C/S 架构 1 ...
- mysql_proxy
mysql_proxy中间件实现:读写分离.负载均衡. mysql_proxy中间件实现:读写分离.负载均衡. 负载均衡:给多台数据库,看能不能均匀的分给不同的数据库. 客户端连的是proxy,此时的 ...
- spring的依赖注入(DI)、控制反转(IOC)和面向切面(AOP)
在spring的配置文件增加 <context:component-scan base-package="com.jmu.ccjoin.service"/> <c ...
- HDU2102 A计划 —— BFS
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 A计划 Time Limit: 3000/1000 MS (Java/Others) Me ...