Reputation: 1315
I'm using Winapi's function SHBrowseForFolder
and I need to set a default folder for browsing. To achieve that, I need to get the desired default folder's "PIDL". I can get the "PIDL" using this function: SHGetFolderLocation(hwnd, nCSIDL, NULL, NULL, &pidlRoot);
but as you can see, the second parameter is another identifier "nCSIDL" (type int).
How can I get a path's indentifier by path (LPCSTR)?
This is my code:
TCHAR szDir[MAX_PATH];
BROWSEINFO bInfo;
HWND hwnd = ObPanelAPI::GetPanelHandleByName("*Current");
bInfo.hwndOwner = hwnd;
bInfo.pszDisplayName = szDir;
bInfo.lpszTitle = "Seleccionar directorio"; //Dialog title
bInfo.ulFlags = 0 ;
bInfo.lpfn = NULL;
bInfo.lParam = 0;
bInfo.iImage = -1;
//Default folder set
LPITEMIDLIST pidlRoot = NULL;
//*******I NEED TO GET nCSIDL HERE********
SHGetFolderLocation(hwnd, nCSIDL, NULL, NULL, &pidlRoot);
bInfo.pidlRoot = pidlRoot;
LPITEMIDLIST lpItem = SHBrowseForFolder(&bInfo);
Upvotes: 0
Views: 1762
Reputation: 597951
I'm using Winapi's function
SHBrowseForFolder
and I need to set a default folder for browsing. To achieve that, I need to get the desired default folder's "PIDL".
First, you need to differentiate something here. BROWSEINFO
has a pidlRoot
field, which specifies the top-most folder that the browse dialogs displays. A user cannot select items above that folder. This is NOT the same thing as a "default folder", which is just the folder that is initially selected within the chosen root when the dialog appears.
To set a "default folder", you actually do not need a PIDL, you can use a path string instead (the dialog accepts both). Assign a pointer to the path string to the BROWSEINFO.lParam
field and provide a callback function in the BROWSEINFO.lpfn
field. Inside the callback, when it receives the BFFM_INITIALIZED
notification, it can send the dialog a BFFM_SETSELECTION
message, setting the wParam
parameter to TRUE and setting the lParam
parameter to the path string pointer. This is documented on MSDN:
BFFM_SETSELECTION
Specifies the path of a folder to select. The path can be specified as a string or a PIDL.
Now, with that said, the BROWSEINFO.pidlRoot
field requires a PIDL, and the BFFM_SETSELECTION
message does accept a PIDL as input, so...
I can get the "PIDL" using this function:
SHGetFolderLocation(hwnd, nCSIDL, NULL, NULL, &pidlRoot);
but as you can see, the second parameter is another identifier "nCSIDL" (type int).
That function is for retrieving PIDLs for special folders that are pre-defined by Microsoft, like Documents, AppData, User Profiles, etc. These are identified by constant CSIDL
values (and KNOWNFOLDERID
values on Vista+) which are consistent on every Windows version, though the particular paths may differ from one system to another based on user configuration.
How can I get a path's indentifier by path (LPCSTR)?
There are a few different ways:
IShellFolder::ParseDisplayName()
. Call SHGetDesktopFolder()
to get the IShellFolder
for the Shell namespace root, and then call its ParseDisplayName()
to parse the path.
SHParseDisplayName()
. Similar to above, but with some additional options available. Do be aware of the following note in the documentation, though:
You should call this function from a background thread. Failure to do so could cause the UI to stop responding.
ILCreateFromPath()
. However, it has been observed that ILCreateFromPath()
does not always return the same PIDLs that IShellFolder::ParseDisplayName()
/SHParseDisplayName()
return, that sometimes that difference can cause things like SHBrowseForFolder()
to behave incorrectly. I have not personally experienced this, but other people claim they have. You will just have to try it for yourself.
Upvotes: 4