Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Windows поддерживает светлую и темную темы в качестве параметра персонализации в параметрах Windows. В Windows по умолчанию используется светлый режим, но пользователи могут выбрать темный режим, в котором цвет большей части пользовательского интерфейса изменяется на темный. Пользователи могут выбрать этот параметр, так как он упрощает просмотр в средах с менее интенсивным освещением, или из-за того, что в целом предпочитают более темный интерфейс. Кроме того, более темные цвета пользовательского интерфейса могут уменьшить использование батареи на дисплеях компьютера некоторых типов, таких как экраны OLED
Мы работаем над расширением поддержки Темного режима, не нарушая существующие приложения, и в этом случае мы предоставляем технические рекомендации по обновлению классического Windows app Win32 для поддержки как легких, так и темных режимов.
Сравнение светлого и темного режимов
Цветовой режим в параметрах (в частности, светлый и темный режимы) — это параметр, определяющий общие цвета переднего плана и фона для операционной системы и приложений.
| Режим | Описание | Пример |
|---|---|---|
| Легкий | Светлый фон с контрастным темным передним планом. Обычно в светлом режиме черный или темный текст отображается на белом или светлом фоне. |
|
| Темный | Темный фон с контрастным светлым передним планом. Обычно в темном режиме белый или светлый текст отображается на черном или темном фоне. |
|
Примечание.
Причина использования черного или темного, а также белого или светлого цветов заключается в том, что есть дополнительные цвета, такие как цвет элементов, которые могут оттенять различные цвета переднего плана и фона. Так, в некоторых частях пользовательского интерфейса светло-синий текст может отображаться на темно-синем фоне. Это по-прежнему считается приемлемым пользовательским интерфейсом в темном режиме.
Из-за широкого разнообразия оформления пользовательского интерфейса в различных приложениях настройка определенного цветового режима, а также цвета переднего плана и фона является скорее рекомендацией, чем правилом:
- Элементы переднего плана, выделенные элементы и текст должны быть ближе к цвету переднего плана, чем к цвету фона.
- Большие, сплошные фоновые области и фон текста обычно должны быть ближе к цвету фона, чем к цвету переднего плана.
На практике это означает, что в темном режиме большая часть пользовательского интерфейса будет темной. В светлом режиме большая часть пользовательского интерфейса будет светлой. Концепция фона в Windows — это большая область цветов в приложении или цвет страницы. Концепция переднего плана в Windows — это цвет текста.
Совет
Если вам кажется странным, что цвет переднего плана светлый в темном режиме и темный в светлом режиме, может помочь воспринимать цвет переднего плана как "цвет текста по умолчанию".
Включение поддержки переключения цветового режима
Есть много подходов к реализации поддержки темного режима в приложении. Некоторые приложения содержат два набора пользовательских интерфейсов (со светлым и с темным цветом). Некоторые платформы пользовательского интерфейса Windows, такие как WinUI 3, автоматически определяют тему системы и настраивают пользовательский интерфейс в соответствии с этой темой. Чтобы полностью поддерживать темный режим, вся поверхность приложения должна следовать темной теме.
Для поддержки светлой и темной тем в приложении Win32 можно выполнить два следующих основных действия:
Определить, включен ли темный режим.
Если вы знаете, включен ли в параметрах системы темный режим, вам будет легче понять, когда нужно переключить тему пользовательского интерфейса вашего приложения на темную.
Включить темный режим для строк заголовка в приложениях Win32
Не все приложения Win32 поддерживают темный режим, поэтому по умолчанию Windows предоставляет приложениям Win32 светлую строку заголовка. Если вы готовы поддерживать тёмный режим, вы можете попросить Windows отрисовать тёмную строку заголовка, когда тёмный режим включен.
Примечание.
В этой статье приведены примеры способов определения изменений темы системы и запрашивания светлой или темной строки заголовка окна приложения Win32. В статье не описаны особенности того, как изменить цвет пользовательского интерфейса приложения и отобразить его с помощью набора цветов темного режима.
Определение того, включен ли темный режим
Первый шаг — следить за самим параметром цветового режима. Это позволит настроить код цветового оформления и отображения приложения для использования цветового набора темного режима. Для этого приложение должно считывать параметр цвета при запуске и определять, когда параметры цвета изменяются во время сеанса приложения.
Чтобы сделать это в приложении Win32, используйте Windows::UI::Color и определите, можно ли классифицировать цвет как светлый или тёмный. Чтобы использовать Windows::UI::Color, импортируйте (в pch.h) заголовок Windows.UI.ViewManagement из winrt.
#include <winrt/Windows.UI.ViewManagement.h>
Также включите это пространство имен в main.cpp.
using namespace Windows::UI::ViewManagement;
В main.cpp с помощью этой функции определите, можно ли классифицировать цвет как светлый.
inline bool IsColorLight(Windows::UI::Color& clr)
{
return (((5 * clr.G) + (2 * clr.R) + clr.B) > (8 * 128));
}
Эта функция выполняет быстрое вычисление воспринимаемой яркости цвета и учитывает способы, с помощью которых различные каналы в значении цвета RGB влияют на то, насколько ярко цвет воспринимается человеческим глазом. Для повышения скорости на стандартных ЦП функция использует целочисленную математику.
Примечание.
Это не является моделью для реального анализа яркости цвета. Это полезно для быстрых вычислений, требующих определения того, можно ли классифицировать цвет как светлый или темный. Цвета темы часто могут быть светлыми, но не чисто-белыми, или темными, но не чисто-черными.
Теперь, когда у вас есть функция, которая проверяет, является ли цвет светлым, с ее помощью можно определить, включен ли темный режим.
Темный режим определяется как темный фон с контрастным светлым передним планом. Так как IsColorLight проверяет, является ли цвет светлым, с помощью функции можно узнать, является ли светлым передний план. Если передний план светлый, значит, включен темный режим.
Для этого необходимо получить тип цвета UI (пользовательского интерфейса) фона в системных настройках. Используйте этот код в main.cpp.
auto settings = UISettings();
auto foreground = settings.GetColorValue(UIColorType::Foreground);
UISettings позволяет получить все параметры пользовательского интерфейса, включая параметр цвета. Вызовите UISettings.GetColorValue(UIColorType::Foreground), чтобы получить значение цвета переднего плана из параметров пользовательского интерфейса.
Теперь вы можете выполнить проверку, чтобы узнать, считается ли передний план светлым (в main.cpp).
bool isDarkMode = static_cast<bool>(IsColorLight(foreground));
wprintf(L"\nisDarkMode: %u\n", isDarkMode);
- Если передний план светлый, то
isDarkModeбудет иметь значение 1 (true). Это означает, что включен темный режим. - Если передний план темный, то
isDarkModeбудет иметь значение 0 (false). Это означает, что темный режим не включен.
Чтобы автоматически отслеживать изменения параметров темного режима во время сеанса приложения, вы можете обернуть проверки следующим образом.
auto revoker = settings.ColorValuesChanged([settings](auto&&...)
{
auto foregroundRevoker = settings.GetColorValue(UIColorType::Foreground);
bool isDarkModeRevoker = static_cast<bool>(IsColorLight(foregroundRevoker));
wprintf(L"isDarkModeRevoker: %d\n", isDarkModeRevoker);
});
Полный код должен выглядеть примерно так:
inline bool IsColorLight(Windows::UI::Color& clr)
{
return (((5 * clr.G) + (2 * clr.R) + clr.B) > (8 * 128));
}
int main()
{
init_apartment();
auto settings = UISettings();
auto foreground = settings.GetColorValue(UIColorType::Foreground);
bool isDarkMode = static_cast<bool>(IsColorLight(foreground));
wprintf(L"\nisDarkMode: %u\n", isDarkMode);
auto revoker = settings.ColorValuesChanged([settings](auto&&...)
{
auto foregroundRevoker = settings.GetColorValue(UIColorType::Foreground);
bool isDarkModeRevoker = static_cast<bool>(IsColorLight(foregroundRevoker));
wprintf(L"isDarkModeRevoker: %d\n", isDarkModeRevoker);
});
static bool s_go = true;
while (s_go)
{
Sleep(50);
}
}
При выполнении этого кода:
Если включен темный режим, isDarkMode будет иметь значение 1.
При изменении параметра с темного режима на светлый isDarkModeRevoker будет иметь значение 0.
Включить темный режим для строк заголовка приложений Win32.
У Windows нет данных о том, может ли приложение поддерживать темный режим, поэтому предполагается, что оно не может поддерживать этот режим, из соображений обратной совместимости. Некоторые платформы разработки Windows, такие как Windows App SDK, поддерживают темный режим в собственном коде и изменяют определенные элементы пользовательского интерфейса без дополнительного кода. Приложения Win32 часто не поддерживают темный режим, поэтому по умолчанию Windows предоставляет приложениям Win32 светлую строку заголовка.
Но для любого приложения, использующего стандартную строку заголовка Windows, можно включить темную версию строки заголовка, если система находится в темном режиме. Чтобы включить темную строку заголовка, вызовите функцию диспетчера окон рабочего стола (DWM) с именем DwmSetWindowAttribute в окне верхнего уровня, используя атрибут окна DWMWA_USE_IMMERSIVE_DARK_MODE (DWM отображает атрибуты для окна).
В следующих примерах предполагается, что у вас есть окно со стандартной строкой заголовка, например окно, созданное с помощью этого кода.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
Сначала импортируйте API DWM, как показано ниже.
#include <dwmapi.h>
Затем определите макросы DWMWA_USE_IMMERSIVE_DARK_MODE над функцией InitInstance.
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
…
В результате с помощью API DWM вы сможете настроить темный цвет для заголовка строки. На этом этапе создается BOOL с именем value и ему присваивается значение TRUE.
BOOL позволяет активировать этот параметр атрибута Windows. Затем с помощью DwmSetWindowAttribute вы можете изменить атрибут окна для использования цветов темного режима.
BOOL value = TRUE;
::DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
Ниже назначение этого вызова описано более подробно.
Блок синтаксиса для DwmSetWindowAttribute выглядит примерно так:
HRESULT DwmSetWindowAttribute(
HWND hwnd,
DWORD dwAttribute,
[in] LPCVOID pvAttribute,
DWORD cbAttribute
);
После передачи hWnd (дескриптора окна, которое нужно изменить) как первого параметра, нужно передать DWMWA_USE_IMMERSIVE_DARK_MODE как параметр dwAttribute. Это константа в API DWM, которая обеспечивает отображение интерфейса Windows в цветах темного режима, когда включен системный параметр темного режима. Если вы переключитесь на светлый режим, вам нужно будет изменить значение DWMWA_USE_IMMERSIVE_DARK_MODE с 20 на 0, чтобы строка заголовка отображались в цветах светлого режима.
Параметр pvAttribute указывает на значение типа BOOL (поэтому вы установили значение BOOL ранее). Требуется, чтобы для pvAttribute было установлено значение TRUE. Это позволит применить для окна темный режим. Если для pvAttribute установлено значение FALSE, для окна будет использоваться светлый режим.
Наконец, для cbAttribute необходимо задать размер атрибута в pvAttribute. Чтобы сделать это легко, мы передаём sizeof(value).
Код для реализации темной строки заголовка окна должен выглядеть примерно так:
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
BOOL value = TRUE;
::DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
При выполнении этого кода заголовок окна приложения должен быть темным:
См. также
Windows developer