Freigeben über


Unterstützen dunkler und heller Designs in Win32-Apps

In den Windows-Einstellungen werden helle und dunkle Designs als Personalisierungsoption unterstützt. Von Windows wird standardmäßig der helle Modus verwendet. Benutzer können jedoch den dunklen Modus auswählen. Dadurch wird ein Großteil der Benutzeroberfläche in einer dunklen Farbe dargestellt. Manche Benutzer bevorzugen diese Einstellung, weil sie bei schwacher Beleuchtung augenschonender ist. Andere bevorzugen einfach allgemein eine dunklere Benutzeroberfläche. Außerdem kann eine Benutzeroberfläche mit dunkleren Farben bei einigen Arten von Computerdisplays (beispielsweise bei OLED-Bildschirmen) die Akkulaufzeit verlängern.

A split image of an app in light theme on the left, and dark theme on the right.

Wir arbeiten kontinuierlich daran, die Unterstützung des dunklen Modus weiter auszubauen, ohne vorhandene Anwendungen zu beeinträchtigen. Hierzu bieten wir eine technische Anleitung, die zeigt, wie eine Win32-Desktop-App unter Windows aktualisiert wird, um sowohl den hellen als auch den dunklen Modus zu unterstützen.

Dunkler Modus im Vergleich zum hellen Modus

Der Farbmodus in den Einstellungen (einschließlich hellem und dunklem Modus) ist eine Einstellung, die die allgemeinen Farben für Vordergrund und Hintergrund des Betriebssystems und der Apps definiert.

Mode BESCHREIBUNG Beispiel
Hell Ein heller Hintergrund mit einem kontrastierenden dunklen Vordergrund.

Im hellen Modus wird in der Regel schwarzer oder dunkler Text auf weißem oder hellem Hintergrund angezeigt.
A screenshot of the Alarms & Clock app in light mode
Dunkel Ein dunkler Hintergrund mit einem kontrastierenden hellen Vordergrund.

Im dunklen Modus wird in der Regel weißer oder heller Text auf schwarzem oder dunklem Hintergrund angezeigt.
A screenshot of the Alarms & Clocks app in Dark mode

Hinweis

Wir sprechen von „schwarz oder dunkel“ und „weiß oder hell“, da es noch weitere Farben wie etwa die Akzentfarbe gibt, die verschiedene Vordergrund- und Hintergrundfarben farblich verändern kann. Wenn bei Ihnen also beispielsweise in einigen Bereichen der Benutzeroberfläche hellblauer Text auf einem dunkelblauen Hintergrund angezeigt wird, wäre das immer noch eine akzeptable Benutzeroberfläche mit dunklem Modus.

Aufgrund des breiten Spektrums an Benutzeroberflächen in verschiedenen Apps handelt es sich beim Farbmodus sowie bei den Vordergrund- und Hintergrundfarben eher um eine Richtlinie und weniger um eine feste Regel:

  • Vordergrundelemente, Hervorhebungen und Text sollten näher an der Vordergrundfarbe als an der Hintergrundfarbe sein.
  • Große, einfarbige Hintergrundbereiche und Texthintergründe sollten im Allgemeinen näher an der Hintergrundfarbe als an der Vordergrundfarbe sein.

In der Praxis bedeutet das, dass im dunklen Modus der Großteil der Benutzeroberfläche dunkel und im hellen Modus der Großteil der Benutzeroberfläche hell ist. Das Konzept eines Hintergrunds in Windows ist der große Bereich von Farben in einer App oder die Seitenfarbe. Das Konzept eines Vordergrunds in Windows ist die Textfarbe.

Tipp

Wenn es für Sie verwirrend ist, dass die Vordergrundfarbe im dunklen Modus hell und im hellen Modus dunkel ist, kann es hilfreich sein, sich die Vordergrundfarbe als Standardtextfarbe vorzustellen.

Aktivieren der Unterstützung des Farbmoduswechsels

Die Unterstützung des dunklen Modus kann auf unterschiedlichste Weise in einer Anwendung implementiert werden. Einige Apps enthalten zwei Arten von Benutzeroberflächen – eine mit einer hellen Farbe und eine mit einer dunklen Farbe. Einige Windows-Benutzeroberflächenframeworks (etwa WinUI 3) erkennen das Design eines Systems automatisch und passen die Benutzeroberfläche an das Systemdesign an. Um den dunklen Modus vollständig zu unterstützen, muss die gesamte Oberfläche einer App dem dunklen Design entsprechen.

Es gibt im Wesentlichen zwei Dinge, die Sie in Ihrer Win32-App umsetzen können, um sowohl ein helles als auch ein dunkles Design zu unterstützen.

  • Ermitteln des Aktivierungsstatus des dunklen Modus

    Es kann hilfreich sein, den Aktivierungsstatus des dunklen Modus in den Systemeinstellungen zu kennen, um die Benutzeroberfläche Ihrer App ggf. auf eine Benutzeroberfläche mit dunklem Design umzustellen.

  • Aktivieren einer Titelleiste für den dunklen Modus für Win32-Anwendungen

    Da nicht alle Win32-Anwendungen den dunklen Modus unterstützen, werden Win32-Apps von Windows standardmäßig mit einer hellen Titelleiste versehen. Wenn Sie den dunklen Modus unterstützen möchten, können Sie festlegen, dass Windows bei aktiviertem dunklem Modus die dunkle Titelleiste verwenden soll.

Hinweis

In diesem Artikel erfahren Sie anhand von Beispielen, wie Sie Systemdesignänderungen erkennen und eine helle oder dunkle Titelleiste für das Fenster Ihrer Win32-Anwendung anfordern. Spezifische Informationen zum Neuzeichnen und Rendern der Benutzeroberfläche Ihrer App mit einer Farbpalette für den dunklen Modus werden hier nicht behandelt.

Ermitteln des Aktivierungsstatus des dunklen Modus

Der erste Schritt besteht darin, die eigentliche Farbmoduseinstellung nachzuverfolgen. Dadurch können Sie den Zeichnungs- und Renderingcode Ihrer Anwendung anpassen, um eine Farbpalette für den dunklen Modus zu verwenden. Hierzu muss die App die Farbeinstellung beim Start lesen und wissen, wann sich die Farbeinstellung während einer App-Sitzung ändert.

Verwenden Sie dazu in einer Win32-Anwendung Windows::UI::Color, und ermitteln Sie, ob eine Farbe als hell oder dunkel klassifiziert werden kann. Für die Verwendung von Windows::UI::Color müssen Sie die Kopfzeile Windows.UI.ViewManagement aus „winrt“ importieren (in pch.h).

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

Schließen Sie diesen Namespace auch in main.cpp ein.

using namespace Windows::UI::ViewManagement;

Verwenden Sie in main.cpp die folgende Funktion, um zu ermitteln, ob eine Farbe als hell klassifiziert werden kann:

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

Diese Funktion führt eine schnelle Berechnung der wahrgenommenen Helligkeit einer Farbe durch und berücksichtigt, wie sich verschiedene Kanäle in einem RGB-Farbwert auf die Helligkeitswahrnehmung des menschlichen Auges auswirken. Sie verwendet rein ganzzahlige Mathematik, um auf typischen CPUs eine hohe Geschwindigkeit zu erzielen.

Hinweis

Dies ist kein Modell für eine echte Analyse der Farbhelligkeit. Es eignet sich gut für schnelle Berechnungen zur Bestimmung, ob sich eine Farbe als hell oder dunkel klassifizieren lässt. Designfarben sind oft hell, aber nicht rein weiß, oder dunkel, aber nicht rein schwarz.

Nachdem Sie nun über eine Funktion verfügen, um zu überprüfen, ob eine Farbe hell ist, können Sie mithilfe dieser Funktion ermitteln, ob der dunkle Modus aktiviert ist.

Der dunkle Modus ist als dunkler Hintergrund mit einem kontrastierenden hellen Vordergrund definiert. Da von IsColorLight überprüft wird, ob eine Farbe als helle Farbe betrachtet wird, können Sie mithilfe dieser Funktion ermitteln, ob der Vordergrund hell ist. Ist der Vordergrund hell, ist der dunkle Modus aktiviert.

Hierzu muss der Farbtyp des Vordergrunds der Benutzeroberfläche aus den Systemeinstellungen abgerufen werden. Verwenden Sie den folgenden Code in main.cpp:

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

Von UISettings werden alle Einstellungen der Benutzeroberfläche abgerufen – einschließlich Farbe. Rufen Sie UISettings.GetColorValue(UIColorType::Foreground) auf, um den Wert der Vordergrundfarbe aus den Benutzeroberflächeneinstellungen abzurufen.

Nun können Sie überprüfen, ob der Vordergrund als hell betrachtet wird (in main.cpp).

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

wprintf(L"\nisDarkMode: %u\n", isDarkMode);
  • Wenn der Vordergrund hell ist, ergibt die Auswertung von isDarkMode den Wert 1 (true), was bedeutet, dass der dunkle Modus aktiviert ist.
  • Ist der Vordergrund dunkel ist, ergibt die Auswertung von isDarkMode den Wert 0 (false), was bedeutet, dass der dunkle Modus nicht aktiviert ist.

Wenn Sie während einer App-Sitzung automatisch Änderungen der Einstellung für den dunklen Modus nachverfolgen möchten, können Sie Ihre Prüfungen wie folgt umschließen:

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

Ihr Code sollte wie folgt aussehen:

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

Wenn dieser Code ausgeführt wird, gilt Folgendes:

Wenn der dunkle Modus aktiviert ist, ergibt die Auswertung von isDarkMode den Wert 1:

A screenshot of an app in dark mode.

Wenn über die Einstellung vom dunklen Modus zum hellen Modus gewechselt wird, ergibt die Auswertung von isDarkModeRevoker den Wert 0:

A screenshot of an app in light mode.

Aktivieren einer Titelleiste für den dunklen Modus für Win32-Anwendungen

Da Windows nicht bekannt ist, ob der dunkle Modus von einer Anwendung unterstützt wird, wird aus Gründen der Abwärtskompatibilität davon ausgegangen, dass sie den dunklen Modus nicht unterstützt. Einige Windows-Entwicklungsframeworks (beispielsweise das Windows App SDK) unterstützen den dunklen Modus nativ und ändern bestimmte Benutzeroberflächenelemente ohne zusätzlichen Code. Von Win32-Anwendungen wird der dunkle Modus häufig nicht unterstützt. Daher werden Win32-Apps von Windows standardmäßig mit einer hellen Titelleiste versehen.

Für Apps, die die standardmäßige Windows-Titelleiste verwenden, kann jedoch die dunkle Version der Titelleiste aktiviert werden, wenn sich das System im dunklen Modus befindet. Rufen Sie zum Aktivieren der dunklen Titelleiste eine DWM-Funktion (Desktop Windows Manager, Desktopfenster-Manager) namens DwmSetWindowAttribute für Ihr übergeordnetes Fenster auf, und verwenden Sie dabei das Fensterattribut DWMWA_USE_IMMERSIVE_DARK_MODE. (DWM rendert Attribute für ein Fenster.)

In den folgenden Beispielen wird davon ausgegangen, dass Sie über ein Fenster mit einer Standardtitelleiste verfügen – beispielsweise über die, die im folgenden Code erstellt wird:

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

Als Erstes muss die DWM-API wie folgt importiert werden:

#include <dwmapi.h>

Definieren Sie dann die DWMWA_USE_IMMERSIVE_DARK_MODE-Makros über Ihrer InitInstance-Funktion:

#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
…

Abschließend können Sie die DWM-API verwenden, um die Titelleiste auf eine dunkle Farbe festzulegen. Hier wird ein boolescher Wert (BOOL) namens value erstellt und auf TRUE festgelegt. Der boolesche Wert (BOOL) wird verwendet, um diese Windows-Attributeinstellung auszulösen. Anschließend wird DwmSetWindowAttribute verwendet, um das Fensterattribut zu ändern, sodass Farben für den dunklen Modus verwendet werden.

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

Im Anschluss erfahren Sie mehr über diesen Aufruf.

Der Syntaxblock für DwmSetWindowAttribute sieht wie folgt aus:

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

Nach der Übergabe von hWnd (das Handle für das zu ändernde Fenster) als erster Parameter muss DWMWA_USE_IMMERSIVE_DARK_MODE als dwAttribute-Parameter übergeben werden. Hierbei handelt es sich um eine Konstante in der DWM-API, mit der der Windows-Rahmen in Farben des dunklen Modus dargestellt werden kann, wenn die Systemeinstellung für den dunklen Modus aktiviert ist. Wenn Sie zum hellen Modus wechseln, muss DWMWA_USE_IMMERSIVE_DARK_MODE von 20 in 0 geändert werden, damit die Titelleiste in Farben des hellen Modus dargestellt wird.

Der pvAttribute-Parameter verweist auf einen Wert vom Typ BOOL. (Aus diesem Grund wurde zuvor der BOOL-Wert erstellt.) pvAttribute muss TRUE sein, damit der dunkle Modus für das Fenster verwendet wird. Wenn pvAttribute den Wert FALSE hat, wird für das Fenster der helle Modus verwendet.

cbAttribute muss außerdem über die Größe des Attributs verfügen, das in pvAttribute festgelegt wird. Hierzu wird einfach sizeof(value) übergeben.

Ihr Code zum Zeichnen einer dunklen Fenstertitelleiste sollte wie folgt aussehen:

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

Wenn dieser Code ausgeführt wird, sollte die App-Titelleiste dunkel sein:

A screenshot of an app with a dark title bar.

Siehe auch