如何从SHBrowseForFolder函数获取完整路径?

时间:2009-12-23 15:11:17

标签: c++ c windows

我正在使用SHBrowseForFolder和SHGetPathFromIDList函数来获取用户选择的文件夹路径。但是,此方法不会返回完整路径的驱动路径。如何另外获取该信息?

1 个答案:

答案 0 :(得分:5)

取自此新闻组post

你可以使用SHBrowseForFolder(...),它将BROWSEINFO作为参数;

TCHAR szDir[MAX_PATH];
BROWSEINFO bInfo;
bInfo.hwndOwner = Owner window
bInfo.pidlRoot = NULL; 
bInfo.pszDisplayName = szDir; // Address of a buffer to receive the display name of the folder selected by the user
bInfo.lpszTitle = "Please, select a folder"; // Title of the dialog
bInfo.ulFlags = 0 ;
bInfo.lpfn = NULL;
bInfo.lParam = 0;
bInfo.iImage = -1;

LPITEMIDLIST lpItem = SHBrowseForFolder( &bInfo);
if( lpItem != NULL )
{
  SHGetPathFromIDList(lpItem, szDir );
  //......
}

SHBrowseForFolder 返回文件夹的PIDL及其显示名称,以获取PIDL的完整路径,调用 SHGetPathFromIDList

编辑: OP似乎无法使其正常工作,所以这里有一些有效的C#代码(您应该能够将其翻译成任何语言,API都是相同的):

class SHGetPath
{
    [DllImport("shell32.dll")]
    static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);

    [DllImport("shell32.dll")]
    public static extern Int32 SHGetPathFromIDList(
    IntPtr pidl, StringBuilder pszPath);

    public delegate int BrowseCallBackProc(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp);
    struct BROWSEINFO 
    {
        public IntPtr hwndOwner;
        public IntPtr pidlRoot;
        public string pszDisplayName;
        public string lpszTitle;
        public uint ulFlags;
        public BrowseCallBackProc lpfn;
        public IntPtr lParam;
        public int iImage;
    }

    public SHGetPath()
    {
        Console.WriteLine(SelectFolder("Hello World", "C:\\"));
    }

    public string SelectFolder(string caption, string initialPath)
    {
        StringBuilder sb = new StringBuilder(256);
        IntPtr pidl = IntPtr.Zero;
        BROWSEINFO bi;
        bi.hwndOwner = Process.GetCurrentProcess().MainWindowHandle; ;
        bi.pidlRoot = IntPtr.Zero;
        bi.pszDisplayName = initialPath;
        bi.lpszTitle = caption;
        bi.ulFlags = 0; // BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
        bi.lpfn = null; // new BrowseCallBackProc(OnBrowseEvent);
        bi.lParam = IntPtr.Zero;
        bi.iImage = 0;

        try
        {
            pidl = SHBrowseForFolder(ref bi);
            if (0 == SHGetPathFromIDList(pidl, sb))
            {
                return null;
            }
        }
        finally
        {
            // Caller is responsible for freeing this memory.
            Marshal.FreeCoTaskMem(pidl);
        }
        return sb.ToString();
    }
}