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 и добавил этот код в меню «Справка | Об обработчике».

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


person Adam Badura    schedule 11.03.2011    source источник
comment
Я опубликовал это после отсутствия активности в исходном сообщении на форумах MSDN (social.msdn.microsoft.com/Forums/en-US/)   -  person Adam Badura    schedule 11.03.2011
comment
может помочь, если вы объясните, почему, где и когда вы вызываете SetThemeAppProperties   -  person David Heffernan    schedule 11.03.2011
comment
В оригинальном приложении он вызывается при запуске в модуле, предоставляющем собственный скин для приложения. (Как обычно, у меня не так много вариантов с этим, и, честно говоря, я не уверен, почему модуль вообще вызывает эту функцию.) Но проблема кажется более общей, поскольку то же самое происходит в примере приложения (как описано в вопросе) .   -  person Adam Badura    schedule 11.03.2011
comment
что произойдет, если вы добавите этот флаг обратно?   -  person David Heffernan    schedule 11.03.2011
comment
Затем успешно выполняется второй экземпляр CoCreateInstance.   -  person Adam Badura    schedule 11.03.2011


Ответы (2)


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

person Hans Passant    schedule 11.03.2011
comment
GetOpenFileName будет использовать диалог нового общего элемента. Вам придется убедить его использовать устаревший диалог, например, используя одну из старых версий OPENFILENAME. - person David Heffernan; 11.03.2011
comment
@ Дэвид - я уверен, что это не так. Общеизвестно, что WPF в версии 3.5 получает расширенный диалог, отличный от Vista, потому что он использует GetOpenFileName(). Он был обновлен в 4.0 для использования IFileDialog. - person Hans Passant; 11.03.2011
comment
@Hans GetOpenFileName() действительно дает новый диалог, если вы используете его правильно. Пока вам не нужна настройка, вы можете получить новые диалоги через старые вызовы функций. Только когда вам нужна настройка, вы вынуждены использовать новый COM-интерфейс. - person David Heffernan; 11.03.2011
comment
Проблема в том, что мы добавляем настраиваемые элементы управления в диалог (флажок), и это легко делается с новым диалогом COM, в то время как старые диалоги требовали некоторого недокументированного взлома для этого (если я не ошибаюсь). К тому же они выглядели некрасиво. - person Adam Badura; 11.03.2011
comment
@Adam Настройка старых диалогов задокументирована и использует шаблоны диалогов. Они уродливы, и вы правы, что избегаете их. Ваша проблема в коде скина. Это нарыв, который вы должны вскрыть. - person David Heffernan; 11.03.2011
comment
@David Heffernan Да, модуль скинов, который мы используем, проблематичен. Но, к сожалению, он должен остаться, и теперь уже некому его хотя бы поддерживать. Спасибо за совет с шаблонами. - person Adam Badura; 11.03.2011

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

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

person Stefan    schedule 11.03.2011
comment
Я подозревал, что это не сработает, но попробовал, тем не менее надеясь, что сработает. Но это не так. Подсказка заключается в том, что первый вызов CoCreateInstance всегда завершается успешно. - person Adam Badura; 11.03.2011