Page 1 of 1

Lazarus – macOS – Force Theme (DarkTheme and such)

Lazarus – macOS – Force Theme (DarkTheme and such)

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
Examples: "MacOS X - Your question", "MS Word - Your Tip or Trick".

Please note that switching to another language when reading a post will not work!
Posts will not have a translated counterpart.

RSS Feed

Home Forums Software Development Delphi, Lazarus, Free Pascal Lazarus – macOS – Force Theme (DarkTheme and such)

Viewing 1 post (of 1 total)
  • Author
  • 11884


    With the introduction of DarkTheme (macOS 10.14.x / Mojave), and the great work of Dmitry, we can now support DarkTheme in our Lazarus applications for macos. Based on some of Dmitry’s work, I created a function that allows you to force a theme, or force back to system default theme.

    I’m sure this could have been done better, but this works well for me;

    {$modeswitch objectivec1}
    uses ..., CocoaAll, ... ;
        TmacOSThemes = (ThemeSystem, ThemeAqua, ThemeAquaDark, ThemeVibrant, ThemeVibrantDark);
    // Force macOS Theme (ThemeSystem, ThemeAqua, ThemeAquaDark, ThemeVibrant, ThemeVibrantDark)
    function t4a_ForceTheme(AForm: TComponent; aTheme:TmacOSThemes): Boolean;
    { Force Theme }
    function t4a_ForceTheme(AForm: TComponent; aTheme:TmacOSThemes): Boolean;
      ClassByName : id;
      AppearanceString : string;
      AppearanceID : id;
      MyNSWindow : NSWindow;
      MyNSObject : NSObject;
      Result := false;
      if not Assigned(AForm) or not (AForm is TWinControl) then Exit;
      MyNSObject := NSObject(TWinControl(AForm).Handle);
      if not Assigned(MyNSObject) then Exit;
      if MyNSObject.respondsToSelector(ObjCSelector('window')) then
        MyNSWindow := objc_msgSend(MyNSObject, ObjCSelector('window'));
      if not Assigned(MyNSWindow) then Exit;
      case aTheme of
        ThemeAqua : AppearanceString := 'NSAppearanceNameAqua';
        ThemeAquaDark : AppearanceString := 'NSAppearanceNameDarkAqua';
        ThemeVibrant : AppearanceString := 'NSAppearanceNameVibrantLight';
        ThemeVibrantDark : AppearanceString := 'NSAppearanceNameVibrantDark';
        else AppearanceString := 'NSAppearanceNameAqua';
      ClassByName := NSClassFromString( NSSTR('NSAppearance'));
      if not Assigned(ClassByName) then Exit; // not suppored in OSX version
      AppearanceID := objc_msgSend(ClassByName, ObjCSelector('appearanceNamed:'), NSSTR(@AppearanceString[1]));
      if not Assigned(AppearanceID) then Exit;
      if MyNSWindow.respondsToSelector(ObjCSelector('setAppearance:')) then
        if aTheme=ThemeSystem then
          objc_msgSend(MyNSWindow, ObjCSelector('setAppearance:'), nil)
          objc_msgSend(MyNSWindow, ObjCSelector('setAppearance:'), AppearanceID);
        Result := true;
      Result := false;

    This function can be called from within your application, like so (self = the mainform):

    t4a_ForceTheme(self, ThemeAquaDark);

    Note that in the onPaint event of your form you can correct colors of custom controls if you’d want to.
    On theme change (even without this function), the onPaint event of your form will always be called.

    Available themes (you can expand the list if you’d like):

    ThemeSystem: use system defined theme

    Forced themes:

    ThemeAqua: the default theme of MacOS
    ThemeAquaDark: The DarkTheme used in 10.14 (Mojave) and newer (will not work in macOS prior to Mojave)
    ThemeVibrant: a slightly lighter version of the default Aqua theme (I have not seen this one used yet)
    ThemeVibrantDark: The DarkTheme used in macOS version prior to 10.14.

Viewing 1 post (of 1 total)

You must be logged in to reply to this topic.