簡體   English   中英

TSaveDialog失敗,客戶端視覺樣式被禁用

[英]TSaveDialog fails with client visual styles disabled

我想在Delphi XE6中使用TSaveDialog

if not SaveDialog1.Execute(0) then
   Exit;

該調用立即返回false ,而不顯示任何對話框。 我將其追溯到創建shell Save Dialog 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}

我的應用程序使用公共控件庫(6.0.7601.18837)的第6版,但我意識到,如果用戶已禁用我的應用程序的視覺樣式時才會發生:

在此輸入圖像描述

我們仍在使用公共控件庫的第6版,只是IsAppThemed返回false。

注意 :我知道很多人錯誤地認為:

  • Visual Styles API僅在我們加載了Comctrl32.dll版本6時才有效
  • 如果加載了Comctrl32.dll的版本6,則Visual Styles API將起作用
  • 如果我們不使用ComCtrl v6那么這意味着視覺樣式被禁用
  • 如果我們使用舊的公共控件庫,則禁用視覺樣式

蠻力解決方案是將全局UseLatestCommonDialogs設置為false。

但這非常糟糕,因為它僅適用於在應用程序中禁用視覺樣式的人:

  • 對話框繼續在沒有視覺樣式的操作系統上工作(例如Windows Server 2008 R2)
  • 關閉視覺樣式后對話框繼續工作(例如關閉視覺樣式的Windows 7)

這意味着我不能簡單地使用IsAppThemed ,因為如果IsThemeActive為false,它也會返回false。

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

我想我要問的是如何檢查Disble Visual Styles compat標志的狀態。

我真正要問的是如何使Delphi中的TSaveDialog正常工作(並不意味着讀取compat標志是解決方案的一部分)。

你肯定不想測試compat標志。 如果要進行測試,則需要測試該標志控制的內容。 在這種情況下,是否使用主題。 如果您要進行類似測試,則在滿足以下條件時應使用Vista樣式對話框:

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

否則,您需要使用舊的XP樣式對話框。 您可以使用以下代碼實現此目的:

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

但問題是,當用戶使用Windows經典主題運行時,您將禁用新樣式對話框。 我確信你不想要。

所以你可以采用基於功能的方法。 如果新的失敗,那就是嘗試在舊樣式對話框中使用新樣式對話框和回退。 因此,嘗試創建一個IFileSaveDialog 根據是否成功分配UseLatestCommonDialogs


另一方面,此compat設置旨在用於啟用主題時無法正常工作的應用程序。 您的應用程序在主題下可以正常工作,我認為您的應用程序不支持該特定的compat模式是完全合理的。

您不應該支持兼容模式。 例如,如果你停止支持XP,那么你不會期望支持XP compat墊片。

經過反思,這是我對你的建議。 什么都不做。 如果您的用戶以這種方式詢問您的應用是否失敗,請告訴他們您不支持該compat模式。 使您的應用程序支持兼容模式不是您的職責。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM