Partager via


Prendre en charge les thèmes Sombre et Clair dans les applications Win32

Windows prend en charge les thèmes Clair et Sombre comme option de personnalisation dans les paramètres Windows. Windows utilise le mode Clair par défaut, mais les utilisateurs peuvent le changer par le mode Sombre pour afficher une grande partie de l’interface utilisateur dans une couleur foncée. Les utilisateurs peuvent faire ce choix de paramètre afin de gagner en confort visuel dans les environnements moins lumineux, ou simplement parce qu’ils préfèrent l’esthétique d’une interface plus foncée de manière générale. De plus, les couleurs d’interface utilisateur plus foncées peuvent réduire l’utilisation de la batterie sur certains types d’écrans d’ordinateur, tels que les écrans OLED.

Image divisée d’une application avec un thème clair à gauche et un thème sombre à droite.

Nous faisons de notre mieux pour élargir la prise en charge du mode Sombre sans que cela provoque des changements cassants dans les applications existantes. Dans cette optique, nous fournissons des conseils techniques pour mettre à jour une application de bureau Windows (Win32) afin qu’elle prenne en charge les modes Clair et Sombre.

Description du mode Sombre et du mode Clair

Le mode couleur dans les paramètres (qui inclut les modes Clair et Sombre) est un paramètre qui définit les couleurs de premier plan et d’arrière-plan globales pour le système d’exploitation et les applications.

Mode Description Exemple
Clair Arrière-plan clair avec un premier plan foncé contrastant.

En mode Clair, vous verrez généralement du texte noir ou foncé sur des arrière-plans blancs ou clairs.
Capture d’écran de l’application Alarmes & horloge en mode clair
Foncé Arrière-plan foncé avec un premier plan clair contrastant.

En mode Sombre, vous verrez généralement du texte blanc ou clair sur des arrière-plans noirs ou foncés.
Capture d’écran de l’application Alarmes & horloge en mode sombre

Remarque

La raison pour laquelle nous utilisons du « noir ou foncé » et du « blanc ou clair » est qu’il existe d’autres couleurs, comme la couleur d’accentuation, qui peuvent teinter différentes couleurs de premier plan et d’arrière-plan. Vous pouvez donc voir du texte bleu clair sur un arrière-plan bleu foncé dans certaines parties de l’interface utilisateur. Cela reste acceptable pour une interface utilisateur en mode Sombre.

Du fait de la grande diversité des interfaces utilisateur dans les applications, le mode couleur ainsi que les couleurs de premier plan et d’arrière-plan sont davantage à considérer comme des bonnes pratiques que comme des règles strictes :

  • Les éléments de premier plan, les surbrillances et le texte doivent être d’une couleur plus proche de la couleur de premier plan que de la couleur d’arrière-plan.
  • Les grandes zones d’arrière-plan unies et les arrière-plans de texte doivent généralement être d’une couleur plus proche de la couleur d’arrière-plan que de la couleur de premier plan.

Dans la pratique, cela signifie qu’en mode Sombre, la majeure partie de l’interface utilisateur sera foncée et qu’en mode Clair, la majeure partie de l’interface utilisateur sera claire. Le concept d’un arrière-plan dans Windows est la grande zone de couleurs dans une application, ou la couleur de page. Le concept d’un premier plan dans Windows est la couleur de texte.

Astuce

Pour mieux comprendre l’idée que la couleur de premier plan est claire en mode Sombre et qu’elle est foncée en mode Clair, il est peut-être plus simple de considérer la couleur de premier plan comme la « couleur de texte par défaut ».

Activer la prise en charge du basculement des modes couleur

Beaucoup d’approches sont possibles pour implémenter la prise en charge du mode Sombre dans une application. Certaines applications contiennent deux jeux d’interfaces utilisateur (l’un de couleur claire et l’autre de couleur foncée). Certains frameworks d’interface utilisateur Windows, tels que WinUI 3, détectent automatiquement un thème système et adaptent l’interface utilisateur sur la base du thème système. Pour une prise en charge complète du mode Sombre, l’intégralité de la surface d’une application doit adopter le thème Sombre.

Il y a deux choses principales à faire dans votre application Win32 pour assurer la prise en charge des thèmes Clair et Sombre.

  • Comprendre les facteurs d’activation du mode Sombre

    En comprenant les facteurs d’activation du mode Sombre dans les paramètres système, vous pourrez plus facilement décider quand basculer l’interface utilisateur de votre application vers une interface utilisateur avec les thèmes foncés du mode Sombre.

  • Activer une barre de titre en mode Sombre dans les applications Win32

    Les applications Win32 ne prennent pas toutes en charge le mode Sombre. C’est pourquoi Windows utilise par défaut une barre de titre claire dans les applications Win32. Si vous êtes prêt à implémenter la prise en charge du mode Sombre, vous pouvez demander à Windows d’utiliser à la place la barre de titre foncée lorsque le mode Sombre est activé.

Note

Cet article fournit plusieurs exemples qui montrent les façons de détecter les modifications des thèmes système et d’activer une barre de titre claire ou foncée dans la fenêtre de votre application Win32. Il n’explique pas de manière spécifique comment repeindre et rendre l’interface utilisateur de votre application en utilisant un jeu de couleurs en mode Sombre.

Comprendre les facteurs d’activation du mode Sombre

La première étape est d’effectuer le suivi du paramètre du mode couleur proprement dit. Cela vous permettra d’ajuster le code de peinture et de rendu de votre application pour utiliser un jeu de couleurs en mode Sombre. Pour cela, l’application doit lire le paramètre de couleur au démarrage et détecter tout changement de ce paramètre durant une session d’application.

Pour implémenter ceci dans une application Win32, utilisez Windows::UI::Color et détectez si une couleur peut être classifiée comme une couleur claire ou sombre. Pour utiliser Windows::UI::Color, vous devez importer (dans pch.h) l’en-tête Windows.UI.ViewManagement de winrt.

#include <winrt/Windows.UI.ViewManagement.h>

Vous devez également ajouter cet espace de noms dans main.cpp.

using namespace Windows::UI::ViewManagement;

Dans main.cpp, utilisez cette fonction pour détecter si une couleur peut être classifiée comme claire.

inline bool IsColorLight(Windows::UI::Color& clr)
{
    return (((5 * clr.G) + (2 * clr.R) + clr.B) > (8 * 128));
}

Cette fonction effectue un calcul rapide de la luminosité perçue d’une couleur, et prend en compte les façons dont les différents canaux d’une valeur de couleur RVB contribuent à la perception de la luminosité par l’œil humain. Elle utilise des calculs mathématiques entiers pour plus de rapidité sur les processeurs standard.

Note

Ce modèle n’est pas destiné à une analyse réelle de la luminosité des couleurs. Il convient pour les calculs rapides visant à déterminer si une couleur peut être classifiée comme claire ou foncée. Les couleurs de thème peuvent souvent être claires, à l’exception du blanc pur, ou foncées, à l’exception du noir pur.

Maintenant que vous avez une fonction permettant de déterminer si une couleur est claire, vous pouvez l’utiliser pour détecter si le mode Sombre est activé.

Le mode Sombre correspond à un arrière-plan foncé avec un premier plan clair contrastant. Comme la fonction IsColorLight détermine si une couleur est considérée comme claire, vous pouvez l’utiliser pour détecter si le premier plan est clair. Si le premier plan est clair, cela signifie que le mode Sombre est activé.

Pour cela, vous devez obtenir le type de couleur du premier plan de l’interface utilisateur à partir des paramètres système. Utilisez ce code dans main.cpp.

auto settings = UISettings();
    
auto foreground = settings.GetColorValue(UIColorType::Foreground);

UISettings obtient tous les paramètres de l’interface utilisateur, dont la couleur. Appelez UISettings.GetColorValue(UIColorType::Foreground) pour obtenir la valeur de couleur de premier plan à partir des paramètres de l’interface utilisateur.

Vous pouvez maintenant déterminer si le premier plan est considéré comme clair (dans main.cpp).

bool isDarkMode = static_cast<bool>(IsColorLight(foreground));

wprintf(L"\nisDarkMode: %u\n", isDarkMode);
  • Si le premier plan est clair, isDarkMode a la valeur 1 (true), ce qui signifie que le mode Sombre est activé.
  • Si le premier plan est foncé, isDarkMode a la valeur 0 (false). C’est donc que le mode Sombre n’est pas activé.

Pour effectuer automatiquement le suivi des changements du paramètre du mode Sombre pendant une session d’application, vous pouvez inclure vos vérifications de la façon suivante.

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);
});

Au final, votre code doit ressembler à ceci.

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);
    }
}

À l’exécution de ce code :

Si le mode Sombre est activé, isDarkMode prend la valeur 1.

Capture d’écran d’une application en mode sombre.

Si le paramètre est changé du mode Sombre au mode Clair, isDarkModeRevoker prend la valeur 0.

Capture d’écran d’une application en mode clair.

Activer une barre de titre en mode Sombre dans les applications Win32

Windows ne sait pas si une application peut prendre en charge le mode Sombre. Pour garantir la compatibilité descendante, il suppose qu’elle ne peut pas. Certains frameworks de développement Windows, tels que le SDK Windows App, prennent en charge le mode Sombre de façon native et modifient certains éléments d’interface utilisateur sans code supplémentaire. Les applications Win32 ne prennent souvent pas en charge le mode Sombre. C’est pourquoi Windows utilise par défaut une barre de titre claire dans les applications Win32.

Toutefois, dans les applications qui utilisent la barre de titre standard de Windows, vous pouvez activer la version foncée de la barre de titre lorsque le système est en mode Sombre. Pour activer la barre de titre foncée, appelez une fonction Desktop Windows Manager (DWM) appelée DwmSetWindowAttribute sur votre fenêtre de niveau supérieur, en incluant l’attribut de fenêtre DWMWA_USE_IMMERSIVE_DARK_MODE. (DWM affiche les attributs d’une fenêtre.)

Les exemples suivants supposent que vous avez une fenêtre avec une barre de titre standard, comme celle créée par ce code.

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;
}

Tout d’abord, importez l’API DWM, comme ceci.

#include <dwmapi.h>

Ensuite, définissez les macros DWMWA_USE_IMMERSIVE_DARK_MODE au-dessus de votre fonction InitInstance.

#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
…

Enfin, vous pouvez utiliser l’API DWM pour définir la barre de titre sur une couleur foncée. Ici, vous créez un BOOL appelé value et vous lui attribuez la valeur TRUE. C’est ce BOOL qui déclenchera ce paramètre d’attribut Windows. Ensuite, vous spécifiez DwmSetWindowAttribute pour modifier l’attribut de fenêtre afin qu’il utilise les couleurs du mode Sombre.

BOOL value = TRUE;
::DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));

Voici en détail ce que fait cet appel.

Le bloc de syntaxe pour DwmSetWindowAttribute ressemble à ceci.

HRESULT DwmSetWindowAttribute(
       HWND    hwnd,
       DWORD   dwAttribute,
  [in] LPCVOID pvAttribute,
       DWORD   cbAttribute
);

Après avoir passé hWnd (handle de la fenêtre que vous souhaitez modifier) comme premier paramètre, vous devez passer DWMWA_USE_IMMERSIVE_DARK_MODE en tant que paramètre dwAttribute. Il s’agit d’une constante dans l’API DWM qui permet au cadre Windows d’être dessiné dans les couleurs du mode Sombre quand le paramètre système du mode Sombre est activé. Si vous basculez en mode Clair, vous devrez changer la valeur de DWMWA_USE_IMMERSIVE_DARK_MODE de 20 à 0 pour que la barre de titre soit dessinée dans les couleurs du mode Clair.

Le paramètre pvAttribute pointe vers une valeur de type BOOL (c’est pour cela que vous avez créé la valeur BOOL précédemment). Vous devez définir pvAttribute sur TRUE pour que la fenêtre s’affiche en mode Sombre. Si pvAttribute a la valeur FALSE, la fenêtre utilisera le mode Clair.

Enfin, cbAttribute doit avoir la même taille que l’attribut défini dans pvAttribute. Pour le faire rapidement, nous passons sizeof(value).

Votre code pour dessiner une barre de titre foncée dans la fenêtre doit ressembler à ceci.

#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;
}

Après exécution de ce code, la barre de titre de l’application doit normalement être de couleur foncée :

Capture d’écran d’une application avec une barre de titre sombre.

Voir aussi