Changeset 115 for trunk


Ignore:
Timestamp:
Dec 11, 2024, 10:26:02 AM (5 weeks ago)
Author:
chronos
Message:
  • Modified: Automatically detect and use dark mode on Windows.
  • Modified: Use dark mode title bar on Windows 10.
Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Core.pas

    r109 r115  
    118118      FormMain.FormMain.Redraw;
    119119      FormMain.FormMain.UpdateInterface;
     120      ThemeManager1.UseTheme(FormMain.FormMain);
    120121      UpdateInterface;
    121122    end;
  • trunk/Game.pas

    r113 r115  
    409409  // Clear background
    410410  MetaCanvas.Brush.Style := bsSolid;
    411   MetaCanvas.Brush.Color := Core.Core.ThemeManager1.Theme.ColorControl;
     411  MetaCanvas.Brush.Color := Core.Core.ThemeManager1.ActualTheme.ColorControl;
    412412  MetaCanvas.FillRect(0, 0, MetaCanvas.Width, MetaCanvas.Height);
    413413
     
    663663begin
    664664  with Canvas do begin
    665     Font.Color := Core.Core.ThemeManager1.Theme.ColorControlText;
     665    Font.Color := Core.Core.ThemeManager1.ActualTheme.ColorControlText;
    666666    Font.Size := Trunc(ScaleX(BoxFontSize, 96));
    667667
     
    671671
    672672    Brush.Style := bsSolid;
    673     Brush.Color := Core.Core.ThemeManager1.Theme.ColorWindow;
     673    Brush.Color := Core.Core.ThemeManager1.ActualTheme.ColorWindow;
    674674    FillRect(Pos.X, Pos.Y, Pos.X + BoxSize.Width, Pos.Y + BoxSize.Height);
    675675
     
    678678
    679679    Brush.Style := bsClear;
    680     Font.Color := Core.Core.ThemeManager1.Theme.ColorControlText;
     680    Font.Color := Core.Core.ThemeManager1.ActualTheme.ColorControlText;
    681681    Font.Size := Trunc(ScaleX(BoxFontSize, 96));
    682682    TextOut(Pos.X + (BoxSize.Width - TextWidth(Value)) div 2,
     
    11461146  Color: TPixel32;
    11471147begin
    1148   if (Core.Core.ThemeManager1.Theme.Name = ThemeNameDark) or
    1149   ((Core.Core.ThemeManager1.Theme.Name = ThemeNameSystem) and
     1148  if (Core.Core.ThemeManager1.ActualTheme.Name = ThemeNameDark) or
     1149  ((Core.Core.ThemeManager1.ActualTheme.Name = ThemeNameSystem) and
    11501150  Core.Core.ThemeManager1.IsDarkTheme)
    11511151  then begin
  • trunk/Packages/Common/Theme.pas

    r113 r115  
    55uses
    66  Classes, SysUtils, Graphics, ComCtrls, Controls, ExtCtrls, Menus, StdCtrls,
    7   Spin, Forms, Generics.Collections, Grids;
     7  Spin, Forms, Generics.Collections, Grids, Registry, LCLType;
    88
    99type
     
    3030  private
    3131    FTheme: TTheme;
     32    FActualTheme: TTheme;
    3233    function Gray(C: TColor): Byte;
    3334    procedure SetTheme(AValue: TTheme);
    34     procedure SetThemeName(AValue: TTheme);
     35    procedure SetThemeName(Name: string);
     36    procedure SetThemedTitleBar(AForm: TForm; Active: Bool);
     37    function IsWindows10OrGreater(BuildNumber: Integer): Boolean;
    3538  public
    3639    Used: Boolean;
     
    4245    procedure UseTheme(Form: TForm);
    4346    property Theme: TTheme read FTheme write SetTheme;
     47    property ActualTheme: TTheme read FActualTheme;
    4448  end;
    4549
     
    105109
    106110function TThemeManager.IsDarkTheme: Boolean;
    107 begin
    108   Result := Gray(ColorToRGB(clWindow)) < Gray(ColorToRGB(clWindowText));
    109 end;
    110 
    111 procedure TThemeManager.SetThemeName(AValue: TTheme);
     111{$IFDEF WINDOWS}
     112var
     113  LightKey: Boolean;
     114  Registry: TRegistry;
     115const
     116  KeyPath = '\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize';
     117  KeyName = 'AppsUseLightTheme';
     118{$ELSE}
     119var
     120  ColorWindow: TColor;
     121  ColorWindowText: TColor;
     122{$ENDIF}
     123begin
     124  Result := False;
     125  {$IFDEF WINDOWS}
     126  Registry := TRegistry.Create;
     127  try
     128    Registry.RootKey := HKEY_CURRENT_USER;
     129    if Registry.OpenKeyReadOnly(KeyPath) then begin
     130      if Registry.ValueExists(KeyName) then
     131        LightKey := Registry.ReadBool(KeyName)
     132      else LightKey := True;
     133    end else LightKey := True;
     134    Result := not LightKey;
     135  finally
     136    Registry.Free;
     137  end;
     138  {$ELSE}
     139  ColorWindow := ColorToRGB(clWindow);
     140  ColorWindowText := ColorToRGB(clWindowText);
     141  Result := Gray(ColorWindow) < Gray(ColorWindowText);
     142  {$ENDIF}
     143end;
     144
     145procedure TThemeManager.SetThemeName(Name: string);
     146begin
     147  Theme := Themes.FindByName(Name);
     148end;
     149
     150function TThemeManager.IsWindows10OrGreater(BuildNumber: Integer): Boolean;
     151begin
     152  {$IFDEF WINDOWS}
     153  Result := (Win32MajorVersion >= 10) and (Win32BuildNumber >= BuildNumber);
     154  {$ELSE}
     155  Result := False;
     156  {$ENDIF}
     157end;
     158
     159procedure TThemeManager.SetThemedTitleBar(AForm: TForm; Active: Bool);
     160type
     161  TDwmSetWindowAttribute = function(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HRESULT; stdcall;
     162const
     163  DwmapiLibName = 'dwmapi.dll';
     164  DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
     165  DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
     166var
     167  DwmapiLib: TLibHandle;
     168  DwmSetWindowAttribute: TDwmSetWindowAttribute;
     169  Attr: DWord;
     170begin
     171  DwmapiLib := LoadLibrary(DwmapiLibName);
     172  if DwmapiLib <> 0 then DwmSetWindowAttribute := GetProcAddress(DwmapiLib, 'DwmSetWindowAttribute')
     173    else DwmSetWindowAttribute := nil;
     174
     175  if Assigned(DwmSetWindowAttribute) and IsWindows10OrGreater(17763) then begin
     176    Attr := DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
     177    if IsWindows10OrGreater(18985) then Attr := DWMWA_USE_IMMERSIVE_DARK_MODE;
     178
     179    DwmSetWindowAttribute(AForm.Handle, Attr, @Active, SizeOf(Active));
     180  end;
     181  if DwmapiLib <> 0 then FreeLibrary(DwmapiLib);
     182end;
     183
     184procedure TThemeManager.SetTheme(AValue: TTheme);
    112185begin
    113186  if FTheme = AValue then Exit;
    114187  FTheme := AValue;
    115 end;
    116 
    117 procedure TThemeManager.SetTheme(AValue: TTheme);
    118 begin
    119   if FTheme = AValue then Exit;
    120   FTheme := AValue;
     188  FActualTheme := FTheme;
     189  {$IFDEF WINDOWS}
     190  if Assigned(FTheme) and (FTheme = Themes.FindByName(ThemeNameSystem)) and IsDarkTheme then
     191    FActualTheme := Themes.FindByName(ThemeNameDark);
     192  {$ENDIF}
    121193end;
    122194
     
    132204    ColorControlSelected := clWindow;
    133205  end;
    134   Theme := TTheme(Themes.First);
    135206  with Themes.AddNew(ThemeNameDark) do begin
    136207    ColorWindow := RGBToColor($20, $20, $20);
     
    147218    ColorControlSelected := RGBToColor(196, 225, 255);
    148219  end;
     220  Theme := TTheme(Themes.First);
    149221end;
    150222
     
    170242    (Control is TMemo) or (Control is TListView) or (Control is TCustomDrawGrid) or
    171243    (Control is TCheckBox) or (Control is TPageControl) or (Control is TRadioButton) then begin
    172       Control.Color := FTheme.ColorWindow;
    173       Control.Font.Color := FTheme.ColorWindowText;
     244      Control.Color := FActualTheme.ColorWindow;
     245      Control.Font.Color := FActualTheme.ColorWindowText;
    174246    end else begin
    175       Control.Color := FTheme.ColorControl;
    176       Control.Font.Color := FTheme.ColorControlText;
     247      Control.Color := FActualTheme.ColorControl;
     248      Control.Font.Color := FActualTheme.ColorControlText;
    177249    end;
    178250
    179251    if Control is TCustomDrawGrid then begin
    180       (Control as TCustomDrawGrid).Editor.Color := FTheme.ColorWindow;
    181       (Control as TCustomDrawGrid).Editor.Font.Color := FTheme.ColorWindowText;
     252      (Control as TCustomDrawGrid).Editor.Color := FActualTheme.ColorWindow;
     253      (Control as TCustomDrawGrid).Editor.Font.Color := FActualTheme.ColorWindowText;
    182254    end;
    183255
     
    195267procedure TThemeManager.UseTheme(Form: TForm);
    196268begin
    197   if not Used and (FTheme.Name = ThemeNameSystem) then Exit;
     269  if not Used and (FActualTheme.Name = ThemeNameSystem) then Exit;
    198270  ApplyTheme(Form);
     271  SetThemedTitleBar(Form, FActualTheme.Name = ThemeNameDark);
    199272  Used := True;
    200273end;
Note: See TracChangeset for help on using the changeset viewer.