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)的更多相关文章

  1. 关于WPF中文件夹浏览对话框的方式

    文件夹浏览时dialogresult要写全引用路径 string path=null; FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd ...

  2. FolderBrowserDialog(文件夹浏览对话框)

    1.选择数据库目录,在此处不需要新建文件夹,因此屏蔽新建文件夹按钮. C#代码 FolderBrowserDialog df = new FolderBrowserDialog(); //设置文件浏览 ...

  3. 清除Windows 10的文件夹浏览痕迹

    windows 10有一个功能就是在快速访问时显示“最近访问的文件”,“常用文件”.如果是一台共用电脑,这个功能会经常暴露自己的“行踪”. 可以在“文件夹选项”-“隐私”中去掉勾选,并点击“清除”来清 ...

  4. WPF中弹出文件夹浏览对话框

    附一个共享目录正则表达式判断: bool result= System.Text.RegularExpressions.Regex.IsMatch("\\pc-test\share" ...

  5. 在WPF中调用文件夹浏览/选择对话框

    var dialog = new System.Windows.Forms.FolderBrowserDialog(); System.Windows.Forms.DialogResult resul ...

  6. MFC 使用MFC EditBrowse Control控件选择文件或者文件夹

    从工具箱中拖拽一个MFC EditBrowse Control到窗体中, 通过设置“Browse Mode”属性指定“文件浏览”还是“文件夹浏览” 可以通过添加对象的方式将其与一个CString se ...

  7. MFC 如何创建浏览文件夹的对话框

    如何创建浏览文件夹的对话框 如何创建浏览文件夹的对话框 CString CXXXXDlg::GetOpenfolderPath() { BROWSEINFO bi; ZeroMemory(&b ...

  8. C#利用浏览按钮获得文件路径和文件夹路径

    生成文件夹路径 private void btnChoose_Click(object sender, EventArgs e) {            using (OpenFileDialog ...

  9. atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php

    atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...

随机推荐

  1. HDU:1269-迷宫城堡(tarjan模板)

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Descri ...

  2. Tarjan算法及其应用

    Tarjan算法及其应用 引入 tarjan算法可以在图上求解LCA,强连通分量,双联通分量(点双,边双),割点,割边,等各种问题. 这里简单整理一下tarjan算法的几个应用. LCA http:/ ...

  3. [转]mysql Access denied for user 'root'@'localhost' 问题的解决方法

    解决方案如下: # /etc/init.d/mysql stop # mysqld_safe --user=mysql --skip-grant-tables --skip-networking &a ...

  4. tomcat6-servlet规范对接 与 ClassLoader隔离

    之前写的一个ppt 搬到博客来

  5. day01_13.数组

    数组基本语法 <?php $a = array(键1=>值1,键2=>值2); ?> <?php $arr = array(1=>'张三的裤子',2=>'李四 ...

  6. [git 学习篇] 创建公钥

    http://riny.net/2014/git-ssh-key/ 1 安装 windows gitbash    msysgit是Windows版的Git,从https://git-for-wind ...

  7. [Uiautomator篇][2] UiDeviceAPI介绍

    1 https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html  http://www.cnb ...

  8. poj 2195 最小费用最大流模板

    /*Source Code Problem: 2195 User: HEU_daoguang Memory: 1172K Time: 94MS Language: G++ Result: Accept ...

  9. php rabbitmq操作类及生产者和消费者实例代码 转

    注意事项: 1.accept.php消费者代码需要在命令行执行 2.'username'=>'asdf','password'=>'123456' 改成自己的帐号和密码 RabbitMQC ...

  10. eclipse Java EE安装和web项目的创建

    一.根据http://www.itnose.net/detail/6139800.html基本安装成功二.根据http://www.cnblogs.com/freebsd-pann/archive/2 ...