Delphi VCL styles tips
List available styles in a combobox
To list available styles in a combobox:
Uses
Vcl.Themes,
Vcl.Styles;
procedure TForm1.ListAvailableStyles(ComboBox: TComboBox);
var
S: String;
begin
ComboBox.Items.BeginUpdate;
try
ComboBox.Items.Clear;
for S in TStyleManager.StyleNames do begin
ComboBox.Items.Add(s);
end;
ComboBox.Sorted := True;
// Select the style that's currently in use in the combobox
ComboBox.ItemIndex := ComboBox.Items.IndexOf(TStyleManager.ActiveStyle.Name);
finally
ComboBox.Items.EndUpdate;
end;
end;
Disable styles for a specific class
To disable styling for a specific class, for a specific window for example, register the default style hook class ('TStyleHook') for it:
interface
Uses
Vcl.Themes,
Vcl.Styles;
type
TMyForm = class(TForm)
...
end;
Implementation
...
Initialization
TStyleManager.Engine.RegisterStyleHook(TMyForm, TStyleHook);
end.
TMyForm will not be styled from now on.
Fixing the TListView flickering issue when VCL styles are enabled
To fix the flickering when changing the content of a list view disable the drawing of the client area and set the listview's background color by code:
Uses
Vcl.Themes,
Vcl.Styles;
procedure FixTListViewStyled(ListView: TListView);
var
BackgroundColor: TColor;
LStyle: TCustomStyleServices;
begin
//* Default value
BackgroundColor := clWindow;
LStyle := StyleServices;
if LStyle.Enabled
AND (TStyleManager.ActiveStyle.Name <> 'Windows')
then begin
BackgroundColor := TStyleManager.ActiveStyle.GetStyleColor(scListView);
end;
ListView.StyleElements := ListView.StyleElements - [seClient];
ListView.DoubleBuffered := True;
ListView.Color := BackgroundColor;
end;
Fixing the TForm bsSingle and bsDialog size issue when VCL styles are enabled
unit FixFormsWhenStyled;
interface
Uses
Messages,
Forms;
type
TFixedFormStyleHook = class(TFormStyleHook)
strict protected
procedure WndProc(var Message: TMessage); override;
end;
implementation
Uses
SysUtils,
Windows,
Vcl.Themes,
Vcl.Styles;
{ TFixedFormStyleHook }
procedure TFixedFormStyleHook.WndProc(var Message: TMessage);
var
ncParams: NCCALCSIZE_PARAMS;
newMsg: TMessage;
begin
if (Message.Msg = WM_NCCALCSIZE)
AND (Message.WParam = 0)
then begin
// Convert message to format with WPARAM == TRUE due to VCL styles
// failure to handle it when WPARAM == FALSE.
Message.WParam := 1;
inherited WndProc(Message);
end else begin
inherited;
end;
end;
Initialization
TCustomStyleEngine.RegisterStyleHook(TForm, TFixedFormStyleHook);
TCustomStyleEngine.RegisterStyleHook(TCustomForm, TFixedFormStyleHook);
end.
Using styles in app. and in a .dll at the same time
It's possible to use both in the main application and in a loaded .dll (for example a plugin) styles at the same time.
To have this working the .dll needs not to set styles on menus, as the main application already hooks the drawing of menus.
Somewhere in the .dll disable menu styles before applying a style, for example in the DLLPROC or add an 'Initialization' section:
Uses
Vcl.Themes,
Vcl.Styles,
VCL.SysStyles; // to gain access to TSysPopupStyleHook;
Initialization
TStyleManager.SystemHooks := TStyleManager.SystemHooks - [shMenus];
TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook);
end.
If the .dll is loading a .vsf style file that it gets as a parameter from the application, there might be a problem if you want to load a style file that is already loaded as this generates an exception.
To avoid this parse the style name and catch the exception in case:
procedure SetStyleByApp(StyleNameOrFileName: String);
var
StyleInfo: TStyleInfo;
begin
if FileExists(StyleNameOrFileName) then begin
if TStyleManager.IsValidStyle(StyleNameOrFileName, StyleInfo) then begin
try
TStyleManager.LoadFromFile(StyleNameOrFileName);
except
//* Style already loaded or not valid
end;
TStyleManager.TrySetStyle(StyleInfo.Name);
end;
end else begin
TStyleManager.TrySetStyle(StyleNameOrFileName);
end;
end;
Integrating style files as resources in a .dll that has styles enabled
Delphi (as of XE7) does not have option to include the style files in the .dll itself. Here's how to do it with resources:
- Using XN Resource Editor, right click on the left panel of the window and in the pop-up menu select 'Import User Resource'.
- Select the style file you want to include from 'C:\Program Files (x86)\Embarcadero\Studio\15.0\Redist\styles\vcl\'
- The new resource should appear on the left, click on 'VSF', presss F2 and change it to 'VCLSTYLE'
- Repet the above until all the styles needed are added
- Save the new resource package with menu: 'File/Save As...' for example 'VCLStyles.res'
- In Delphi include this .res file with adding '{$R VCLStyles.res}' for example after '{$R *.res}' (the .res file should be in the project folder)
- Build the .dll - Delphi will now automatically load/list the included styles automatically and they are ready to apply them with 'TStyleManager.TrySetStyle(StyleName);'
If you found the above information useful, check my components.
|