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?