在 Windows C++ 中检测白色或黑色高对比度模式

Cha*_*tte 5 c++ windows winapi accessibility system-tray

MS App Assure 团队向我报告了一个问题,即我的应用程序的通知区域/系统托盘图标在白色高对比度主题(或接近白色,如 Windows 11 的“沙漠”主题)上几乎不可见。

我已经有一个在(正常、非高对比度)Windows 浅色主题打开时使用的深色图标,因此我也想在这些场景中使用它。

唯一的问题是,虽然我可以检测高对比度模式是否打开SystemParametersInfo,但我没有找到任何东西来检测它是白色还是黑色高对比度主题。我将如何继续检测到这一点?

我知道 MSIX 包支持为白色和黑色高对比度主题使用不同的图标,那么它们如何检测它呢?

Cha*_*tte 0

首先,检查高对比度模式是否打开:

HIGHCONTRAST info = { .cbSize = sizeof(info) };
if (SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &info, 0) && info.dwFlags & HCF_HIGHCONTRASTON)
{
    // it's on
}
Run Code Online (Sandbox Code Playgroud)

然后,检查的相对亮度GetSysColor(COLOR_WINDOWTEXT)。如果它低于或等于 0.5,则在托盘中使用深色图标:

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
}
Run Code Online (Sandbox Code Playgroud)