将 SHBrowseForFolder 和 struct BROWSEINFO 的使用更改为 - IFileOpenDialog
Posted
技术标签:
【中文标题】将 SHBrowseForFolder 和 struct BROWSEINFO 的使用更改为 - IFileOpenDialog【英文标题】:change the use of SHBrowseForFolder and struct BROWSEINFO TO - IFileOpenDialog 【发布时间】:2020-08-31 17:08:13 【问题描述】:直到现在——为了打开一个对话框,我使用了SHBrowseForFolder
函数。它会导致一些错误,我被告知使用IFileOpenDialog
。
这是我需要替换的代码:
bool wvFM::SelectFileSystemObjectDialogTree(const WCDialogCreationOptions& in_options,
WCDialogReply& out_Reply)
AUTO_FUNC_DEBUG;
DWORD osErr = NO_ERROR;
WTErr wtErr = eNoErr;
out_Reply.accept = false;
if(in_options.m_flags[WCDialogCreationOptions::eSelectFolder])
BROWSEINFO bi = 0;
bi.hwndOwner = (HWND)in_options.m_owner;
bi.pidlRoot = NULL; // TBD by callback BrowseCallbackProc
bi.lpszTitle = in_options.m_windowTitle.c_str();
bi.ulFlags = BIF_USENEWUI; // to enable pasting path
bi.lpfn = BrowseCallbackProc; // for initial dir option
WTPathString initialLocationPathString(
in_options.m_InitialDir.GetNativePathString());
bi.lParam = in_options.m_InitialDir.IsValid()
? (LPARAM)initialLocationPathString.c_str()
: NULL;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
// returns focus to the internal window of the plug
::SetFocus((HWND)in_options.m_owner);
if(pidl != NULL)
TCHAR szPath[MAX_PATH];
SHGetPathFromIDList(pidl, szPath);
out_Reply.m_filePathRef = wvFM::WCStPath((char*)szPath);
out_Reply.accept = true;
IMalloc* imalloc = 0;
if(SUCCEEDED(SHGetMalloc(&imalloc)))
imalloc->Free(pidl);
imalloc->Release();
return true;
我不太确定如何进行这种转换。 感谢任何愿意提供帮助的人!
【问题讨论】:
您似乎缺少函数的结尾。左大括号比右大括号多一个。 @danieloren 在尝试将此代码从SHBrowseForFolder()
转换为 IFileOpenDialog
时,您到底遇到了什么问题?到目前为止,您尝试过哪些不适合您的方法?
@TedLyngmo 因为有问题的代码侧重于设置了 eSelectFolder
标志的情况,因此您所指的“缺失”代码包含更多代码来处理以下情况eSelectFolder
未设置。
@RemyLebeau 可能是。原来的缩进让它看起来好像真的不见了。
@danieloren "[SHBrowseForFolder] 导致一些错误" - 究竟是什么错误?
【参考方案1】:
您显然正在使用具有某种自定义字符串类型的 3rd 方库,但您没有提供有关该字符串类型实际是什么的任何详细信息。我猜测字符串类型是基于char
的,因为您在将SHGetPathFromIDList()
的结果分配给out_Reply.m_filePathRef
时将其类型转换为char*
,所以您很可能使用UNICODE
undefined 编译您的项目,以便TCHAR
映射到char
而不是wchar_t
。在这种情况下,SHBrowseForFolder()
将调用SHBrowseForFolderA()
而不是SHBrowseForFolderW()
。
IFileOpenDialog
根本不处理 ANSI 字符串,只处理 UNICODE 字符串,因此您必须根据需要在 3rd 方字符串类型和 Windows UTF-16 字符串之间来回转换。
SHBrowseForFolder()
到 IFileOpenDialog
的转换大致如下所示(其中 toWString()
中的 YourStringType
是第 3 方字符串类型 - 在指示的地方进行所需的任何调整) :
std::wstring toWString(const YourStringType &str)
const char pStr = ... pointer to str's characters ...;
int sLen = ... length of str in chars, not counting the null terminator ...;
std::wstring ws;
int wLen = MultiByteToWideChar(CP_ACP, 0, pStr, slen, NULL, 0);
if (wLen > 0)
ws.resize(wLen);
MultiByteToWideChar(CP_ACP, 0, pStr, sLen, ws.data(), wLen);
return ws;
std::string toString(const wchar_t *ws)
std::string s;
int wLen = lstrlenW(s);
int sLen = WideCharToMultiByte(CP_ACP, 0, ws, wLen, NULL, 0, NULL, NULL);
if (sLen > 0)
s.resize(sLen);
WideCharToMultiByte(CP_ACP, 0, ws, wLen, s.data(), sLen, NULL, NULL);
return s;
IShellItem* toShellItem(const YourStringType &path)
IShellItem *pItem = NULL;
if (FAILED(SHCreateItemFromParsingName(toWString(path).c_str(), NULL, IID_PPV_ARGS(&pItem))))
pItem = NULL;
return pItem;
bool wvFM::SelectFileSystemObjectDialogTree(const WCDialogCreationOptions& in_options,
WCDialogReply& out_Reply)
AUTO_FUNC_DEBUG;
out_Reply.accept = false;
if (in_options.m_flags[WCDialogCreationOptions::eSelectFolder])
IFileOpenDialog *pFileOpen = NULL;
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pFileOpen))))
return false;
FILEOPENDIALOGOPTIONS opts = 0;
pFileOpen->GetOptions(&opts);
pFileOpen->SetTitle(toWString(in_options.m_windowTitle).c_str());
pFileOpen->SetOptions(opts | FOS_PICKFOLDERS);
IShellItem *pItem = toShellItem(in_options.m_InitialDir);
if (pItem)
pFileOpen->SetFolder(pItem);
pItem->Release();
HWND hwndOwner = (HWND) in_options.m_owner;
HRESULT hr = pFileOpen->Show(hwndOwner);
::SetFocus(hwndOwner);
if (SUCCEEDED(hr))
if (SUCCEEDED(pFileOpen->GetResult(&pItem)))
PWSTR pszFilePath;
if (SUCCEEDED(pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath)))
out_Reply.m_filePathRef = wvFM::WCStPath(toString(pszFilePath).c_str());
out_Reply.accept = true;
CoTaskMemFree(pszFilePath);
pItem->Release();
pFileOpen->Release();
return true;
...
【讨论】:
以上是关于将 SHBrowseForFolder 和 struct BROWSEINFO 的使用更改为 - IFileOpenDialog的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 .str 和 .split 将 pandas 代码转换为 Pyspark
R语言使用str_split函数和str_split_fixed函数将字符串分割(分裂split)成几个部分:str_split函数使用指定的字符或者字符串分割字符串str_split_fixed