5

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?

Charles Milette
  • 388
  • 3
  • 21
  • Could it be as simple as checking the return value of `GetSysColor (COLOR_WINDOW)`? – Paul Sanders Feb 14 '22 at 20:11
  • I've considered that and maybe it's just me, but it feels like checking the background color's luminance to see which icon I should be using to be more of a hack than a proper solution. – Charles Milette Feb 14 '22 at 20:20
  • COLOR_WINDOW is the color of textboxes etc. Not the taskbar. The UXTheme API might know about the taskbar visual style. – Anders Feb 14 '22 at 20:23
  • IE and old Edge had a CSS media query for (-ms-high-contrast: black-on-white) https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/ – Anders Feb 14 '22 at 20:32
  • IAccessibilitySettings::get_HighContrastScheme returns a name but checking for "white" and "desert" is ugly. – Anders Feb 14 '22 at 20:40
  • Yeah, that name is affected by the user's locale, plus it may change in the future (best example being the Desert theme, which is new) – Charles Milette Feb 14 '22 at 20:53
  • _it feels like checking the background color's luminance to see which icon I should be using to be more of a hack than a proper solution_ I'm not sure I agree. After all, you want to avoid white-on-white, so checking the background colour makes a lot of sense. You just want to check for a 'light value', rather than testing for exactly pure white. – Paul Sanders Feb 14 '22 at 21:18
  • @PaulSanders but which background color? I think Windows 10 at some point let you have a dark taskbar with light everything else. – Anders Feb 14 '22 at 22:44
  • @Anders OK that one then, if you can find a way of figuring it out. – Paul Sanders Feb 14 '22 at 22:48
  • High contrast mode and high contrast themes are different. If you are in high contrast mode, you can also use some high contrast themes. It is also possible to select a high-contrast theme without being in high-contrast mode.Refer to the Blog: https://devblogs.microsoft.com/oldnewthing/20160707-00/?p=93835. So what you actually need is to detect if there is a high-contrast theme, or a high-contrast mode? – Jeaninez - MSFT Feb 15 '22 at 02:42
  • @Jeaninez-MSFT I'm trying to detect high contrast mode with a white high contrast theme, as selecting a high contrast theme without high contrast mode will keep the default "acrylic" taskbar background instead of turning it opaque. – Charles Milette Feb 15 '22 at 03:54
  • @CharlesMilette I suggest you could try calling the SystemParametersInfo function with the SPI_GETHIGHCONTRAST flag. And for more details about High-contrast mode, you could reefer to the Doc:https://learn.microsoft.com/en-us/windows/win32/w8cookbook/high-contrast-mode – Jeaninez - MSFT Feb 16 '22 at 07:53
  • @Jeaninez-MSFT that gets me if high contrast mode is enabled but no info on whether the user is using a white or dark high contrast theme (in combination of high contrast mode), which is what I'm looking for – Charles Milette Feb 18 '22 at 04:02
  • @CharlesMilette As far as I'm concerned, you confused contrast themes with light and dark themes,which support a much larger color palette and don't necessarily increase contrast or make things easier to see. I suggest you could refer to the Docs:[Contrast themes](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/high-contrast-themes) [Color](https://learn.microsoft.com/en-us/windows/apps/design/style/color) – Jeaninez - MSFT Feb 22 '22 at 02:45
  • I am talking about these themes: https://i.imgur.com/Nj98xdq.png – Charles Milette Feb 24 '22 at 18:50
  • As you can see @Jeaninez-MSFT, the "Aa" in the preview is a different color. On some it's white, on others it's black. I want to detect this. Because it affects the color that system tray icons should take. For example if I use the white tray icon for my app on the "Desert" theme, contrast is extremely poor and the icon is barely visible. I need to be able to detect that situation and show my black icon. – Charles Milette Feb 24 '22 at 18:52

1 Answers1

0

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
}
Charles Milette
  • 388
  • 3
  • 21