These doesn't work because the pidlRoot member of the
BROWSEINFO struct is a
PIDL, not a string. A PIDL is a pointer to a structure that is used to identify objects in the Windows shell. You can get the PIDL for a given folder name via the
SHParseDisplayName function, but ultimately I don't think that this will do what you want since this would actually set the root folder for the browse dialog, which means that you would not be able to browse to folders above the specified folder - you would only be able to select the specified folder or subfolders of the specified folder.
The way to handle this is to specify a
BrowseCallbackProc callback function in the BROWSEINFO struct, then handle the BFFM_INITIALIZED message in the callback function to use the BFFM_SETSELECTION message to set the starting selected folder. Here is a modified version of the code from the
previous post about SHBrowseForFolder that demonstrates how to do this:
static int CALLBACK BrowseForFolderCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED)
{
LPCTSTR startFolder = reinterpret_cast<LPCTSTR>(lpData);
::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(startFolder));
}
return 0;
}
static bool ChooseFolder(HWND hParent, const CString& title, const CString& startFolder, CString& folder)
{
bool success = false;
BROWSEINFO bi;
::ZeroMemory(&bi, sizeof(bi));
LPTSTR pBuffer = folder.GetBuffer(MAX_PATH);
bi.hwndOwner = hParent;
bi.pszDisplayName = pBuffer;
bi.lpszTitle = title;
bi.pidlRoot = 0;
bi.lpfn = BrowseForFolderCallback;
bi.lParam = reinterpret_cast<LPARAM>(static_cast<LPCTSTR>(startFolder));
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
LPITEMIDLIST pItem = ::SHBrowseForFolder(&bi);
if (pItem != NULL)
{
::SHGetPathFromIDList(pItem, pBuffer);
success = true;
CComPtr<IMalloc> pMalloc;
if (SUCCEEDED(::SHGetMalloc(&pMalloc)))
pMalloc->Free(pItem);
}
folder.ReleaseBuffer();
return success;
}
Then if you wanted the dialog to start with the current directory, you could
call the function from your dialog class like this:
CString startFolder;
LPTSTR currentFolder = startFolder.GetBuffer(MAX_PATH);
::GetCurrentDirectory(MAX_PATH, currentFolder);
startFolder.ReleaseBuffer();
CString folder;
if (ChooseFolder(m_hWnd, _T("Choose a folder:"), startFolder, folder))
MessageBox(folder);
- Elton