TSaveDialog не с клиента визуальные стили отключены

Я пытаюсь использовать TSaveDialog в Делфи версии XE6:

if not SaveDialog1.Execute(0) then
   Exit;

вызов немедленно возвращает false, без отображения диалогового окна. Я проследил его до акта создания диалогового окна сохранения оболочки COM-объекта:

function TCustomFileSaveDialog.CreateFileDialog: IFileDialog;
var
       LGuid: TGUID;
begin
  LGuid := CLSID_FileSaveDialog;

  CoCreateInstance(LGuid, nil, CLSCTX_INPROC_SERVER,
    StringToGUID(SID_IFileSaveDialog), Result);
end;

вызов CoCreateInstance не в состоянии. Я создал минимальный код для воспроизведения проблемы:

procedure TForm1.Button1Click(Sender: TObject);
const
   CLSID_FileSaveDialog: TGUID = '{C0B4E2F3-BA21-4773-8DBA-335EC946EB8B}';
begin
   CreateComObject(CLSID_FileSaveDialog);
end;

выдает EOleSysError исключения:

0x80040111: ClassFactory не удается предоставить запрошенный класс, ClassID: {C0B4E2F3-BA21-4773-8DBA-335EC946EB8B}

Мои приложения is используя версию 6 библиотеки Common Controls (6.0.7601.18837), но я понял, что это происходит только в том случае, если пользователь отключил визуальные стили для моего приложения:

enter image description here

мы все еще используем версию 6 библиотеки common controls, только это IsAppThemed возвращает false.

Примечание: я знаю, что многие люди ошибочно считают, что:

  • API визуальных стилей работает только в том случае, если у нас есть версия 6 Comctrl32.библиотеки DLL, загружаемой
  • если версия 6 Comctrl32.dll загружается, затем API визуальных стилей будет работать
  • если мы не используем ComCtrl v6, то это означает, что визуальные стили отключены
  • визуальные стили отключены, если мы используем старую библиотеку общих элементов управления

силовое решение установить глобальный UseLatestCommonDialogs значение false.

но это довольно плохо, так как это относится только к людям, которые отключили визуальные стили в своем приложении:

  • диалог продолжает работать в ОС без визуальных стилей (например, Windows Server 2008 R2)
  • диалог продолжает работать с отключенными визуальными стилями (например, Windows 7 с визуальными стилями выключен)

это означает, что я не могу просто использовать IsAppThemed, так как это также возвращает false if IsThemeActive ложно.

| IsThemeActive | IsAppThemed | Disable visual styles | Result    |
|---------------|-------------|-----------------------|-----------|
| True          | True        | Unchecked             | Works     |
| True          | False       | Checked               | Fails     |
| False         | False       | Unchecked             | Works     |
| False         | False       | Checked               | Fails     |

то, что я думаю, я спрашиваю Как проверить статус Disble Визуальные Стили флаг compat.

что я действительно спрашиваю, Так это как сделать TSaveDialog правильно работать в Delphi (не подразумевая, что чтение флага compat является частью решения).

1 ответов


вы, конечно, не хотите тестировать флаг compat. Если вы собираетесь протестировать, вы хотите проверить, что контролирует этот флаг. В этом случае используются или нет темы. Если вы собираетесь проверить это, то вы должны использовать диалоги стиля Vista, когда выполняется следующее условие:

IsWindowsVistaOrGreater and Winapi.UxTheme.InitThemeLibrary and Winapi.UxTheme.UseThemes

в противном случае вам нужно использовать старые диалоги стиля XP. Вы можете сделать это с помощью следующего кода:

UseLatestCommonDialogs := IsWindowsVistaOrGreater and Winapi.UxTheme.InitThemeLibrary 
  and Winapi.UxTheme.UseThemes;

проблема с этим состоит в том, что вы будете отключите диалоги нового стиля, когда пользователь работает с темой Windows Classic. Чего, я уверен, вы не хотите.

так можно взять функциональность подхода. Это попытка использовать новые диалоговые окна стиля и резервный вариант в старом диалоговом окне стиля, если новый не удается. Итак, попробуйте создать IFileSaveDialog. Назначить UseLatestCommonDialogs на основе того, удастся ли это или нет.


С другой стороны, этот параметр совместимости предназначен для использования в приложениях, которые не работать правильно, когда темы включены. Ваше приложение работает правильно по темам, и я думаю, что для вас вполне оправданно говорить, что ваше приложение не поддерживает этот конкретный режим compat.

вы не должны поддерживать режимы совместимости. Например, если вы прекратите поддерживать XP, то вы не должны поддерживать XP compat shims.

подумав, что это мой вам совет. Просто ничего не делайте. Если пользователи спрашивают о приложении потерпев неудачу таким образом, скажите им, что вы не поддерживаете этот режим compat. Это не ваша работа, чтобы сделать ваши режимы совместимости поддержки приложений.