Delphi VCL样式教程 - 如何在运行时更改样式

时间:2012-03-28 11:12:54

标签: delphi delphi-xe2 vcl-styles

是否有一个很好的VCL样式教程,我们看到如何动态(在运行时)加载/更改样式?

这应该适用于Delphi XE2及更高版本,因为XE2是第一个带有VCL样式的版本。

5 个答案:

答案 0 :(得分:29)

我正在添加答案,因为本地信息通常仅供链接使用。

以下是您在开始之前需要了解的关键事实:

  1. 许多VCL控件都有颜色属性,但是当打开样式时这些属性会被忽略,而像Button这样的默认“常用控件”将由Delphi本身绘制,而不是使用XP或Windows 2000风格“随Windows一起提供”。

  2. 不知何故,在您的应用程序的深处,VCL样式中的钩子会接管绘制控件。它可以处理的所有东西都将使用常规控件顶部的“皮肤”绘制。很多人称之为“剥皮vcl”,在VCL风格之前,你可能已经找到了第三方皮肤系统。现在它已经内置。

  3. 任何没有挂钩的东西,仍会保持常规风格。所以大多数第三方控件,以及VCL的一些位都不是主题。不要指望完美的即时结果。此外,您可能有时会看到一些由于蒙皮造成的瞬间闪烁或毛刺,这是可以预料的。在运行时添加样式加载,结果的最终质量是任何人的猜测。您不一定能保证在运行时加载的样式将包含您可能希望它包含的所有内容。你也不能保证在你的应用程序中静态包含一个,但至少你静态包含的那些可以由你的QA团队(可能是你)验证。

  4. 这是最简单的入门步骤:真的只有第2步到第4步是必不可少的。

    1. 点击文件 - >新 - > VCL Forms项目。

    2. 右键单击“项目管理器”窗格中的项目选项,然后单击“属性”。导航到应用程序 - >外观

    3. 单击自定义样式以将其启用。 (Amakrits是我列表中的第一个,所以我会点击它)。

    4. 单击默认样式组合框并将其更改为默认值以外的其他内容。

    5. 在表单上放一些内容,使其不为空。 (按钮,列表框等)。

    6. 运行您的应用。

    7. enter image description here

      现在,高级的东西:在运行时改变你的风格:

      我使用此按钮单击并使用formcreate执行此操作:

      fdefaultStyleName:String;添加到表单的私有部分。

      确保Vcl.Themes在您的使用条款中。

      procedure TForm1.Button1Click(Sender: TObject);
      begin
       if Assigned(TStyleManager.ActiveStyle) and (TStyleManager.ActiveStyle.Name<>'Windows') then begin
         TStyleManager.TrySetStyle('Windows');
       end else begin
         TStyleManager.TrySetStyle(fdefaultStyleName); // whatever was in the project settings.
       end;
      
      end;
      
      procedure TForm1.FormCreate(Sender: TObject);
      begin
      if Assigned(TStyleManager.ActiveStyle) then
        fdefaultStyleName := TStyleManager.ActiveStyle.Name;
      
      end;
      

答案 1 :(得分:20)

有关VCL样式的大量内容,请参阅RRUZ主页。

以下是一个主要演示,您可以动态加载几种样式:exploring-delphi-xe2-vcl-styles-part-i

答案 2 :(得分:18)

有关VCL样式的最佳信息来源是Rodrigo Ruz's博客:http://theroadtodelphi.wordpress.com/category/vcl-styles/

答案 3 :(得分:3)

一个例子(公共程序)。记住使用Vcl.Themes;

procedure TData.AllowSKIN( bSKIN:boolean );
var
    sSKIN:string;
begin
    sSKIN := 'Aqua Light Slate';
    if not bSKIN then sSKIN := 'Windows';
    TStyleManager.TrySetStyle( sSKIN );
end;

答案 4 :(得分:1)

我有一个(模板)表单,可以在应用程序中调用该表单以让用户设置外观。只需ShowSkinForm即可显示该表单。您也可以在应用程序初始化期间调用LoadLastSkin以自动应用最后的皮肤。

UNIT FormSkinsDisk;

    {-----------------
   2017.02.23
   Universal skin loader. Loads skins from disk (vsf file)

   To use it:
      Application.ShowMainForm:= FALSE;   
      MainForm.Visible:= FALSE; // Necessary so the form won't flicker during skin loading at startup
      LoadLastSkin  (during application initialization)
      MainForm.Show;
      Skins should be present in the 'System\skins' folder

  Skins folder:
         c:\Users\Public\Documents\Embarcadero\Studio\15.0\Styles\

  KNOWN BUG:
     TStyleManager.IsValidStyle always fails if Vcl.Styles is not in the USES list!!  http://stackoverflow.com/questions/30328644/how-to-check-if-a-style-file-is-already-loaded
-------------------------------------------------------------------------------------------------------------}

INTERFACE                                                                                                     {$WARN GARBAGE OFF}   {Silence the: 'W1011 Text after final END' warning }

USES
  System.SysUtils, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls, System.Classes, System.Types;

TYPE
  TfrmSkinsDisk = class(TForm)
    lBox: TListBox;
    procedure FormCreate  (Sender: TObject);
    procedure FormDestroy (Sender: TObject);
    procedure lBoxClick   (Sender: TObject);
    procedure FormClose   (Sender: TObject; var Action: TCloseAction);
    procedure lblTopClick (Sender: TObject);
  private
    procedure FillLstBox;
  public
 end;


procedure LoadLastSkin(CONST DefaultSkin: string= '');    { On first run, set the DefaultSkin to an existing file (no path) like: 'Graphite Green.vsf'. Leave it empty if you want the default Windows theme to load }
procedure ShowSkinForm;



IMPLEMENTATION {$R *.dfm}

USES
   IOUtils, Vcl.Styles, cIO, vcl.Themes, cINIFile, cINIFileEx, CubicTPU;   {VCL.Styles is mandatory here}

VAR
  SkinFile: string;                                              { Disk short file name (not full path) for the current loaded skin }

CONST
    DefWinTheme= 'Windows default theme';





{-----------------------------------------------------------------------------------------
   UTILS
-----------------------------------------------------------------------------------------}

function GetSkinDir: string;
begin
 Result:= GetAppSysDir+ 'skins\';
end;


function LoadSkinFromFile(CONST DiskShortName: string): Boolean;
VAR  Style : TStyleInfo;
begin
 Result:= FileExists(GetSkinDir+ DiskShortName);

 if Result then
  if TStyleManager.IsValidStyle(GetSkinDir+ DiskShortName, Style)
  then
    if NOT TStyleManager.TrySetStyle(Style.Name, FALSE)
    then
      begin
       TStyleManager.LoadFromFile(GetSkinDir+ DiskShortName);
       TStyleManager.SetStyle(Style.Name);
      end
    else Result:= FALSE
  else
     MesajError('Style is not valid: '+ GetSkinDir+ DiskShortName);
end;


procedure LoadLastSkin(CONST DefaultSkin: string= '');
begin
 SkinFile:= cINIFile.ReadString('LastDiskSkin', DefaultSkin);                                                  { This is a relative path so the skin can still be loaded when the application is moved to a different folder }

 if SkinFile = ''
 then SkinFile:= DefaultSkin;

 if (SkinFile > '')
 AND (SkinFile <> DefWinTheme)              { DefWinTheme represents the default Windows theme/skin. In other words don't load any skin file. Let Win skin the app }
 then LoadSkinFromFile(SkinFile);
end;


procedure ShowSkinForm;
VAR
   frmSkins: TfrmSkinsDisk;
begin
 frmSkins:= TfrmSkinsDisk.Create(NIL);
 frmSkins.ShowModal;
 FreeAndNil(frmSkins);
end;




{----------------------------------------------------------------------------------------
   CREATE
-----------------------------------------------------------------------------------------}

procedure TfrmSkinsDisk.FormCreate(Sender: TObject);
begin
 LoadForm(Self);
 FillLstBox;     { Populate skins }
end;


procedure TfrmSkinsDisk.FormDestroy(Sender: TObject);
begin
 SaveForm(Self);
 cINIFile.WriteString ('LastDiskSkin', SkinFile);
end;

procedure TfrmSkinsDisk.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action:= caFree;
end;







{-----------------------------------------------------------------------------------------------------------------------
   Populate skins
-----------------------------------------------------------------------------------------------------------------------}

procedure TfrmSkinsDisk.lblTopClick(Sender: TObject);
begin
 FillLstBox;
end;


procedure TfrmSkinsDisk.FillLstBox;     { Populate skins }
VAR
   s, FullFileName: string;
begin
 lBox.Items.Clear;
 lBox.Items.Add(DefWinTheme);    { This corresponds to Windows' default theme }
 lblTop.Hint:= GetSkinDir;

 if NOT DirectoryExists(GetSkinDir) then
  begin
   lblTop.Caption:= 'The skin directory could not be located! '+ GetSkinDir+ CRLF+ 'Add skins then click here to refresh the list.';
   lblTop.Color:= clRedBright;
   lblTop.Transparent:= FALSE;
   EXIT;
  end;

 { Display all *.vsf files }
 for FullFileName in TDirectory.GetFiles(GetSkinDir, '*.vsf') DO
  begin
   s:= ExtractFileName(FullFileName);
   lBox.Items.Add(s);
  end;
end;



procedure TfrmSkinsDisk.lBoxClick(Sender: TObject);
begin
 if lBox.ItemIndex < 0 then EXIT;

 SkinFile:= lBox.Items[lBox.ItemIndex];
 if SkinFile= DefWinTheme then
  begin
   TStyleManager.SetStyle('Windows');
   SkinFile:= DefWinTheme;
  end
 else
  if LoadSkinFromFile(SkinFile) then
   begin
    { Bug fix }                                                                                  { fix for this bug: http://stackoverflow.com/questions/30328924/form-losses-modal-attribute-after-changing-app-style }
    Application.ProcessMessages;
    BringToFront;
   end;
end;


end.