Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

BROWSEINFO and pidlRoot

Elton Wells provided an excellent advice to choose/create a folder as shown at the end. However, when it runs, it always begins with the desktop. So I tried the following:

In the main function:
char buffer[_MAX_PATH];
_getcwd( buffer, _MAX_PATH )

In the function ChooseFolder :
bi.pidlRoot = (LPCITEMIDLIST)buffer;

Then, I get an error message "The folder cannot be used." Any advice would be appreciated. Thanks.

--- Elton's suggestion ---

static bool ChooseFolder(HWND hParent, const CString& title, CString& folder)
{
bool success = false;


BROWSEINFO bi;
::ZeroMemory(&bi, sizeof(bi));
LPTSTR pBuffer = folder.GetBuffer(MAX_PATH);


bi.hwndOwner = hParent;
bi.pszDisplayName = pBuffer;
b
i.lpszTitle = title;
bi.pidlRoot = 0;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;


LPITEMIDLIST pItem = ::SHBrowseForFolder(&bi);
if (pItem != NULL)
{
::SHGetPathFromIDList(pItem, pBuffer);
success = true;


CComPtr pMalloc;
if (SUCCEEDED(::SHGetMalloc(&pMalloc)))
pMalloc->Free(pItem);
}


folder.ReleaseBuffer();
return success;
}


Then you can use this function from your dialog class like this:


CString folder;
if (ChooseFolder(m_hWnd, _T("Choose a folder:"), folder))
MessageBox(folder);
0 Kudos
Message 1 of 5
(7,684 Views)
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
Message 2 of 5
(7,684 Views)
Elton, Thanks again for your help. When I compiled, however, I get 2 errors: (1)syntax error : identifier 'LPCT' and (2) missing '(' before identifier 'LPCT' I did updated the SDK last time and the last code did compile as a result. Is there any other update I need to perform? I do have included currently. Thanks in advance!
0 Kudos
Message 3 of 5
(7,684 Views)
Looks like something got messed up when I copied and pasted the code. The problem is with this line:

bi.lParam = reinterpret_cast<LPARAM>(static_cast<LPCTSTR>(startFolder));

Somehow an extra space was added - the LPCT STR part should be LPCTSTR. Try removing the space and recompiling.

- Elton
0 Kudos
Message 4 of 5
(7,684 Views)
GREAT! THANKS, ELTON!!!
0 Kudos
Message 5 of 5
(7,684 Views)