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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12034943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:49:02  来源:igfitidea点击:

Win32 - Select Directory Dialog from C/C++

c++winapi

提问by Kirill Kobelev

How to select an existing folder (or create new) from a native Win32 application?

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

Here is a similar question. It has a good answer for C#/.NET. But I want the same thing for native Win32.

这是一个类似的问题。它对 C#/.NET 有很好的回答。但是我想要对原生 Win32 做同样的事情。

Anybody knows a solution, free code, etc?

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

Update:

更新:

I tried the function from the answer. Everything worked as expected, except it is necessary to call the SHGetPathFromIDListfunction to retrieve the name of selected directory. Here is a sample screen shot:

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

Example of the directory pickup dialog.

目录选取对话框的示例。

回答by peterchen

SHBrowseForFolder

SH浏览文件夹

Do your users a favor, and set at least the BIF_NEWDIALOGSTYLEflag.

帮您的用户一个忙,并至少设置BIF_NEWDIALOGSTYLE标志。

To set the initial folder, add the following code:

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

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;
...

and provide a suitable path (such as remembering the last selection, your applications data folder, or similar)

并提供合适的路径(例如记住上次选择、您的应用程序数据文件夹或类似路径)

回答by SparkyRobinson

Just as a go to for future users, this article helped me a lot with getting a directory dialog in C++

作为未来用户的参考,这篇文章对我在 C++ 中获取目录对话框有很大帮助

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

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

Here is my code (heavily based/taken on the article)

这是我的代码(主要基于/取自文章)

NOTE: You should be able to copy/paste this into a file / compile it (g++, see VS in ninja edit below) and it'll work.

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

#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;
}

EDIT:I've updated the code to show people how to remember the last selected path and use that.

编辑:我已经更新了代码以向人们展示如何记住最后选择的路径并使用它。

Also, for VS, using Unicode character set. replace this line:

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

const char * path_param = saved_path.c_str();

With this:

有了这个:

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

My Test code above is compiled with g++, but doing this fixed it in VS for me.

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

回答by GrayFace

For Windows Vista and above, it's best to use IFileOpenDialogwith the FOS_PICKFOLDERSoption for a proper open dialog rather than this tree dialog. See Common Item Dialogon MSDN for more details.

对于 Windows Vista 及更高版本,最好IFileOpenDialogFOS_PICKFOLDERS正确打开对话框的选项一起使用,而不是使用此树形对话框。有关更多详细信息,请参阅MSDN 上的公共项目对话框