Changeset 219 for trunk/Packages/Common/Theme.pas
- Timestamp:
- Jan 17, 2025, 9:05:54 PM (4 days ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/Packages/Common/Theme.pas
r218 r219 1 unit UTheme;1 unit Theme; 2 2 3 3 interface … … 5 5 uses 6 6 Classes, SysUtils, Graphics, ComCtrls, Controls, ExtCtrls, Menus, StdCtrls, 7 Spin, Forms, fgl, Grids;7 Spin, Forms, Generics.Collections, Grids, Registry, LCLType; 8 8 9 9 type … … 19 19 { TThemes } 20 20 21 TThemes = class(T FPGObjectList<TTheme>)21 TThemes = class(TObjectList<TTheme>) 22 22 function AddNew(Name: string): TTheme; 23 23 function FindByName(Name: string): TTheme; … … 25 25 end; 26 26 27 TDwmSetWindowAttribute = function(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HRESULT; stdcall; 28 27 29 { TThemeManager } 28 30 … … 30 32 private 31 33 FTheme: TTheme; 34 FActualTheme: TTheme; 35 DwmapiLib: TLibHandle; 36 DwmSetWindowAttribute: TDwmSetWindowAttribute; 37 function Gray(C: TColor): Byte; 32 38 procedure SetTheme(AValue: TTheme); 33 procedure SetThemeName(AValue: TTheme); 39 procedure SetThemeName(Name: string); 40 procedure SetThemedTitleBar(AForm: TForm; Active: Bool); 41 function IsWindows10OrGreater(BuildNumber: Integer): Boolean; 34 42 public 35 43 Used: Boolean; 36 44 Themes: TThemes; 45 function IsDarkTheme: Boolean; 37 46 procedure ApplyTheme(Component: TComponent); 38 47 constructor Create(AOwner: TComponent); override; … … 40 49 procedure UseTheme(Form: TForm); 41 50 property Theme: TTheme read FTheme write SetTheme; 42 end; 51 property ActualTheme: TTheme read FActualTheme; 52 end; 53 54 const 55 ThemeNameSystem = 'System'; 56 ThemeNameLight = 'Light'; 57 ThemeNameDark = 'Dark'; 58 DwmapiLibName = 'dwmapi.dll'; 59 DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19; 60 DWMWA_USE_IMMERSIVE_DARK_MODE = 20; 43 61 44 62 procedure Register; 63 45 64 46 65 implementation … … 89 108 end; 90 109 91 procedure TThemeManager.SetThemeName(AValue: TTheme); 110 { TThemeManager } 111 112 function TThemeManager.Gray(C: TColor): Byte; 113 begin 114 Result := Trunc(Red(C) * 0.3 + Green(C) * 0.59 + Blue(C) * 0.11); 115 end; 116 117 function TThemeManager.IsDarkTheme: Boolean; 118 {$IFDEF WINDOWS} 119 var 120 LightKey: Boolean; 121 Registry: TRegistry; 122 const 123 KeyPath = '\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize'; 124 KeyName = 'AppsUseLightTheme'; 125 {$ELSE} 126 var 127 ColorWindow: TColor; 128 ColorWindowText: TColor; 129 {$ENDIF} 130 begin 131 Result := False; 132 {$IFDEF WINDOWS} 133 Registry := TRegistry.Create; 134 try 135 Registry.RootKey := HKEY_CURRENT_USER; 136 if Registry.OpenKeyReadOnly(KeyPath) then begin 137 if Registry.ValueExists(KeyName) then 138 LightKey := Registry.ReadBool(KeyName) 139 else LightKey := True; 140 end else LightKey := True; 141 Result := not LightKey; 142 finally 143 Registry.Free; 144 end; 145 {$ELSE} 146 ColorWindow := ColorToRGB(clWindow); 147 ColorWindowText := ColorToRGB(clWindowText); 148 Result := Gray(ColorWindow) < Gray(ColorWindowText); 149 {$ENDIF} 150 end; 151 152 procedure TThemeManager.SetThemeName(Name: string); 153 begin 154 Theme := Themes.FindByName(Name); 155 end; 156 157 function TThemeManager.IsWindows10OrGreater(BuildNumber: Integer): Boolean; 158 begin 159 {$IFDEF WINDOWS} 160 Result := (Win32MajorVersion >= 10) and (Win32BuildNumber >= BuildNumber); 161 {$ELSE} 162 Result := False; 163 {$ENDIF} 164 end; 165 166 procedure TThemeManager.SetThemedTitleBar(AForm: TForm; Active: Bool); 167 var 168 Attr: DWord; 169 begin 170 if Assigned(DwmSetWindowAttribute) and IsWindows10OrGreater(17763) then begin 171 Attr := DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; 172 if IsWindows10OrGreater(18985) then Attr := DWMWA_USE_IMMERSIVE_DARK_MODE; 173 174 DwmSetWindowAttribute(AForm.Handle, Attr, @Active, SizeOf(Active)); 175 end; 176 end; 177 178 procedure TThemeManager.SetTheme(AValue: TTheme); 92 179 begin 93 180 if FTheme = AValue then Exit; 94 181 FTheme := AValue; 95 end; 96 97 procedure TThemeManager.SetTheme(AValue: TTheme); 98 begin 99 if FTheme = AValue then Exit; 100 FTheme := AValue; 182 FActualTheme := FTheme; 183 {$IFDEF WINDOWS} 184 if Assigned(FTheme) and (FTheme = Themes.FindByName(ThemeNameSystem)) and IsDarkTheme then 185 FActualTheme := Themes.FindByName(ThemeNameDark); 186 {$ENDIF} 101 187 end; 102 188 … … 104 190 begin 105 191 inherited; 192 {$IFDEF WINDOWS} 193 DwmapiLib := LoadLibrary(DwmapiLibName); 194 if DwmapiLib <> 0 then DwmSetWindowAttribute := GetProcAddress(DwmapiLib, 'DwmSetWindowAttribute') 195 else DwmSetWindowAttribute := nil; 196 {$ENDIF} 197 106 198 Themes := TThemes.Create; 107 with Themes.AddNew( 'System') do begin199 with Themes.AddNew(ThemeNameSystem) do begin 108 200 ColorWindow := clWindow; 109 201 ColorWindowText := clWindowText; … … 112 204 ColorControlSelected := clWindow; 113 205 end; 114 Theme := TTheme(Themes.First); 115 with Themes.AddNew('Dark') do begin 206 with Themes.AddNew(ThemeNameDark) do begin 116 207 ColorWindow := RGBToColor($20, $20, $20); 117 208 ColorWindowText := clWhite; … … 120 211 ColorControlSelected := RGBToColor(96, 125, 155); 121 212 end; 122 with Themes.AddNew( 'Light') do begin213 with Themes.AddNew(ThemeNameLight) do begin 123 214 ColorWindow := clWhite; 124 215 ColorWindowText := clBlack; … … 127 218 ColorControlSelected := RGBToColor(196, 225, 255); 128 219 end; 220 Theme := TTheme(Themes.First); 129 221 end; 130 222 … … 132 224 begin 133 225 FreeAndNil(Themes); 226 {$IFDEF WINDOWS} 227 if DwmapiLib <> 0 then FreeLibrary(DwmapiLib); 228 {$ENDIF} 134 229 inherited; 135 230 end; … … 150 245 (Control is TMemo) or (Control is TListView) or (Control is TCustomDrawGrid) or 151 246 (Control is TCheckBox) or (Control is TPageControl) or (Control is TRadioButton) then begin 152 Control.Color := F Theme.ColorWindow;153 Control.Font.Color := F Theme.ColorWindowText;247 Control.Color := FActualTheme.ColorWindow; 248 Control.Font.Color := FActualTheme.ColorWindowText; 154 249 end else begin 155 Control.Color := F Theme.ColorControl;156 Control.Font.Color := F Theme.ColorControlText;250 Control.Color := FActualTheme.ColorControl; 251 Control.Font.Color := FActualTheme.ColorControlText; 157 252 end; 158 253 159 254 if Control is TCustomDrawGrid then begin 160 (Control as TCustomDrawGrid).Editor.Color := F Theme.ColorWindow;161 (Control as TCustomDrawGrid).Editor.Font.Color := F Theme.ColorWindowText;255 (Control as TCustomDrawGrid).Editor.Color := FActualTheme.ColorWindow; 256 (Control as TCustomDrawGrid).Editor.Font.Color := FActualTheme.ColorWindowText; 162 257 end; 163 258 … … 175 270 procedure TThemeManager.UseTheme(Form: TForm); 176 271 begin 177 if not Used and (F Theme.Name = 'System') then Exit;272 if not Used and (FActualTheme.Name = ThemeNameSystem) then Exit; 178 273 ApplyTheme(Form); 274 SetThemedTitleBar(Form, FActualTheme.Name = ThemeNameDark); 179 275 Used := True; 180 276 end; 181 277 182 183 278 end.
Note:
See TracChangeset
for help on using the changeset viewer.