Met de officele intro van DarkTheme (macOS 10.14.x / Mojave), en het geweldige werk van Dmitry, ondersteunen onze Lazarus apps onder macOS Dark Theme nu ook. Op basis van het werk van Dmitry heb ik een functie gemaakt waarmee je een theme kunt forceren of terugschakelen naar het systeem theme.
Het kon vast beter, maar dit werkte uitstekend voor mijn toepassingen;
...
{$modeswitch objectivec1}
...
uses ..., CocoaAll, ... ;
...
interface
...
Type
TmacOSThemes = (ThemeSystem, ThemeAqua, ThemeAquaDark, ThemeVibrant, ThemeVibrantDark);
...
// Force macOS Theme (ThemeSystem, ThemeAqua, ThemeAquaDark, ThemeVibrant, ThemeVibrantDark)
function t4a_ForceTheme(AForm: TComponent; aTheme:TmacOSThemes): Boolean;
...
implementation
...
{ Force Theme }
function t4a_ForceTheme(AForm: TComponent; aTheme:TmacOSThemes): Boolean;
var
ClassByName : id;
AppearanceString : string;
AppearanceID : id;
MyNSWindow : NSWindow;
MyNSObject : NSObject;
begin
{$IFDEF DARWIN}
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';
end;
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
begin
if aTheme=ThemeSystem then
objc_msgSend(MyNSWindow, ObjCSelector('setAppearance:'), nil)
else
objc_msgSend(MyNSWindow, ObjCSelector('setAppearance:'), AppearanceID);
Result := true;
end;
{$ELSE}
Result := false;
{$ENDIF}
end;
Je roept de functie vanuit jouw applicatie als volgt aan (self = de mainform):
t4a_ForceTheme(self, ThemeAquaDark);
Merk op dat het onPaint event van een form aangeroepen wordt als het systeem of deze functie het theme veranderen - de plek dus voor kleine custom aanpassingen indien nodig.
Beschikbare themes (je kunt dit uitbreiden indien nodig):
ThemeSystem: theme zoals het systeem dit gebruikt op dit moment.
Forceer themes:
ThemeAqua: het standaard MacOS theme
ThemeAquaDark: DarkTheme in 10.14 (Mojave) en nieuwer (werkt niet met oudere macOS versies!)
ThemeVibrant: een lichtere variant van Aqua theme
ThemeVibrantDark: DarkTheme zoals deze in ouder macOS versies (voor 10.14) gebruikt wordt.