Мое приложение состоит из стандартного диалогового окна и пары кнопок. Одна из кнопок должна открывать диалог выбора папки, поэтому я использовал IFileOpenDialog. Однако, когда это диалоговое окно открывается после создания основного диалогового окна, кнопки «Выбрать папку», «Отмена» и «X» не работают, как если бы никто не обрабатывал событие щелчка (навигация по файловой системе по-прежнему работает).
Пример минимальной воспроизводимости (компилируется с UNICODE):
Resource.r c
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_LTH)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOGEX 0, 0, 191, 52
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Browse...",IDC_BUTTON_BROWSE,71,19,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 184
TOPMARGIN, 7
BOTTOMMARGIN, 45
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_DIALOG1 AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Программа. cpp
#include <assert.h>
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <shobjidl_core.h>
#include <wrl.h>
#include "resource.h"
static void PickDirectory(HWND hwnd)
{
Microsoft::WRL::ComPtr<IFileDialog> folderPicker;
auto hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&folderPicker));
assert(SUCCEEDED(hr));
DWORD pickerOptions;
hr = folderPicker->GetOptions(&pickerOptions);
assert(SUCCEEDED(hr));
hr = folderPicker->SetOptions(pickerOptions | FOS_PICKFOLDERS);
assert(SUCCEEDED(hr));
if (SUCCEEDED(folderPicker->Show(hwnd)))
{
Microsoft::WRL::ComPtr<IShellItem> folderShellItem;
hr = folderPicker->GetResult(&folderShellItem);
assert(SUCCEEDED(hr));
PWSTR folderPath = nullptr;
hr = folderShellItem->GetDisplayName(SIGDN_FILESYSPATH, &folderPath);
assert(SUCCEEDED(hr));
OutputDebugStringW(L"Picked folder: ");
OutputDebugStringW(folderPath);
OutputDebugStringW(L"\r\n");
CoTaskMemFree(folderPath);
}
return;
}
static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON_BROWSE && HIWORD(wParam) == BN_CLICKED)
{
PickDirectory(hwnd); // <------- freezes!
return 0;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
int CALLBACK wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow)
{
auto hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
assert(SUCCEEDED(hr));
PickDirectory(nullptr); // <------- works!
auto hwnd = CreateDialogParamW(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, WndProc, 0);
assert(hwnd != nullptr);
ShowWindow(hwnd, nCmdShow);
PickDirectory(nullptr); // <------- freezes!
for (;;)
{
MSG msg;
auto getMessageResult = GetMessageW(&msg, nullptr, 0, 0);
if (getMessageResult == 0 || getMessageResult == -1)
break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
Примечание что средство выбора папок работает, прежде чем я создаю основной диалог приложения. После его создания он больше не работает.
Есть ли какой-нибудь секретный соус, который вы должны использовать при открытии IFileOpenDialog при использовании других диалогов?