The MS App Assure team reported to me an issue where my app's notification area/system tray icon is nearly invisible on white high contrast themes (or near-white like Windows 11's "Desert" theme).
I already have a dark icon I use when the (normal, non high-contrast) Windows light theme is on so I would like to use it in these scenarios as well.
The only issue is, while I can detect if high contrast mode is on with SystemParametersInfo
, I haven't found anything to detect if it's a white or a black high contrast theme. How would I proceed to detect that?
I know MSIX packages support having different icons for white and black high contrast themes, so how do they detect it?
First, check if High Contrast mode is on:
HIGHCONTRAST info = { .cbSize = sizeof(info) };
if (SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &info, 0) && info.dwFlags & HCF_HIGHCONTRASTON)
{
// it's on
}
Then, you check the relative luminance of GetSysColor(COLOR_WINDOWTEXT)
. If it's lower than or equal to 0.5, then use a dark icon for your tray:
double Luminance(COLORREF color)
{
const uint8_t R = GetRValue(color);
const uint8_t G = GetGValue(color);
const uint8_t B = GetBValue(color);
const double rg = R <= 10 ? R / 3294.0 : std::pow((R / 269.0) + 0.0513, 2.4);
const double gg = G <= 10 ? G / 3294.0 : std::pow((G / 269.0) + 0.0513, 2.4);
const double bg = B <= 10 ? B / 3294.0 : std::pow((B / 269.0) + 0.0513, 2.4);
return (0.2126 * rg) + (0.7152 * gg) + (0.0722 * bg);
}
if (Luminance(GetSysColor(COLOR_WINDOWTEXT)) <= 0.5)
{
// use dark icon
}
else
{
// use light icon
}