文件夹浏览(SHBrowseForFolder)
from http://www.cnblogs.com/Clingingboy/archive/2011/04/16/2018284.html
一.首先要为SHBrowseForFolder准备一个结构体BROWSEINFO
typedef struct _browseinfoW {
HWND hwndOwner;
PCIDLIST_ABSOLUTE pidlRoot;
LPWSTR pszDisplayName; // Return display name of item selected.
LPCWSTR lpszTitle; // text to go in the banner over the tree.
UINT ulFlags; // Flags that control the return stuff
BFFCALLBACK lpfn;
LPARAM lParam; // extra info that's passed back in callbacks
int iImage; // output var: where to return the Image index.
} BROWSEINFOW, *PBROWSEINFOW, *LPBROWSEINFOW;
二.获取PIDL
在BROWSEINFOW结构体中,pidlRoot是最关键的,需要调用一些额外的函数来获取PIDL,然后给pidlRoot赋值
1.获取特殊的目录地址
在Windows中有很多特殊的的目录地址,如我的电脑,控件面板,我的图片等,如下定义
#define CSIDL_DESKTOP 0x0000 // <desktop>
#define CSIDL_INTERNET 0x0001 // Internet Explorer (icon on desktop)
#define CSIDL_PROGRAMS 0x0002 // Start Menu\Programs
#define CSIDL_CONTROLS 0x0003 // My Computer\Control Panel
#define CSIDL_PRINTERS 0x0004 // My Computer\Printers
#define CSIDL_PERSONAL 0x0005 // My Documents
#define CSIDL_FAVORITES 0x0006 // <user name>\Favorites
#define CSIDL_STARTUP 0x0007 // Start Menu\Programs\Startup
#define CSIDL_RECENT 0x0008 // <user name>\Recent
我们可以通过SHGetSpecialFolderLocation来填充一个LPITEMIDLIST,
BROWSEINFO bi;
bi.hwndOwner = hDlg;
TCHAR szTitle[MAX_PATH] = {0};
TCHAR szPath[MAX_PATH] = {0};
TCHAR szDisplay[MAX_PATH] = {0};
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
bi.pidlRoot = pidl;
然后调用SHBrowseForFolder(&bi);就可以出现以下对话框
2.使用IShellFolder获取目录地址
如果不是特殊目录的,可以使用IShellFolder的ParseDisplayName方法,来获取PIDL
首先要调用SHGetDesktopFolder函数来获取IShellFolder,ShellFolder代表桌面,表示是根目录,根目录总是有办法找到任意一个子目录的
然后调用ParseDisplayName方法来解析目录,最终得到LPITEMIDLIST。
下面的步骤还是一样把LPITEMIDLIST填充到BROWSEINFO的pidlRoot 字段,调用SHBrowseForFolder方法
SHParseDisplayName方法提供了一个便利
HRESULT SHPathToPIDL(LPCTSTR szPath, LPITEMIDLIST* ppidl)
{
LPSHELLFOLDER pShellFolder = NULL;
OLECHAR wszPath[MAX_PATH] = {0};
ULONG nCharsParsed = 0; // Get an IShellFolder interface pointer
HRESULT hr = SHGetDesktopFolder(&pShellFolder);
if(FAILED(hr))
return hr; // Convert the path name to Unicode
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH); // Call ParseDisplayName() to do the job
hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL); // Clean up
pShellFolder->Release();
return hr;
}
3.获取选择的目录
当选中目录点击确定之后,就需要获取一个文件系统路径,可以使用SHGetPathFromIDList函数
SHGetPathFromIDList(pidlFolder, szPath);
szPath就是我们想要的结果
4.BROWSEINFO的回调方法
在.net中会声明很多的事件,若Initialized,SelectedChanged等,c++是采用消息的机制,根据消息的不同进行不同处理,当然这些消息都是预先定义好的.
#define BFFM_INITIALIZED 1
#define BFFM_SELCHANGED 2
#define BFFM_VALIDATEFAILEDA 3 // lParam:szPath ret:1(cont),0(EndDialog)
#define BFFM_VALIDATEFAILEDW 4 // lParam:wzPath ret:1(cont),0(EndDialog)
#define BFFM_IUNKNOWN 5 // provides IUnknown to client. lParam: IUnknown*
示例如下:
bi.lpfn = BrowseCallbackProc; int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM dwData)
{
switch(uMsg)
{
case BFFM_INITIALIZED:
{ }
break; case BFFM_SELCHANGED:
{ }
break; case BFFM_VALIDATEFAILED: return 1;
} return 0;
}
三.文件夹选项
如下图,应该是很熟悉
SHGetSettings函数可以获取这些选项的信息,存在结构体SHELLFLAGSTATE当中
typedef struct {
BOOL fShowAllObjects : 1;
BOOL fShowExtensions : 1;
BOOL fNoConfirmRecycle : 1;
BOOL fShowSysFiles : 1;
BOOL fShowCompColor : 1;
BOOL fDoubleClickInWebView : 1;
BOOL fDesktopHTML : 1;
BOOL fWin95Classic : 1;
BOOL fDontPrettyPath : 1;
BOOL fShowAttribCol : 1;
BOOL fMapNetDrvBtn : 1;
BOOL fShowInfoTip : 1;
BOOL fHideIcons : 1;
#if (NTDDI_VERSION >= NTDDI_VISTA)
BOOL fAutoCheckSelect: 1;
BOOL fIconsOnly: 1;
UINT fRestFlags : 1; // when adding additional flags keep SHELLSTATE and SHGetSettings in sync. #else
UINT fRestFlags : 3; // when adding additional flags keep SHELLSTATE and SHGetSettings in sync.
#endif
} SHELLFLAGSTATE, *LPSHELLFLAGSTATE;
必须输入想要获取标识才行,不然就会是默认值(难道是为了性能,为何如此,太麻烦)
SHELLFLAGSTATE sfs;
SHGetSettings(&sfs, SSF_DESKTOPHTML | SSF_SHOWALLOBJECTS |
SSF_MAPNETDRVBUTTON | SSF_SHOWATTRIBCOL | SSF_SHOWEXTENSIONS);
文件夹浏览(SHBrowseForFolder)的更多相关文章
- 关于WPF中文件夹浏览对话框的方式
文件夹浏览时dialogresult要写全引用路径 string path=null; FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd ...
- FolderBrowserDialog(文件夹浏览对话框)
1.选择数据库目录,在此处不需要新建文件夹,因此屏蔽新建文件夹按钮. C#代码 FolderBrowserDialog df = new FolderBrowserDialog(); //设置文件浏览 ...
- 清除Windows 10的文件夹浏览痕迹
windows 10有一个功能就是在快速访问时显示“最近访问的文件”,“常用文件”.如果是一台共用电脑,这个功能会经常暴露自己的“行踪”. 可以在“文件夹选项”-“隐私”中去掉勾选,并点击“清除”来清 ...
- WPF中弹出文件夹浏览对话框
附一个共享目录正则表达式判断: bool result= System.Text.RegularExpressions.Regex.IsMatch("\\pc-test\share" ...
- 在WPF中调用文件夹浏览/选择对话框
var dialog = new System.Windows.Forms.FolderBrowserDialog(); System.Windows.Forms.DialogResult resul ...
- MFC 使用MFC EditBrowse Control控件选择文件或者文件夹
从工具箱中拖拽一个MFC EditBrowse Control到窗体中, 通过设置“Browse Mode”属性指定“文件浏览”还是“文件夹浏览” 可以通过添加对象的方式将其与一个CString se ...
- MFC 如何创建浏览文件夹的对话框
如何创建浏览文件夹的对话框 如何创建浏览文件夹的对话框 CString CXXXXDlg::GetOpenfolderPath() { BROWSEINFO bi; ZeroMemory(&b ...
- C#利用浏览按钮获得文件路径和文件夹路径
生成文件夹路径 private void btnChoose_Click(object sender, EventArgs e) { using (OpenFileDialog ...
- atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php
atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...
随机推荐
- HDU - 5884 Sort (二分答案+贪心)
有n个数字,你需要把这n个数字合成一个数字,每次只能把k个数字合并成一个,花费为这k个数字的和. 给一个最大花费,问不超过这个最大花费的情况下,k的最小值. Sample Input 1 5 25 1 ...
- C指针问题
<!DOCTYPE html> 多级c指针传值问题 /* GitHub stylesheet for MarkdownPad (http://markdownpad.com) / / Au ...
- Python虚拟机中的一般表达式(一)
在Python虚拟机框架这一章中,我们通过PyEval_EvalFrameEx看到了Python虚拟机的整体框架.而这章开始,我们将了解Python虚拟机是如何完成对Python的一般表达式的执行,这 ...
- TCP缓冲区大小及限制
这个问题在前面有的部分已经涉及,这里在重新总结下.主要参考UNIX网络编程. (1)数据报大小IPv4的数据报最大大小是65535字节,包括IPv4首部.因为首部中说明大小的字段为16位.IPv6的数 ...
- Freemarker的循环通过assign指令引入计数变量
这里是一个jeecms框架的前台的一个内容列表集,因为不是每个内容子项符合要求,而且需要统计符合要求的子项个数,仿照java的for循环,需要在循环前声明一个计数变量,这就需要使用Freemaker的 ...
- 学习boundingRectWithSize:options:attributes:context:计算文本尺寸
oundingRectWithSize:options:context: 返回文本绘制所占据的矩形空间. - (CGRect)boundingRectWithSize:(CGSize)size opt ...
- jQuery效果show()方法
$("button").click(function(){ $("p").show(); }); Syntax $(selector).show(speed,e ...
- Python 协程、IO模型
1.协程(单线程实现并发)2.I/0模型 2.1阻塞I/O 2.2非阻塞I/O 知识点一:协程 协程的目的:是想要在单线程下实现并发(并发看起来是同时运行的) 并发=多个任务间切换+保存状态(正常情况 ...
- javascript学习笔记 - 面向对象 理解对象
ECMAScript 中有两种属性:数据属性和访问器属性 一 属性类型 1.数据属性.数据属性有4个描述其行为的特性 [[Configurable]]表示能否通过delete删除属性从而重新定义属性: ...
- 【java基础 15】java代码中“==”和equals的区别
导读:昨夜闲来无事,和贾姑娘聊了聊java基础,然后就说到了这个"=="和equals的问题,我俩都是以前了解过,也常用这个,但是,昨天说到的时候,又乱了,什么比较地址值,什么判断 ...