Forum > Windows

Dark mode class...

(1/2) > >>

Espectr0:
Hola,

I was thinking of making a class to implement "dark mode" in our applications in Windows 10 as I show in the images below (first image normal, second image dark mode).

For controls that don't support dark mode, maybe a custom paint can be implemented?

I await your comments, Greetings.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit UWSystem.DarkTheme; // ----------------------------------------------------------------------------- {$mode ObjFPC}{$H+} interface uses  Windows, Forms, Classes, SysUtils, dynlibs, Controls, StdCtrls; const  dwmapi = 'dwmapi.dll';  DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;  DWMWA_USE_IMMERSIVE_DARK_MODE = 20;   uxtheme = 'uxtheme.dll';   BackColor: Integer = $1E1E1E;  TextColor: Integer = $9B9B9B; type   { TUWDarkMode }   TUWDarkMode = class  private    FDWMlib  : TLibHandle;    FDWMfunc : function(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HRESULT; stdcall;    FUXlib   : TLibHandle;    FUXfunc  : function(hwnd: HWND; pszSubAppName: LPCWSTR; pszSubIdList: LPCWSTR): HRESULT; stdcall;     function IsWindows10OrGreater(const ABuild: Integer = -1): Boolean;  public    constructor Create(const AForm: TForm);    destructor Destroy; override;    function Loaded: Boolean;    function SetDarkMode(const AForm: TForm; const AValue: Bool = True): Boolean;  end; // ----------------------------------------------------------------------------- implementation // ----------------------------------------------------------------------------- { TUWDarkMode } // ----------------------------------------------------------------------------- constructor TUWDarkMode.Create(const AForm: TForm);begin  FDWMfunc := NIL;  FUXfunc  := NIL;   FDWMlib := LoadLibrary(dwmapi);  if FDWMlib <> 0 then Pointer(FDWMfunc) := GetProcAddress(FDWMlib, 'DwmSetWindowAttribute');   FUXlib := LoadLibrary(uxtheme);  if FUXlib <> 0 then Pointer(FUXfunc) := GetProcAddress(FUXlib, 'SetWindowTheme');   SetDarkMode(AForm);end; // ----------------------------------------------------------------------------- destructor TUWDarkMode.Destroy;begin  if FDWMfunc <> NIL then FDWMfunc := NIL;  if FDWMlib <> 0 then FreeLibrary(FDWMlib);   if FUXfunc <> NIL then FUXfunc := NIL;  if FUXlib <> 0 then FreeLibrary(FUXlib);   inherited Destroy;end; // ----------------------------------------------------------------------------- function TUWDarkMode.Loaded: Boolean;begin  Result := (FDWMlib <> 0) and (FUXlib <> 0)    and Assigned(FDWMfunc) and Assigned(FUXfunc);end; // ----------------------------------------------------------------------------- function TUWDarkMode.SetDarkMode(const AForm: TForm; const AValue: Bool = True): Boolean;var  attr: DWord;  i: Integer;begin  Result := False;  if AForm = NIL then Exit;   if IsWindows10OrGreater(17763) then  begin    attr := DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;    if IsWindows10OrGreater(18985) then attr := DWMWA_USE_IMMERSIVE_DARK_MODE;     FDWMfunc(AForm.Handle, attr, @AValue, SizeOf(AValue));  end;   with AForm do  begin    Color := BackColor;    Font.Color := TextColor;  end;   for i := 0 to AForm.ComponentCount-1 do  begin    if AForm.Components[i] is TWinControl then      FUXfunc((AForm.Components[i] as TWinControl).Handle, 'DarkMode_Explorer', NIL);  end;   Result := True;end; // ----------------------------------------------------------------------------- function TUWDarkMode.IsWindows10OrGreater(const ABuild: Integer = -1): Boolean;begin  Result := (Win32MajorVersion >= 10) and (Win32BuildNumber >= ABuild);end; // ----------------------------------------------------------------------------- end. 

AlexTP:
For MainMenu you can use:
https://wiki.freepascal.org/Win32MenuStyler

Espectr0:
Gracias @AlexTP, I will check it later.

Thinking about the other controls (not menu), I have modified the class a bit and managed more colors except the CheckBox and RadioButton, can't change the font color?

AlexTP:
See the info here
https://stackoverflow.com/questions/12248571/how-to-change-caption-font-color-on-tcheckbox-tradiobutton-tgroupbox

Wallaby:
I was able to implement nearly full dark mode support for my applications.

For certain theme-drawn controls such as CheckBox/Radio, GroupBox, TabSeet, StatusBar and Progress bar you will need to go deeper and subclass them with SetWindowSubclass.

In the subclass routine you'd need to intercept WM_PAINT and WM_ERASEBKGND and custom-draw these controls.

Navigation

[0] Message Index

[#] Next page

Go to full version