When I try to instantiate a CFileDialog
object it shows both the folders and files. How do you create a CFileDialog
that browses for folders alone?
7 Answers
It is very simple, really.
Use CFolderPickerDialog
which is derived from the class CFileDialog
!

- 18,086
- 12
- 59
- 105

- 191
- 1
- 2
-
1This class exists starting from Visual Studio 2010. we've just switched from VS2008 to VS2013, and IFileOpenDialog::SetOptions(FOS_PICKFOLDERS) surprisingly stopped working. IMHO it's against backward compatibility. – blackbada_cpp Dec 10 '15 at 14:38
You can't do it with CFileDialog
.
Either you will use SHBrowseForFolder Function or a wrapper for it,
like CFolderDialog - Selecting Folders.

- 42,588
- 16
- 104
- 136
-
4`SHBrowseForFolder` is heavily outdated. From the remarks: _"For Windows Vista or later, it is recommended that you use IFileDialog with the FOS_PICKFOLDERS option rather than the SHBrowseForFolder function. This uses the Open Files dialog in pick folders mode and is the preferred implementation."_ – zett42 May 24 '18 at 12:27
-
You actually can, if you are willing to reimplement `CFileDialog` - see [here](https://stackoverflow.com/a/66049570/10571377). – Juv Feb 04 '21 at 16:25
-
@Juv, the question is about displaying in the dialog only the folders. – Nick Dandoulakis Feb 04 '21 at 20:11
Like someone mentioned, use CFolderPickerDialog which works great. I would like to give you example how to use it especially when using the multi select flag:
CFolderPickerDialog folderPickerDialog(initialFolder, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING, this,
sizeof(OPENFILENAME));
CString folderPath;
if (folderPickerDialog.DoModal() == IDOK)
{
POSITION pos = folderPickerDialog.GetStartPosition();
while (pos)
{
folderPath = folderPickerDialog.GetNextPathName(pos);
}
}

- 6,789
- 10
- 48
- 67
Starting from Vista it's recommended to use IFileDialog with the FOS_PICKFOLDERS option (see msdn):
CFileDialog od(TRUE/*bOpenFileDialog*/, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT , NULL, NULL, 0,
TRUE/*bVistaStyle*/);
IFileOpenDialog * openDlgPtr = od.GetIFileOpenDialog();
if ( openDlgPtr != NULL )
{
openDlgPtr->SetOptions(FOS_PICKFOLDERS);
openDlgPtr->Release();
}
od.DoModal();

- 422
- 4
- 11
-
2Starting Visual Studio 2010 this will not work. Use CFolderPickerDialog instead (https://msdn.microsoft.com/ru-ru/library/dd795962%28v=vs.120%29.aspx) – blackbada_cpp Dec 10 '15 at 14:36
starting from windows vista,you can use the Common Item Dialog .
void CQiliRegrvDlg::OnBnClickedSelectDir()
{
HRESULT hr = S_OK;
// Create a new common open file dialog.
IFileOpenDialog *pfd = NULL;
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{
// Set the dialog as a folder picker.
DWORD dwOptions;
hr = pfd->GetOptions(&dwOptions);
if (SUCCEEDED(hr))
{
hr = pfd->SetOptions(dwOptions | FOS_PICKFOLDERS);
}
// Set the title of the dialog.
if (SUCCEEDED(hr))
{
hr = pfd->SetTitle(L"Folder");
}
// Show the open file dialog.
if (SUCCEEDED(hr))
{
hr = pfd->Show(m_hWnd);
if (SUCCEEDED(hr))
{
// Get the selection from the user.
IShellItem *psiResult = NULL;
hr = pfd->GetResult(&psiResult);
if (SUCCEEDED(hr))
{
PWSTR pszPath = NULL;
hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
if (SUCCEEDED(hr))
{
m_appDir = pszPath;
SetDlgItemText(IDC_STATIC, m_appDir);
CoTaskMemFree(pszPath);
}
psiResult->Release();
}
}
}
pfd->Release();
}
}

- 640
- 9
- 21
Seems to me the answer you are asking for is inside the code of
CMFCPropertyGridFileProperty::OnClickButton(CPoint /*point*/)
of the
<Your Visual Studio installation folder>\VC\atlmfc\src\mfc\afxpropertygridctrl.cpp
file.
If you do not have access to the code, I will post the essential part of it:
CString strPath = m_varValue.bstrVal;
BOOL bUpdate = FALSE;
if (m_bIsFolder)
{
if (afxShellManager == NULL)
{
CWinAppEx* pApp = DYNAMIC_DOWNCAST(CWinAppEx, AfxGetApp());
if (pApp != NULL)
{
pApp->InitShellManager();
}
}
if (afxShellManager == NULL)
{
ASSERT(FALSE);
}
else
{
bUpdate = afxShellManager->BrowseForFolder(strPath, m_pWndList, strPath);
}
}
else
{
CFileDialog dlg(m_bOpenFileDialog, m_strDefExt, strPath, m_dwFileOpenFlags, m_strFilter, m_pWndList);
if (dlg.DoModal() == IDOK)
{
bUpdate = TRUE;
strPath = dlg.GetPathName();
}
}
As you see, Microsoft itself does not use the Cfiledialog class when wants to open a dialog for picking folders.
For using code like that, your application class MUST be derived from CWinAppEx, not CWinApp

- 4,122
- 4
- 47
- 81
Actually there is a way to do this - I found it in codeguru: "Selected files and folders in CFileDialog"
If you are willing to make your own implementation of CFileDialog such as:
class CMyFileDialog : public CFileDialog
You can add the following code and it should work (It is slightly different from the codeguru example):
// This code overrides the OnNotify message of the CFileDialog
// and catches the CDN_SELCHANGE, this way you can also do
// something with the selected folders.
BOOL CMyFileDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
NMHDR* pNotificationParam = (NMHDR*)lParam;
// Check that we got to the selection change notification.
int code = pNotificationParam->code;
if (code == CDN_SELCHANGE)
{
CStringArray theSelection;
GetListControllSelectedItems(theSelection);
// Do as you want with theSelection.
}
return CFileDialog::OnNotify(wParam, lParam, pResult);
}
// The following Code is accessing the selection in the CFileDialog
// and filling a string array with the selected names
BOOL CMyFileDialog::GetListControllSelectedItems(CStringArray& selectedItemNames)
{
BOOL rc = FALSE;
// Get the list control of the file dialog.
CWnd* pParentWnd = GetParent();
CWnd* pListControlWnd = pParentWnd->GetDlgItem(lst2);
if (pListControlWnd) {
// Get the selection from the list control.
CListCtrl* pListCtrl = (CListCtrl*)(pListControlWnd->GetDlgItem(1));
UINT selectionCount = pListCtrl->GetSelectedCount();
// When there are items selected.
if (selectionCount) {
rc = TRUE;
selectedItemNames.RemoveAll();
POSITION itemPos = pListCtrl->GetFirstSelectedItemPosition();
while (itemPos != NULL)
{
int itemNum = pListCtrl->GetNextSelectedItem(itemPos);
CString currentItemName = pListCtrl->GetItemText(itemNum, 0);
selectedItemNames.Add(currentItemName);
}
}
}
return rc;
}
Note: In CFileDialog::OnFileNameChange
of the Microsoft MFC documentation they actually do hint toward this solution, but without elaborating too much.
I had a problem in my very old, legacy code, where I have a customized file dialog that actually needs to save a folder!!!
After twenty two years of hardship and pain, my code is now complete...

- 744
- 7
- 12