0
votes

Using Delphi 10.2 and themes: is there a reliable way to determine if the current theme is a "light" (white or light clWindow color) or "dark" (black, near-black or dark clWindow color) theme? I have to paint certain elements in specific colors (e.g. an alarm indicator in red, regardless of the theme color) but need to use "bright" red against a dark background vs a more "muted" red against a light background.

I've tried looking at various sets of the RGB components of the theme's clWindow color (i.e. if 2 of the 3 component colors are > $7F, it's a "light" theme) but that's not always reliable for some themes.

Is there a better/more reliable way to determine this?

2
Are you talking about an IDE plugin?Uwe Raabe
You need to take in consideration the luminance of each color component of the background. Formulas can be found in here. Then you can use the simple comparison with $7F.Tom Brunberg
Uwe - No. Unfortunately, Theme name doesn't give me what I need. I think Tom's answer is the correct one.SteveS
Tom - That seems to be spot on, for the themes I've tested at least. Thanks!SteveS

2 Answers

0
votes

If you are writing an IDE plugin you can ask BorlandIDEServices for IOTAIDEThemingServices. The latter contains a property ActiveTheme which gives you the current theme name.

0
votes

Based on Tom's info, I implemented the following function, which works well against every theme I've tried it on:

function IsLightTheme: Boolean;
var
  WC: TColor;
  PL: Integer;
  R,G,B: Byte;
begin
  //if styles are disabled, use the default Windows window color,
  //otherwise use the theme's window color
  if (not StyleServices.Enabled) then
    WC := clWindow
  else
    WC := StyleServices.GetStyleColor(scWindow);

  //break out it's component RGB parts
  ColorToRGBParts(WC, R, G, B);

  //calc the "perceived luminance" of the color.  The human eye perceives green the most,
  //then red, and blue the least; to determine the luminance, you can multiply each color
  //by a specific constant and total the results, or use the simple formula below for a
  //faster close approximation that meets our needs. PL will always be between 0 and 255.
  //Thanks to Glenn Slayden for the formula and Tom Brunberg for pointing me to it!
  PL := (R+R+R+B+G+G+G+G) shr 3;

  //if the PL is greater than the color midpoint, it's "light", otherwise it's "dark".
  Result := (PL > $7F);
end;```