Reputation: 31
I'm currently customizing an Explorer-type custom dialog and I want to add a recent file combo box. I have already added the combo box the recent file items. I was also able to map them to their file path. But I'm having problems on changing the working directory of the explorer type dialog. Upon selecting a file on the combo box, I want the directory to change with the corresponding folder location of the selected file. See image attached.
// Get the index of the selected item in the combo box
const int iCmbIdx = CBGetCurSel(cOPEN_RECENTFILE_CMB);
if (iCmbIdx < 0) break; // Break if it is invalid
int iDefaultFileIndex = -1;
// Key - value pair
// Returns the index of the file saved in registry
int iFileIdx = lIndex.GetValue(iCmbIdx, iDefaultFileIndex);
if (iFileIdx < 0 ) break; // Index not found
// Build the folder path
tchar szItem[LSTR];
tchar szFilePath[LSTR];
tsprintf(szItem, TEXT("File%d"), iFileIdx);
LUserSettingGetString(TEXT("RecentFileList"), szItem, TEXT(""), szFilePath);
if (szFilePath[0] == 0) break;
LFile::GetFolderFromPath(szFilePath, szFilePath);
if (!SetCurrentDirectory(szFilePath)) {
LFDEBUG("SetCurrentDirectory failed (%d)\n", GetLastError());
break;
}
There are no errors in SetCurrentDirectory() call but the dialog will not go to the specified location. Is this the correct API to use to change the location of the folder?
This is the flags I used for the OPENFILENAME structure:
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
Upvotes: 1
Views: 388
Reputation: 101774
SetCurrentDirectory
is too low level, these dialogs use the shell namespace to navigate.
The classic open/save dialog API provides some messages to control it but changing the directory is not one of them. This leaves you with hacks like this:
void SetOpenSaveDlgFolderWithTextHack(HWND hTopDlg, LPCTSTR Path)
{
HWND hCtl = GetDlgItem(hTopDlg, 0x47C); // Combo
if (!hCtl) hCtl = GetDlgItem(hTopDlg, 0x480); // Old Edit
if (hCtl && *Path && (int)(INT_PTR) SendMessage(hCtl, WM_SETTEXT, 0, (SIZE_T) Path) > 0)
{
SendMessage(hTopDlg, WM_COMMAND, IDOK, (SIZE_T) GetDlgItem(hTopDlg, IDOK));
}
}
void SetOpenSaveDlgFolderWithShellBrowserHack(HWND hTopDlg, LPCTSTR Path)
{
UINT cwm_getishellbrowser = WM_USER + 7;
IShellBrowser *pSB, *pUnk = (IShellBrowser*) SendMessage(hTopDlg, cwm_getishellbrowser, 0, 0);
if (pUnk && SUCCEEDED(pUnk->QueryInterface(IID_IShellBrowser, (void**) &pSB)))
{
if (PIDLIST_ABSOLUTE pidl = ILCreateFromPath(Path))
{
pSB->BrowseObject(pidl, SBSP_ABSOLUTE);
ILFree(pidl);
}
pSB->Release();
}
else
{
SetOpenSaveDlgFolderWithTextHack(hTopDlg, Path);
}
}
To find hTopDlg
, use OFN_ENABLEHOOK
and call GetParent
on the HWND given to you in the hook proc for WM_NOTIFY:CDN_INITDONE.
As mentioned by Simon Mourier in the comments, the new dialogs added in Vista allows you to call IFileDialog::SetFolder
to change the current folder. The downside of this API is that you don't have full control of the dialog layout and you have to implement a COM object to catch events.
Upvotes: 1