The main issue is that, as indicated in the documentation, Windows' native file dialog doesn't support showing both files and directories when selecting directories only (check this other related answer too). For QFileDialog::FileMode::Directory
:
The name of a directory. Both files and directories are displayed. However, the native Windows file dialog does not support displaying files in the directory chooser.
One workaround is to use the non-native file dialog for this kind of selection, but, personally, it looks terrible if it has to live together other native file dialogs.
Here a quick comparison of two ways of selecting a directory, using the QFileDialog::getExistingDirectory
, manually by creating an instance of QFileDialog
, and by using native IFileDialog
:
#include <qapplication.h>
#include <qfiledialog.h>
#include <qdebug.h>
#include <Windows.h>
#include <shobjidl.h>
void using_IFileDialog()
{
IFileOpenDialog* pFileOpen;
HRESULT hr;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr)) {
// Show the Open dialog box.
pFileOpen->SetOptions(FOS_PICKFOLDERS | FOS_PATHMUSTEXIST);
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr)) {
IShellItem* pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr)) {
PWSTR pszFilePath;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED(hr)) {
MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
}
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
const auto dir_1 = QFileDialog::getExistingDirectory(nullptr, "getExistingDirectory (dirs only)");
qDebug() << dir_1;
QFileDialog dlg(nullptr, "QFileDialog::DontUseNativeDialog");
dlg.setFileMode(QFileDialog::Directory);
dlg.setOption(QFileDialog::DontUseNativeDialog);
if (dlg.exec() == QFileDialog::Accepted) {
const auto dir_2 = dlg.directory().absolutePath();
qDebug() << dir_2;
}
using_IFileDialog();
return 0;
}