Учебник по стилям Delphi VCL - как изменить стиль во время выполнения - PullRequest
14 голосов
/ 28 марта 2012

Есть ли хорошее руководство по стилям VCL, в котором мы увидим, как динамически (во время выполнения) загружать / изменять стиль?

Это должно работать с Delphi XE2 и выше, поскольку XE2 - первая версия со стилями VCL.

Ответы [ 5 ]

29 голосов
/ 28 марта 2012

Я добавляю ответ, потому что локальная информация часто предпочитается просто ссылкам.

Вот ключевые факты, которые вам необходимо знать перед началом работы:

  1. Многие элементы управления VCL имеют свойства цвета, но эти свойства будут игнорироваться при включении стилей, и «общие элементы управления» по умолчанию, такие как Button, будут рисоваться самим Delphi вместо использования XP или Стиль Windows 2000, который «поставляется с окнами».

  2. Каким-то образом, глубоко внутри вашего приложения, стили VCL ставят зацепки за рисование ваших элементов управления. Все, с чем он может справиться, будет нарисовано с помощью «скина» поверх обычных элементов управления. Многие люди называют это «скиннингом vcl», и до появления стилей VCL вы могли найти стороннюю систему скинов. Теперь он встроен.

  3. Все, что не подключено, все равно получит обычный стиль. Таким образом, большинство сторонних элементов управления и некоторые фрагменты VCL не будут тематическими. Не ожидайте идеальных мгновенных результатов. Кроме того, вы можете иногда увидеть некоторое мгновенное мерцание или глюки в результате скининга, что и следовало ожидать. Добавьте загрузку стилей во время выполнения, и конечное качество вашего результата может быть чьим-либо предположением. Вы не можете обязательно гарантировать, что стиль, который загружается во время выполнения, будет содержать все, что вы хотите, чтобы он содержал. Вы также не можете гарантировать, что с одним из них вы статически включаете в свое приложение, но по крайней мере те, которые вы статически включаете, могут быть проверены вашей командой QA (которая может быть вами).

А вот самые простые шаги, чтобы начать: На самом деле необходимы только шаги с 2 по 4.

  1. Выберите Файл -> Создать -> Проект VCL Forms.

  2. Щелкните правой кнопкой мыши параметры проекта на панели диспетчера проектов и выберите «Свойства». Перейдите к Приложению -> Внешний вид

  3. Нажмите на собственный стиль, чтобы включить его. (Amakrits является первым в моем списке, поэтому я нажму на это).

  4. Нажмите на выпадающий список стиля по умолчанию и измените его на значение, отличное от значения по умолчанию.

  5. Поместите что-нибудь в форму, чтобы она не была пустой. (Кнопка, список и т. Д.).

  6. Запустите ваше приложение.

enter image description here

Теперь, расширенные возможности: Измените свой стиль во время выполнения:

Я использую эту кнопку, чтобы создать это:

Добавьте 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;
20 голосов
/ 28 марта 2012

На домашней странице RRUZ можно найти много информации о стилях VCL.

Вот основная демонстрационная программа, в которой вы можете динамически загрузить несколько стилей: exploring-delphi-xe2-vcl-styles-part-я

18 голосов
/ 28 марта 2012

Лучший источник информации о стилях VCL - Блог Родриго Руза : http://theroadtodelphi.wordpress.com/category/vcl-styles/

3 голосов
/ 08 августа 2016

Пример (публичная процедура). Помните, использует 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;
1 голос
/ 12 июля 2019

У меня есть форма (шаблон), которую я вызываю в своем приложении, чтобы позволить пользователю устанавливать скины. Просто 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.
...