文件夹浏览(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,需要打开浏览服 ...
随机推荐
- poj 3190 奶牛挤奶问题 贪心算法
题意:奶牛挤奶问题,每只奶牛在[a,b]的时间内挤奶,要求挤奶的过程中不能不打扰,且只能自己一个人独享挤奶的机器.问最少需要多少个挤奶的机器? 思路: 对奶牛挤奶开始的时间从小到大开始排序. 将正在工 ...
- dubbo doc入门文档
dubbo document http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-protocol.html
- docker容器utf-8编码问题
locale -a export LANG=C.UTF-8 locale 在docker容器中python脚本汉字的会乱码 按照上面的方法暂时的设置下容器 编码可以解决脚本中文乱码问题
- windows系统使用的误区
1.软件不要装在c盘,影响系统运行速度. 软件c盘不会影响系统运行,会提高软件运行速度 PS:前提条件:C盘有足够的空余空间(50G以上). 大多数软件安装默认路径在C盘的原因是不知道电脑分区的情况, ...
- 大数据学习——spark笔记
变量的定义 val a: Int = 1 var b = 2 方法和函数 区别:函数可以作为参数传递给方法 方法: def test(arg: Int): Int=>Int ={ 方法体 } v ...
- requests与urllib 库
requests库 发送请求: 可以处理所有请求类型:get.post.put.Delete.Head.Options r = requests.get(''https://httpbin.org/' ...
- python 计算日期间隔
from datetime import date a = date(2011,11,24) b = date(2011,11,17) print(a-b)
- 【bzoj2724】[Violet 6]蒲公英 分块+STL-vector
题目描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 样例输入 6 3 1 2 3 2 1 2 1 5 3 ...
- mysql explain字段意思解释
mysql explain字段意思解释 explain包含id.select_type.table.type.possible_keys.key.key_len.ref.rows.extra字段 id ...
- Django模板遍历字典的方法
使用Python + Django做Web开发时,有时需要在view中传递一个字典给模板(template),如何在模板中遍历字典呢? 下面介绍两种方法: views.py代码如下: dicts = ...