0

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?

SteveS
  • 335
  • 1
  • 13
  • Are you talking about an IDE plugin? – Uwe Raabe Oct 27 '20 at 21:32
  • You need to take in consideration the luminance of each color component of the background. Formulas can be found [in here](https://stackoverflow.com/a/596243/2292722). Then you can use the simple comparison with $7F. – Tom Brunberg Oct 28 '20 at 12:33
  • Uwe - No. Unfortunately, Theme name doesn't give me what I need. I think Tom's answer is the correct one. – SteveS Oct 28 '20 at 14:38
  • Tom - That seems to be spot on, for the themes I've tested at least. Thanks! – SteveS Oct 28 '20 at 15:08

2 Answers2

0

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.

Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
0

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;```
SteveS
  • 335
  • 1
  • 13