请看右手,我这三个图片视频文件,其中1、2己保存了,但返回后,从文件夹找不到了怎么办里找不到,是咋回事?

跳转到 0 ? parseInt(this.value) : 1) + '.aspx';}else{window.location='showtopic.aspx?topicid=102&page=' + (parseInt(this.value) > 0 ? parseInt(this.value) : 1) ;}}"" size="4" maxlength="9"/>页查看:101941
showMenu(this.id);" id="newspecial" class="postbtn">
[办公应用]
电脑基础知识讲座(一)、(二)、(三)、(四)、(五)、(六)
电脑基础知识讲座(一)、(二)、(三)、(四)、(五)、(六)
相关链接:                    电脑基础知识讲座(第一讲:电脑入门)平常所说的电脑是个人计算机的形象叫法,是一种微型计算机,英文简称PC机。电脑的功能非常强大,可以说,只有人想不到的,没有电脑做不到的。这是因为人的大脑只有一个,而电脑是由无数个人的大脑共同研究出来了。一、电脑的构成电脑是由硬件和软件组成的。(一)硬件:电脑中看得见摸得着的都称为硬件,主要分为中央处理器、存储器和输入、输出设备。1、中央处理器CPUCPU即中央处理器,它是计算机的大脑,计算机的运算、控制都是由它来处理的。它的发展非常迅速,从最初的8088到奔腾486、586,现在已经发展到双核甚至四核,用迅驰技术装备的笔记本电脑,使用户脱离缆线的约束,真正做到在移动中进行工作、学习、休闲。全世界99%的CPU都是英特尔 (1.68 K) 17:26:48和AMD公司的产品,中国最近才制造出“龙芯一号”。2、存储器存储器是电脑的记忆细胞,用来存放程序和数据。存储器分为内存和外存。内存指CPU可以随时直接存取的存储器,一般容量很小,虽然容量小,但电脑的速度与它有很大关系。外存包括磁盘、磁带等。磁盘有硬盘、移动硬盘、光盘、软盘、U盘等。3、输入设备:键盘、鼠标是最常用的输入设备,扫描仪、话筒、摄像头也是输入设备。4、输出设备有显示器、音箱、打印机等随着科学技术的不断进步,很多新的设备集成了输入、输出和存储多种功能,如数码相机、DV就是既能存储拍摄的照片、视频,又能输入到电脑,也可以从电脑输出到相机、DV;耳麦是个特例,是耳机和麦克风合在一起,但又相互独立的设备,耳机是输出设备,麦克风是输入设备;还有什么MP3、MP4,都有几种功能。5、连接设备(这是我自编的,不一定准确)包括把信号传送给显示器的显卡;把信号传送给音箱的声卡;网卡也叫“网络适配器”,是计算机与网络电缆的接口;调制解调器通常称为猫(Modem),是将计算机的数字信号与电话线上传输的信号相互转换的装置;还有连接光盘的光驱以及各种连接线、接口(USB接口、耳麦插口)等。当然还有电源、风扇等。(二)软件计算机的所有功能都是通过软件来实现的,没有软件,买回的电脑是不能工作的。软件分为操作系统、硬件驱动和应用软件三大类。1、操作系统操作系统是电脑的核心软件。过去的电脑出厂时都是没有安装系统的裸机。现在迫于美国的压力(因为微软是美国企业),品牌机出厂时就安装了正版操作系统。举个形象的例子,电脑就象你开了家中药店,租了房子,置办了桌椅橱柜,请了店员,这个中药店就相当于买回了一台电脑,门面房和桌椅橱柜就是电脑的硬件,店员就相当于电脑的操作系统,没有店员,房里的东西都不能工作,只有店员才能将各种设备利用起来,所不同的是,这个店员还自带了一部分设备,这就是操作系统的组件(如记事本、计算器等)。橱柜相当于电脑的硬盘,其中的抽屉相当于文件夹,存放的药材相当于电脑中的文件。你去抓药,告诉店员要抓什么药,各抓多少,店员就象电脑的操作系统一样,根据你的指令去打开某个抽屉(文件夹),从中抓取某种药材(文件)。操作系统从最早的DOS系统到现在的Windows操作系统、苹果系统等。DOS系统是非常强大的操作系统,曾在很长一段时间统治操作系统行业,微软公司发明了Windows操作系统后,DOS系统现在只是电脑公司人员装机维护时才用到它。Windows操作系统霸占了全世界90%几的市场,一切硬件和软件制造商都要向比尔·盖茨看齐,也就是要能被Windows操作系统兼容,否则你就没有销路。Windows操作系统又叫视窗操作系统,分成Windows 98 、2000、XP,现在又出了Vista,Windows Vista是Windows操作系统的最新版本,因为Vista对硬件的要求太高,没有1G以上的内存不能安装,所以现在使用的操作系统绝大部分都是Windows XP。Windows XP除了原版外,已经被修改的盗版XP有无数种。2、硬件驱动程序电脑的所有硬件都要有一个程序来驱动它才能工作,也就是只有安装了驱动程序,这个硬件设备才能被操作系统调用。硬件驱动有两种,一种是已经在Windows操作系统中自带了的,另一种是没有经过微软公司认证的,这类硬件要另备驱动程序。出厂时所有的硬件都附有相应的驱动光盘,但为了防止驱动光盘丢失,造成硬件无法使用,正确的做法是用驱动精灵备份所有不是Windows自备的硬件驱动。3、应用软件应用软件有无数种,需要什么再安装什么软件。有文字处理软件、图形软件、视频音频软件和各种专业软件,如人事管理软件、财务软件、特困职工软件等等。以驱动精灵安装为例,介绍一下软件的安装、卸载和硬件驱动的备份.软件的安装(以驱动精灵为例)首先双击驱动精灵软件,出现下图,很多软件都捆绑有插件,要注意选择,这个软件会在桌面添加多特网站的链接。(71.94 K) 17:26:48接着一直点击下一步,选择安装路径,一般使用默认路径不要修改(57.45 K) 17:26:48完成安装并运行(或不运行)软件,有的软件还要求输入序列号、注册码甚至注册、激活,都是为了防止盗版,序列号、注册码有的是在安装过程中输入,有的是在第一次运行软件时输入。(68.53 K) 17:26:48硬件驱动的备份双击桌面驱动精灵图标运行或从开始菜单查找打开(59.71 K) 17:26:48它能自动检测你电脑中没有被Windows兼容的硬件驱动,勾选声卡、显卡、打印机,记住备份路径,防止备份后找不到。(56.50 K) 17:26:48点击开始备份,出现备份的进度条(54.50 K) 17:26:48备份完成后在备份路径D:\DriverBackup文件夹中有声卡、显卡、打印机的三个备份文件夹,以备将来使用。软件的卸载有的软件安装后觉得不好用,可以通过三种途径删除,正规叫法是卸载。大多数正规软件都带有卸载按纽,可以从开始菜单中的所有程序中点击卸载;二是从开始/控制面板,点击添加/删除程序,在添加或删除程序对话框中找到它,点击删除,很多软件删除后必须重启电脑才能完成卸载的全过程;(44.47 K) 17:26:48三是有的软件是所谓的流氓软件,只能安装不准删除或删除不尽,有的软件要到相应的网站上才能删除,这类软件只有借助一些强制删除的工具来删除。
风调雨顺 最后编辑于
二、电脑的操作(以下所说的都是指Windows XP操作系统)
因为操作系统都是电脑公司人员安装好的,初学人员不敢安装,所以就不讲系统安装了。1、电脑的启动与关机电脑在关机状态下打开电源开关,按下启动按纽,等待一会,就会出现Windows XP的蓝天白云桌面了;有时出现死机,操作没有响应,在开机情况下按重启按纽可以重新启动。关机:单击“开始”\关闭计算机\关闭,等一会电脑就关闭了。有三点要注意,一是提示“正在关闭计算机......”,不要点击立即结束,以免数据丢失;二是不要强行关机;三是关机后不要忘记关闭电源开关。  
2、鼠标和键盘的操作 鼠标有左键、右键、中键(滚轮),鼠标指针(光标)是鼠标操作的切入点,中键滚轮的作用相当于滚动条,左右键操作分为单击(就是左键单击)、双击(就是左键双击)、右击(就是右键单击)、拖动(拖曳)键盘: 键盘分成功能键区,主键盘区、编辑键区、状态指示区、辅助键区。下面只讲常用按键:Esc:强行退出键;Ctrl、Alt:两个键都是控制键,一般与其它键组合使用;Enter:回车键、换行键;CapsLock:是大写字母切换键;Delete:删除键;Backspace←:退格键,按一次往左边删除一格;NumLock键:用于切换小键盘区中的两种功能(数字和移动光标)。也是小键盘数字键的开关键,Num灯亮时小键盘才能使用;主键盘区二十六个英文字母排成三排。键盘操作的基本要领是双手、盲打,双手是指左手管左半边键盘,右手管右半边键盘,以G和H为分界线,手指要养成放在键盘固定位置的习惯,移动后也要马上复位,这样才能提高打字的速度。盲打是指输入时眼睛看着屏幕,凭感觉用手指击键,不用眼睛帮忙找键; 
3、Windows XP的桌面典型的桌面上有“我的文档”、“我的电脑”、“网上邻居”、“回收站”和“浏览器”图标,“我的电脑” 、“我的文档” 、“回收站” 、“Internet Explorer” 、“网上邻居”,其他图标都是后来自己增加的。最大部分空白区称为工作区,看到的是一张桌面壁纸;桌面最下面的长条叫任务栏,正在运行的程序都会在任务栏上显示出来,上面有图标和名称;最左边是“开始”按钮,最右边是“系统托盘”;。下面分别介绍:我的电脑和资源管理器我的电脑: 双击桌面“我的电脑”图标,打开我的电脑(上图),里面从上到下有共享文档、我的文档(有的显示的是用户名文档)、C、D、E、F四个磁盘(因为过去的电脑多带有软盘驱动器,更老一点的甚至有两个软盘驱动器A、B。所以硬盘是从C盘开始的)和光驱;资源管理器:右键点击我的电脑\资源管理器,出现下图 与打开我的电脑相比,左边多出了一项“文件夹”点一下就可以打开相应的文件和文件夹,而不用双击。开始菜单:点击左下方图标,出现的叫“开始菜单”, 在开始菜单中,最重要的有“所有程序”和“控制面板”。将鼠标移动到“所有程序”处,会看到你已经安装的所有程序; 下面这是控制面板窗口
文件与文件夹文件夹的展开(点击左边的+号变成-号)、折叠(点击左边的-号变成+号)、打开(双击打开,在后面专门讲)、关闭(点击窗口右上角的红×)新建文件夹:打开一个磁盘或文件夹,点击左边的“创建一个新文件夹” 删除(选定文件或文件夹,点击Delete删除或右键删除),重命名:⑴右键点击文件或文件夹,选择重命名;⑵对着下面的文件名或文件夹名左键点击两次就可修改了。复制:右键复制移动:右键剪切到另一个地方粘贴剪切:右键剪切粘贴:先复制或剪切,然后右键粘贴下面专门讲一下文件夹的查看显示,打开任何一个文件夹,右上方都有一个查看按纽,点击后出现缩略图、平铺、图标、列表和祥细信息的下拉式菜单,下图是“我的图片”文件夹的平铺显示 点击缩略图显示后变成下图 这个缩略图显示很有用,有时要在很多图片中查找某一张,用查看按纽就不用一张一张的打开了。5、回收站的清空与恢复文件删除后,有时想想还有用,可以打开回收站,找到那个文件,右键“还原”,就恢复了;时间长了,回收站集满了删除的文件,需要彻底清空,可以右键回收站,选择清空回收站,清空后就不能恢复了。6、窗口、菜单和对话框Windows 从英文字面上看就是窗户的复数形式,也就是说它是由很多窗口组成的。在Windows 操作系统中,每一个程序都有它的窗口。以Word窗口为例 窗口有标题栏、菜单栏、工具栏、滚动条、工作区、状态栏等。下图是写字板窗口 窗口操作:最大化(点击右上角方框)、最小化(点击右上角的-号,窗口只在状态栏显现)、恢复(最小化后点击状态栏文件名)、关闭(点击窗口右上角的红×)、改变大小(点击右上角双框或拉动边框进行大小调整)。对话框:对话框是用于人机交流的信息框,提示你干什么。对话框包括:下拉式列表框、文本框、命令按纽等。举桌面显示属性对话框为例,右键点击桌面空白处\属性,出现下图 顺便介绍一下相关属性设置XP的桌面主题包含风格、壁纸、屏保、鼠标指针、系统声音、图标,除了风格是必须的之外,其他部分都是可选的。风格是大家在Windows里所能看到的一切,例如窗口的外观、字体、颜色,按钮的外观等等,一个桌面主题的风格决定了看到的Windows的样子。要想自己换主题,只有到网上下载,一般自己不会做,但可以在已有的主题中选择;桌面:就是壁纸,可以自己换;屏幕保护程序:简称屏保,简单说屏保就是为了保护显示器,因为如果你的电脑不操作时,整个显示器呈现的画面是不变的,而如果只是一个图像,发出来的粒子总是撞击显示器的一个固定地方,对这个地方会造成损伤。于是就设计了一种程序,如果长时间不操作就会自动出现动态的屏保图案,可以选择使用或不用,也可以使用图片文件夹作为屏保,网上有很多好看的屏保软件;外观:一般不用修改;设置:主要用于设置分辨率,分辨率根据显示器的尺寸来设置,一般17英寸设为8像素,15英寸为800×600像素,有的软件(如会声会影)要求分辨率最少为8像素,分辨率越高桌面字体和图标越小。7、文件的分类与播放(阅读)文件可以分为文本文件、图形文件、音频文件、视频文件、超文本文件、压缩文件、镜像文件等等。文本文件就是文字组成的文件;图形文件就是图片、照片;音频文件就是音乐;电影、动画就是视频文件(GIF图片也有动画效果),视频文件可以同时含有音频;超文本文件可以带有文字、图片甚至音乐、视频的文件,网页就是个最典型的超文本文件;压缩文件是用压缩软件将任何文件压缩后形成的文件,最常用的压缩软件是WinRAR,一般通过点击右键压缩或解压,但都需要安装软件,用它制作的自解压文件可以在没有安装WinRAR的电脑上解压;镜像文件是用软碟通(UltraISO)制作的光盘镜像,没有安装软碟通的电脑可以用WinRAR打开解压。电脑中的文件因格式不同,必须安装相对应的阅读器或播放器才能阅读、播放,有的一个软件可以打开多种文件;有的一种文件格式可以被多种软件打开;很多软件既是编辑制作软件,又是播放器,如Word,既能编辑Word文档又能打开阅读Word文档;有的是专门的播放器,只能播放不能编辑。如果一种文件有多个软件可以打开,这就看这种文件被哪个软件关联了,双击打开的就是这个关联的软件,一些绿色免安装软件往往没有关联,可以右键该文件,点击打开方式,选择程序,通过浏览查找到相应的软件,勾选“始终使用选择的程序打开这种文件”,下次就不用查找了。 特别要解释的一点是文件显示的图标,文件被哪个软件关联,就显示哪个软件的图标。我在初学时,因为新安装了某个软件,忽然发现电脑中的某些文件变成了另外一种样子,还以为是电脑出了故障,其实是因为某些格式的文件被这个软件关联了,所以图标变成了另一种样子。比如,同一个mp3音频文件被Windows Media Player关联时图标是 ,而被千千静听关联时变成了 文件的打开方式有几种:一是双击该文件,让它自动去调用相应的播放器;二是打开该播放器或阅读器,点击文件\打开,查找打开某个文件;文本阅读Windows中自带的记事本是纯文本编辑和阅读工具,双击就可打开; Word文件除了用Word软件打开阅读外,还可以用写字板打开;看图(图片播放)最常见的图片格式是jpg、bmp、gif,点击图片就会自动用Windows中自带的看图工具“图片和传真查看器”打开图片,不用专门去找它;音频和视频播放最常见的音频格式有mp3、wma、wav,Windows中自带有Windows Media Player播放器,与图形一样,不用刻意去找它,打开音频,会在播放器中出现各种各样的动态画面(下图是Windows Media Player 11) 双击打开视频,就能象看电影一样收看。 但由于视频文件格式太多,很多格式用Windows Media Player播放器无法播放,如Flash、RM、MOV等,还要另外安装相应的播放器,我建议安装酷热影音Kuree,只要安装它,一切视频播放都会迎刃而解。光驱使用:光驱有CD光驱和DVD光驱之分,光盘也有CD、VCD、EVCD(超级VCD)和DVD光盘之分,高级的可以兼容低级版本,反过来不能播放,即DVD光驱可以播放VCD碟片,而CD光驱不能播放DVD光盘。这同VCD影碟机不能播放DVD光盘是一样的。将光盘放入光驱,一般光盘都带有自启动功能,会自动播放,不行可以打开我的电脑,点击CD驱动器播放。U盘和移动硬盘使用不要强行拔出.8、电脑中的容量和体积硬盘、文件夹都有它的容量,文件夹的大小是由其中的文件多少决定的,只要文件夹所在的硬盘还有空间,文件夹的容量就可继续增加。电脑中的文件是由字节组成的,1个字节是1B,是1024进位的,1KB=1024字节,1MB=1024KB,1GB=1024MB,平时都把B省略掉,常用的1M就是1兆。现在一般硬盘都是80G的;查看文件的大小,一是把鼠标指针对着它就会显现文件的大小, 二是右键该文件,打开属性对话框,能看到大小、保存路径等。 9、清理系统垃圾及多余的启动项Windows XP的最大缺点是,几乎每操作一步,都会留存下一些垃圾文件,包括:系统和软件安装过程中产生的临时文件、软件卸载后的遗留文件、上网产生的临时文件、历史记录、临时缓存等等,还有一些流氓软件删除不掉,日积月累,你的XP就会不堪重负,运行越来越慢。顺便说一下清除多余的启动项问题。很多软件安装后自动把它加载到启动项中,下次只要开启电脑,它就会自动运行,造成电脑好半天不能启动。在博客日志中说到的超级兔子\超级兔子魔法设置中点击启动程序,打开对话框,把不要的启动程序前的勾去掉,点击确定或应用就行了。
很实用,谢谢您!
帮顶一下,好贴不能沉啊
跳转到 0 ? parseInt(this.value) : 1) + '.aspx';}else{window.location='showtopic.aspx?topicid=102&page=' + (parseInt(this.value) > 0 ? parseInt(this.value) : 1) ;}}"" size="4" maxlength="9"/>页
showMenu(this.id);">当前位置:
计算MDI子窗口数,仅显示文件夹的打开对话框
计算MDI子窗口数,仅显示文件夹的打开对话框
发布日期: 09:49
浏览次数:4875次
标  签:windows
文章评分:5.0
操  作:
称号:未设置简介:...
文章概要:
1、我正在写一个 MFC 的多文档(MDI)应用。在父窗口中,我如何检查所有的MDI子窗口是否都已经关闭?如果都关闭了,那么我想在我的主窗口激活一个窗格。
2、我正在用 Visual Studio .NET 和 MFC 做一个程序。在我的程序里,用户要选择一个文件夹,并在其中拷贝文件。我可以调用 OpenFileDialog 让用户选择某个文件,但如何让打开对话框只显示文件夹呢?我见过好多安装程序给出的对话框里只显示文件夹,但我好像找不到这样的标志。
计算 MDI 子窗口数
仅显示文件夹的打开对话框
我正在写一个 MFC 的多文档(MDI)应用。在父窗口中,我如何检查所有的MDI子窗口是否都已经关闭?如果都关闭了,那么我想在我的主窗口激活一个窗格。
Windows 和 MFC 不提供任何专门的函数来获取 MDI 子窗口数,但实现你想要的这个功能很容易。实际上,我可以想到半打方法来解决这个问题。你可以捕获 WM_CREATE/WM_DESTROY 消息;可以用 SetWindowsHookEx 安装 Windows 钩子;可以用 EnumWindows 来枚举子窗口并计算它的数量。但最简单的解决方法常常是最容易被忽视的方法。
这个问题说白了,无非就是――应用程序使用 MDI 界面或者其它你自己设计的多窗口用户界面――说到底就是一个窗口列表。Figure 1 展示的是一个基于标准模板库(STL) list 的类,很难说这样封装是否值得,但我只是觉得 Windows 程序员在代码中敲入 “push_back”太不可思议。CWinList 使你用“Add”取而代之。为了使用 CWinList,只需要在某个地方添加一个全局实例,既可以是一个全局变量,也可以是主应用程序类中的一个数据成员:
Figure 1 WinList.h
////////////////////////////////////////////////////////////////
// MSDN Magazine — June 2005
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3.
#pragma once
//////////////////
// Simple list class to keep track of windows by adding them to a list.
// Use this to keep track of MDI child or other windows. See view.cpp for
// example of how to use. Based on STL list, CWinList is a list of CWnd
// pointers:
// list& CWnd* &, with methods Add and Remove. You can also call any other
// STL list functions you want, and use the list iterator to enumerate
// the items in the list.
class CWinList : public list& CWnd* & {
CWinList() { }
~CWinList() {
// add window to list
void Add(CWnd* pWnd) {
push_back(pWnd);
// remove window from list
void Remove(CWnd* pWnd) {
remove(pWnd);
class CMyApp : public CWinApp {
CWinList m_ // 打开的恶窗口列表
为了跟踪子窗口,你只需要在创建或销毁子窗口时对此列表进行添加或删除操作既可。显然做这件事情的最佳地点是在拟跟踪窗口的构造函数和析构函数中:
CMyView::CMyView()
theApp.m_winlist.Add(this);
CMyView::~CMyView()
theApp.m_winlist.Remove(this);
除此之外,你还可以从 OnCreate 和 OnDestroy 处理函数中调用 Add 和 Remove,以保证你的列表之包含具备有效的 HWNDs 的窗口对象。因为 CWinList 是从 list 派生而来的,所以处理过程中可以充分借助 STL的威力。例如,你可以用 STL list 的迭代器(iterator)枚举列表中的窗口:
CWinList& wl = theApp.m_
for (CWinList::iterator it=wl.begin(); it!=wl.end(); it++) {
CWnd* pWnd = *
// do something
我写了一个小程序 WinCount,它用 CWinList 计数 MDI 子窗口。运行画面如 Figure 2 所示。
Figure 2 计算子窗口的 WinCount
WinCount 右下角有一个状态栏窗格显示打开的窗口数量,该程序的“关于”对话框列出了窗口的标题。这个“关于”对话框就是用 CWinList::iterator 来产生它的反馈消息;该状态栏窗格是一个标准的 MFC 指示器窗格,使用 ON_UPDATE_COMMAND_UI 来显示视图数量。
void CMainFrame::OnUpdateWinIndicator(CCmdUI* pCmdUI)
s.Format(_T("Open:%d"), theApp.m_winlist.size());
pCmdUI-&SetText(s);
List::size 是 STL list 方法,返回列表中的项数,注意在 WinCount 中,视图与子窗口是一对一的,所以计算出的视图数就是 MDI 子窗口的数量。如果你的 MDI 是更复杂的多视图子框架,那么你必须重写 CMDIChildWnd 以便在派生类中进行 Add/Remove 调用,或者你可以用其它窗口类,保证它在每个子框架中只出现一次。你可以随便使用多少个 CWinList 来跟踪不同的窗口类。
我知道我们处在一个令人兴奋得 MFC、.NET 和 GUI 框架时代,很多事情都可以让它们代劳――但不要忘了如何使用基本的数据结构!
[编辑更新 - 5/9/2005:在 Figure 1 所示的 CWinList 原创实现里,它是从 list 派生而来的。然而,一般情况下,从 STL 容器派生被认为是一种糟糕的做法,因为这样做搞不好会导致不可预知的结果。本文最终下载的代码是一个新版本的 CWinList,使用 typedef。需要用 push_back 和 remove 来代替 Add 和 Remove。]
我正在用 Visual Studio .NET 和 MFC 做一个程序。在我的程序里,用户要选择一个文件夹,并在其中拷贝文件。我可以调用 OpenFileDialog 让用户选择某个文件,但如何让打开对话框只显示文件夹呢?我见过好多安装程序给出的对话框里只显示文件夹,但我好像找不到这样的标志。
Laine Chandler
你之所以找不到正确的标志,是因为你关注的函数不对!文件打开对话框(Win32 是 GetOpenFileName,而 MFC 是 CFileDialog)是不处理文件夹的。为了只显示文件夹,你必须调用专门的外壳函数 SHBrowseForFolder。为了使用这个函数,你得填写一大堆 BROWSEINFO 结构信息,然后调用 SHBrowseForFolder。Windows 显示一个类似 Figure 3 这样的对话框。用户可以导航文件夹层次,扩展和收缩它们,并选择想要的文件夹。
Figure 3 调用 SHBrowseForFolder
不幸的是,使用 SHBrowseForFolder 并不象 CFileDialog 那么容易。它需要理解外壳的基本工作模式,外壳严重依赖 COM,IShellFolder 和 PIDLs。所谓 PIDL(读作“piddle”)是 pointer-to-item-ID-list (ID 列表项指针)的简称。实际对应的 C 类型是 LPITEMIDLIST,或常量变体 LPCITEMIDLIST。PIDL 是一字节串,外壳用它来确定外壳对象,如文件、文件夹,以及伪对象如:我的电脑或网络邻居。对于普通的文件和文件夹,该字节串包含 Unicode 路径名,而对于其它对象则不然。重要的是当你的用户最终选择某个文件夹时,SHBrowseForFolder 返回的是一个 PIDL。为了获得路径名,你得进行转换。
因为 SHBrowseForFolder 非常有用,而 MFC 又没有提供什么类来封装它,我决定自己为大家写一个。(我知道,我是个好人)。CFolderDialog 隐藏了复杂的代码,使得你浏览文件夹易如反掌。你只需要实例化并调用BrowseForFolder 既可:
CFolderDialog dlg(this);
LPCITEMIDLIST pidl = dlg.BrowseForFolder(
_T("Pick a folder, dude!"), BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT);
CString path = dlg.GetPathName(pidl);
CFolderDialog 甚至具备一个将 PIDL 转换为 CString 类型路径名的函数。如果你给 出 BROWSEINFO::pszDisplayName 缓冲,则 SHBrowseForFolder 能将选中的文件夹作为 TCHAR 串返回,但返回的显示名称只有全路径的最后一部分――例如,如果全路径名是:C:\MyStuff\Pub\Photos,则显示的是“Photos”。如果你想得到全路径名,你必须用 SHGetPathFromIDList 或我自己的函数 GetPathName 转换 PIDL。如果显示名是你想要的,则调用 CFolderDialog::GetDisplayName。
如果你只是让用户得到一个文件夹,那么 BrowseForFolder 和 GetPathName 就足够了。但 SHBrowseForFolder能做更多的事情。由于有了 GetOpenFileName,你可以提供一个回调函数来定制其行为。如果提供 BROWSEINFO::lpfn 中的 BrowseCallbackProc,Windows 只要发现你填充了这个域便会调用它。例如,Windows 在文件夹对话框自身被初始化时发送 BFFM_INITIALIZED,当用户选择某个新文件夹时发送 BFFM_SELCHANGED。你的回调过程能处理这些通知消息并做任何想做的事情。例如,你可以通过发送 BFFM_ENABLEOK 来启动或禁用 OK 按钮,或者用 BFFM_SETOKTEXT 改变按钮文本。CFolderDialog 用典型的 MFC 方式的 C++ 虚拟处理函数来替代 C 语言风格的回调,所以要写一个从 CFolderDialog 派生的回调过程并该写 OnInitialized 和 OnSelChanged 这样的虚函数。CFolderDialog 在内部使用其自己调用这些方法的回调。
为了操练更多 CFolderDialog 的高级特性,我写了一个测试程序 FolderPick。它有两个运行文件夹对话框的命令。一个显示“旧式”对话框;另一个显示新式对话框。新式样(BIF_NEWDIALOGSTYLE)创建一个更大的,可变大小的对话框,对应的按钮是“Make New Folder”――如果你指定 BIF_EDITBOX――则有一个编辑框,用户可以敲入文件夹的名字。其它标志还有 BIF_BROWSEFORCOMPUTER,用于显示计算机,BIF_BROWSEFORPRINTER 用于打印机。BIF_RETURNONLYFSDIRS 告诉 Windows 仅返回文件系统目录,而非伪文件夹,如网络邻居,BIF_STATUSTEXT 创建一个状态窗口,你可以设置其文本。(新式对话框不支持 BIF_STATUSTEXT)。完整的标志清单请参考 BROWSEINFO 文档。
FolderPick 派生一个新类,CMyFolderDialog,重写了 nInitialized 和 OnValidateFailed。当该对话框被初始化时,FolderPick 设置状态文本并将 OK 按钮的名字改为“Choose Me!”:
void CMyFolderDialog::OnInitialized()
SetStatusText(_T("Nice day, isn''t it?"));
SetOKText(L"Choose Me!");
这里有两件事情需要注意。第一,CFolderDialog 有包装器,SetStatusText 和 SetOKText,用于文件夹对话框消息 BFFM_SETSTATUSTEXT and BFFM_SETOKTEXT。如果你用 C 编程,你要调用 ::SendMessage;但 CFolderDialog 调用包装器既可。唯一的警告是你只能从通虚拟知消息处理函数(OnInitialized,OnSelChanged 等)中调用这些包装器,因为 m_hWnd 仅在文件夹对话框真正运行的时候才有效,调用 BrowseForFolder 之前或之后则不然。当其回调第一次收到通知消息时,CFolderDialog 在内部子类化文件夹对话框。第二,某些 BFFM_ 消息需要 Unicode 串,而不是 LPCTSTRs。这就是为何代码段中“Choose Me!”使用的是宽字符串的原因(带前缀 L)。
如果你试图用 C 编写 SHBrowseForFolder 程序,Microsoft 的文档有两个小错误,我必须在此指出来。文档中说 BFFM_SETOKTEXT 使用的字符串是在 WPARAM 中传递的,但实际上却是在 LPARAM 中。文档还说 BFFM_SETSELECTION 需要 Unicode 字符串,但 BFFM_SETSELECTION 的处理函数 A 和 W两个版本都有。所以你可以在其中使用 LPCTSTR。
如果你在新式样对话框中使用 BIF_EDITBOX,Windows 将显示一个编辑框,用户可以在其中敲入文件夹名。如果用户敲入非法数据,Windows 将用 BFFM_VALIDATEFAILED 调用浏览过程。CFolderDialog 会调用 OnValidateFailed 来处理它。FolderPick 该写了 OnValidateFailed 以显示如 Figure 4 所示的出错信息框。
BOOL CMyFolderDialog::OnValidateFailed(LPCTSTR lpsz)
MessageBox(...);
return TRUE; // don''t dismiss dialog
Figure 4 FolderPick 的出错框
SHBrowseForFolder 支持的另一个很酷的特性是过滤器定制。它能让你以项目为单位控制在文件夹对话框中显示那些项。使用回调时,这种机制冗长而繁琐。你必须得实现 COM 接口,IFolderFilter,它有两个方法:GetEnumFlags 和 ShouldShow。当文件夹对话框向你的回调发送 BFFM_IUNKNOWN 时,你必须要用 QueryInterface 查询为 IFolderFilterSite 而传递的 IUnknown,然后用你的 IFolderFilter 调用 IFolderFilterSite::SetFilter。现在文件夹对话框调用你的 IFolderFilter::ShouldShow 来过滤每一项,当不再需要 IFolderFilterSite 时必须对之进行 Release 操作。
自然,我将所有这些细节都作了封装。为了使用定制的过滤器,你只需以 bFilter=TRUE 调用 BrowseForFolder 既可,并改写两个虚函数:OnGetEnumFlags 和 OnShouldShow。不需要再处理 COM 的细节――QueryInterface 或 IFolderFilter。Figure 5 具体实现代码和 Figure 6。CFolderDialog 在内部实现了自己的 IFolderFilter,也就是调用对应的虚拟函数。CFolderDialog::OnIUnknown 使用了活动模板库(ATL)CComQIPtr 智能指针类,它使得 COM 编码轻而易举。
Figure 5 FolderDlg
FolderDlg.h
////////////////////////////////////////////////////////////////
// MSDN Magazine — June 2005
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab
// size=3.
#pragma once
#include "debug.h" // debugging tools
//////////////////
// Class to encapsulate SHBrowseForFolder. To use, instantiate in your
// app and call BrowseForFolder, which returns a PIDL. You can call
// GetPathName to get the path name from the PIDL.
class CFolderDialog : public CWnd {
CFolderDialog(CWnd* pWnd);
~CFolderDialog();
LPCITEMIDLIST BrowseForFolder(LPCTSTR title, UINT flags,
LPCITEMIDLIST pidRoot=NULL, BOOL bFilter=FALSE);
CString GetDisplayName() { return m_sDisplayN }
// helpers
static CString GetPathName(LPCITEMIDLIST pidl);
static CString GetDisplayNameOf(
IShellFolder* psf, LPCITEMIDLIST pidl, DWORD uFlags);
static void FreePIDL(LPCITEMIDLIST pidl);
protected:
BROWSEINFO m_
// used with SHBrowseForFolder
CString m_sDisplayN
// display name of folder chosen
// do custom filtering?
CComQIPtr m_shfR
// handy to have root folder
static CALLBACK CallbackProc(
HWND hwnd, UINT msg, LPARAM lp, LPARAM lpData);
virtual int OnMessage(UINT msg, LPARAM lp);
// internal catch-all
// Virtual message handlers: override these instead of using callback
virtual void OnInitialized()
virtual void OnIUnknown(IUnknown* punk);
virtual void OnSelChanged(LPCITEMIDLIST pidl)
virtual BOOL OnValidateFailed(LPCTSTR lpsz)
{ return TRUE; }
// wrappers
void EnableOK(BOOL bEnable) {
SendMessage(BFFM_ENABLEOK,0,bEnable);
void SetOKText(LPCWSTR lpText) {
SendMessage(BFFM_SETOKTEXT,0,(LPARAM)lpText);
... // etc (more wrappers—download for details)
// Override for custom filtering. You must call BrowseForFolder
// with bFilter=TRUE.
virtual HRESULT OnGetEnumFlags(...) { return S_OK; }
virtual HRESULT OnShouldShow(...)
{ return S_OK; }
// IFolderFilter: used to do custom filtering. Download for details.
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(FolderFilter, IFolderFilter)
STDMETHOD(GetEnumFlags)(IShellFolder* psf, ...);
STDMETHOD(ShouldShow)(IShellFolder* psf, ...);
END_INTERFACE_PART(FolderFilter)
FolderDlg.cpp
#include "stdafx.h"
#include "FolderDlg.h"
CFolderDialog::CFolderDialog(CWnd* pWnd)
memset(&m_brinfo,0,sizeof(m_brinfo));
m_brinfo.hwndOwner=pWnd-&m_hW
// use parent window
m_bFilter = FALSE;
// default: no filtering
SHGetDesktopFolder(&m_shfRoot);
// get root IShellFolder
// Browse for folder. Args are same as for SHBrowseForFolder,
// but with extra bFilter that tells whether to do custom filtering.
LPCITEMIDLIST CFolderDialog::BrowseForFolder(LPCTSTR title, UINT flags,
LPCITEMIDLIST root, BOOL bFilter)
TCHAR* buf = m_sDisplayName.GetBuffer(MAX_PATH);
m_brinfo.pidlRoot =
m_brinfo.pszDisplayName =
m_brinfo.lpszTitle =
m_brinfo.ulFlags =
m_brinfo.lpfn = CallbackP
m_brinfo.lParam = (LPARAM)
// filtering only supported for new-style dialogs
m_bFilter = bF
ASSERT(!bFilter||(m_brinfo.ulFlags & BIF_NEWDIALOGSTYLE));
LPCITEMIDLIST pidl = SHBrowseForFolder(&m_brinfo); // do it
m_sDisplayName.ReleaseBuffer();
// Handy function to get the string pathname from pidl.
CString CFolderDialog::GetPathName(LPCITEMIDLIST pidl)
TCHAR* buf = path.GetBuffer(MAX_PATH);
SHGetPathFromIDList(pidl, buf);
path.ReleaseBuffer();
// Handy function to get the display name from pidl.
CString CFolderDialog::GetDisplayNameOf(IShellFolder* psf,
LPCITEMIDLIST pidl, DWORD uFlags)
// special struct for GetDisplayNameOf
strret.uType = STRRET_CSTR;
// get as CSTR
if (SUCCEEDED(psf-&GetDisplayNameOf(pidl, uFlags, &strret))) {
StrRetToBuf(&strret, pidl, dn.GetBuffer(MAX_PATH), MAX_PATH);
dn.ReleaseBuffer();
//////////////////
// Free PIDL using shell's IMalloc
void CFolderDialog::FreePIDL(LPCITEMIDLIST pidl)
CComQIPtriM
HRESULT hr = SHGetMalloc(&iMalloc);
ASSERT(SUCCEEDED(hr));
iMalloc-&Free((void*)pidl);
// Internal callback proc used for SHBrowseForFolder passes control to
// appropriate virtual function after attaching browser window.
int CFolderDialog::CallbackProc(
HWND hwnd, UINT msg, LPARAM lp, LPARAM lpData) {
CFolderDialog* pDlg = (CFolderDialog*)lpD
ASSERT(pDlg);
if (pDlg-&m_hWnd!=hwnd) {
if (pDlg-&m_hWnd)
pDlg-&UnsubclassWindow();
pDlg-&SubclassWindow(hwnd);
return pDlg-&OnMessage(msg, lp);
// Handle notification from browser window: pass to specific handler function.
int CFolderDialog::OnMessage(UINT msg, LPARAM lp) {
switch (msg) {
case BFFM_INITIALIZED: OnInitialized(); return 0;
case BFFM_IUNKNOWN:
OnIUnknown((IUnknown*)lp); return 0;
case BFFM_SELCHANGED:
OnSelChanged((LPCITEMIDLIST)lp); return 0;
case BFFM_VALIDATEFAILED: return OnValidateFailed((LPCTSTR)lp);
default: TRACE(
_T("***Warning: unknown message %d in CFolderDialog::OnMessage\n"));
// Browser is notifying me with its IUnknown: use it to set filter if
// requested. Note this can be called with punk=NULL when shutting down!
void CFolderDialog::OnIUnknown(IUnknown* punk) {
if (punk && m_bFilter) {
VERIFY(SUCCEEDED(punk-&QueryInterface(
IID_IFolderFilterSite, (void**)&iffs)));
iffs-&SetFilter((IFolderFilter*)&m_xFolderFilter);
... // Standard MFC IUnknown not shown here — download source for details
//////////////////////////////// IFolderFilter ////////////////////////////
// Implementation passes control to parent class CFolderDialog (pThis)
BEGIN_INTERFACE_MAP(CFolderDialog, CCmdTarget)
INTERFACE_PART(CFolderDialog, IID_IFolderFilter, FolderFilter)
END_INTERFACE_MAP()
STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::AddRef() {
METHOD_PROLOGUE(CFolderDialog, FolderFilter);
return pThis-&AddRef();
STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::Release() {
METHOD_PROLOGUE(CFolderDialog, FolderFilter);
return pThis-&Release();
STDMETHODIMP CFolderDialog::XFolderFilter::QueryInterface(
REFIID iid, LPVOID* ppv) {
METHOD_PROLOGUE(CFolderDialog, FolderFilter);
return pThis-&QueryInterface(iid, ppv);
// Note: pHwnd is always NULL here as far as I can tell.
STDMETHODIMP CFolderDialog::XFolderFilter::GetEnumFlags(IShellFolder* psf,
LPCITEMIDLIST pidlFolder, HWND *pHwnd, DWORD *pgrfFlags) {
METHOD_PROLOGUE(CFolderDialog, FolderFilter);
return pThis-&OnGetEnumFlags(psf, pidlFolder, pgrfFlags);
STDMETHODIMP CFolderDialog::XFolderFilter::ShouldShow(IShellFolder* psf,
LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem) {
METHOD_PROLOGUE(CFolderDialog, FolderFilter);
return pThis-&OnShouldShow(psf, pidlFolder, pidlItem);
如果你决定用定制的过滤器,要小心,因为它改写了 BIF_RETURNONLYFSDIRS 这样的标志(只返回文件系统目录)。出于好玩,我决定当所选的项目不是文件系统目录时,通过手动禁用 OK 按钮,自己为 FolderPick 实现 BIF_RETURNONLYFSDIRS。为了检查文件系统对象,你要考虑适当的方式调用 IShellFolder::GetAttributesOf 并寻找 SFGAO_FILESYSTEM。但是当我尝试这样做的时候,“我的电脑”得到的是SFGAO_FILESYSTEM 属性,尽管它并非真正的文件系统目录!后来,我发现要想知道某个外壳对象是否为真正的文件或文件夹,唯一可靠的方法是调用 GetPathName 并检查串是否为空。在 CMyFolderDialog 中我就是这么做的,一旦碰到非文件夹则禁用 OK 按钮。具体细节请参考下载的源代码。
最后,为了帮助你理解来龙去脉,我对运行时的 CFolderDialog 进行了 TRACE 跟踪诊断。如图 Figure 6 所示。
Figure 6 TraceWin
你可以通过设置 CFolderDialog::bTRACE 全局变量对诊断进行开/关控制。当然,跟踪只能在调试模式进行。下载的代码中附带有 TraceWin 的免费拷贝,以便不用运行调试器就能察看诊断输出。
SHBrowseForFolder 还有许多标志和特性我没有发掘,但是不论你使用哪种特性,CFolderDialog 都能减轻你的工作负担并让你能用 MFC 的方式来编写使用 SHBrowseForFolder 的程序。
祝编程愉快!
您的提问和评论可发送到 Paul 的信箱:
Paul DiLascia 是一名自由作家,顾问和 Web/UI 设计者。他是《Writing Reusable Windows Code in C++》书(Addison-Wesley, 1992)的作者。通过
可以获得更多了解。  
本文出自 MSDN Magazine 的 June 2005 期刊,可通过当地报摊获得,或者最好是 订阅
最多还可以输入100字
【VIP年会员制套餐】
【C/C++软件工程师实战能力集训大纲】
VC知识库发布了C/C++业界的“本草纲目”
【牛人都在千人一号群! 加群三步走!!!】
第一步:请必须加VC知识库QQ: 为好友;
第二步:请必须关注本站微博:
第三步:申请加入群:.(必须将关注微博截屏发到QQ方可通过!)
【最新2013:】
全部100% VC++源码提供: E-Form++全新大型SCADA & HMI解决方案源码、CAD解决方案源码、Gis解决方案源码 、电力石油化工仿真与图形建模解决方案源码、大量其他高级制图VC++源码下载!
【 新视频发布】
o o o o o o o o o o
用CListCtrl来显示数据比较方便,有时候我们需要标注某一列或某一个单元格的背景和字体颜色,或者需要改变一下行高和字体大小,CListCtrl要改变这些并不是很方便。本文将介绍如何派生一个类来改变CListCtrl及其表头的高度、字体大小、列背景颜色、单元格背景颜色、列字体颜色、单元格字体颜色。...
在VC环境中除了我们所常用的Dialog、Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多。...
本文介绍了套接字编程的基本知识。...

我要回帖

更多关于 找不到appdata文件夹 的文章

 

随机推荐