SetThemeAppProperties отключает общие диалоги COM

Призвание SetThemeAppProperties с аргументом, который имеет флаг STAP_ALLOW_CONTROLS неустановленные причины CoCreateInstance для общих диалогов (или в списке открытия файла, CLSID_FileOpenDialog) вернуть ошибку 0x80040111,

Пример кода следующий:

HRESULT hResult;
CComPtr< IFileOpenDialog > pFileOpenInterface1;
CComPtr< IFileOpenDialog > pFileOpenInterface2;

hResult = ::CoCreateInstance( CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &pFileOpenInterface1 ) );
::SetThemeAppProperties( 0 );
hResult = ::CoCreateInstance( CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &pFileOpenInterface2 ) );

Чтобы превратить его в работающий код, я создал (в Visual Studio 2010 Professional) простое приложение с графическим интерфейсом Win32 и добавил этот код в меню "Справка | Об обработчике".

Почему так и как обойти эту проблему?

3 ответа

Отключение визуальных стилей на всех элементах управления - довольно тяжелый молот. Не удивительно, что последняя версия диалогов не поддерживает это. Попробуйте вернуться к устаревшему диалоговому интерфейсу оболочки с помощью GetOpenFileName(). Затем удалите запись манифеста, которая включает версию 6.0 общих элементов управления. Возможно, немного анафема идее снятия шкуры.

Может быть, глупый вопрос: но вы вызываете InitCommonControlsEx() и CoInitializeEx(), прежде чем пытаться использовать CoCreateInstance?

Я предполагаю, что ваш вызов SetThemeAppProperties инициализирует COM автоматически, если установлен флаг STAP_ALLOW_CONTROLS. Но вы должны сделать это самостоятельно, если этот флаг не установлен.

Используя шаблоны для настройки общего диалога, в Windows 7 это не так просто. Сначала нужно заставить GetOpenFileName вызывать устаревшую функцию из DoModal, что можно легко сделать с помощью m_bVistaStyle = false. Но чем мне пришлось иметь дело с каким-то утверждением

ASSERT (pThreadState-> m_pAlternateWndInit == NULL);
pThreadState-> m_pAlternateWndInit = NULL;

Я до сих пор не уверен, для чего это нужно, но это может быть "работа, основанная" на обработке WM_NCDESTROY и простом назначении

_AFX_THREAD_STATE * pThreadState = AfxGetThreadState ();
if (:: IsWindow (pThreadState-> m_pAlternateWndInit-> m_hWnd))
TRACE ("страшно...");
еще
pThreadState-> m_pAlternateWndInit = NULL;
TRACE ("WM_NCDESTROY");
вернуть ложь;

в оконной процедуре. Однако мне не удалось получить выбранные имена файлов из диалога OpenFile на CDN_SELCHANGE. Отправка CDM_GETFILEPATH возвращает только 256 символов, независимо от того, насколько большой буфер используется с этим сообщением. Может быть, кто-нибудь знает способ сделать это на Windows 7?

Другие вопросы по тегам