Win32 - 从C / C ++中选择目录对话框

时间:2012-08-20 09:10:57

标签: c++ winapi

如何从本机Win32应用程序中选择现有文件夹(或创建新文件夹)?

Here is a similar question。它对C#/ .NET有很好的答案。但是对于原生的Win32我想要同样的东西。

有人知道解决方案,免费代码等吗?

更新

我从答案中尝试了这个功能。一切都按预期工作,除了必须调用SHGetPathFromIDList函数来检索所选目录的名称。以下是一个示例屏幕截图:

Example of the directory pickup dialog.

3 个答案:

答案 0 :(得分:18)

SHBrowseForFolder

帮助您的用户,并至少设置BIF_NEWDIALOGSTYLE标记。

要设置初始文件夹,请添加以下代码:

static int CALLBACK BrowseFolderCallback(
                  HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    if (uMsg == BFFM_INITIALIZED) {
        LPCTSTR path = reinterpret_cast<LPCTSTR>(lpData);
        ::SendMessage(hwnd, BFFM_SETSELECTION, true, (LPARAM) path);
    }
    return 0;
}

// ...
BROWSEINFO binf = { 0 };
...
binf.lParam = reinterpret_cast<LPARAM>(initial_path_as_lpctstr); 
binf.lpfn = BrowseFolderCallback;
...

并提供合适的路径(例如记住最后一个选择,您的应用程序数据文件夹或类似文件)

答案 1 :(得分:11)

对于未来的用户来说,这篇文章对于在C ++中获取目录对话框帮助了我很多

http://www.codeproject.com/Articles/2604/Browse-Folder-dialog-search-folder-and-all-sub-fol

这是我的代码(严重依据/文章)

注意:您应该能够将其复制/粘贴到文件中/编译它(g ++,请参阅下面的ninja编辑中的VS),它会起作用。

#include <windows.h>
#include <string>
#include <shlobj.h>
#include <iostream>
#include <sstream>

static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg, LPARAM lParam, LPARAM lpData)
{

    if(uMsg == BFFM_INITIALIZED)
    {
        std::string tmp = (const char *) lpData;
        std::cout << "path: " << tmp << std::endl;
        SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
    }

    return 0;
}

std::string BrowseFolder(std::string saved_path)
{
    TCHAR path[MAX_PATH];

    const char * path_param = saved_path.c_str();

    BROWSEINFO bi = { 0 };
    bi.lpszTitle  = ("Browse for folder...");
    bi.ulFlags    = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
    bi.lpfn       = BrowseCallbackProc;
    bi.lParam     = (LPARAM) path_param;

    LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );

    if ( pidl != 0 )
    {
        //get the name of the folder and put it in path
        SHGetPathFromIDList ( pidl, path );

        //free memory used
        IMalloc * imalloc = 0;
        if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
        {
            imalloc->Free ( pidl );
            imalloc->Release ( );
        }

        return path;
    }

    return "";
}

int main(int argc, const char *argv[])
{
    std::string path = BrowseFolder(argv[1]);
    std::cout << path << std::endl;
    return 0;
}

编辑:我已更新代码,向人们展示如何记住上次选择的路径并使用它。

另外,对于VS,使用Unicode字符集。替换这一行:

const char * path_param = saved_path.c_str();

有了这个:

std::wstring wsaved_path(saved_path.begin(),saved_path.end());
const wchar_t * path_param = wsaved_path.c_str();

我的上面的测试代码是用g ++编译的,但这样做会在我的VS中修复它。

答案 2 :(得分:2)

对于Windows Vista及更高版本,最好将IFileOpenDialogFOS_PICKFOLDERS选项一起使用,以正确打开对话框而不是树形对话框。有关更多详细信息,请参见MSDN上的Common Item Dialog