Condividi tramite


Supportare i temi Scuro e Chiaro nelle app Win32

Windows supporta i temi Chiaro e Scuro come opzione di personalizzazione nelle impostazioni di Windows. Windows usa la modalità chiara per impostazione predefinita, ma gli utenti possono scegliere la modalità scura, che cambia gran parte dell'interfaccia utente in un colore scuro. Gli utenti potrebbero preferire questa impostazione perché affatica meno gli occhi in ambienti con luce bassa o potrebbero semplicemente preferire un'interfaccia più scura in generale. Inoltre, i colori dell'interfaccia utente più scuri possono ridurre l'utilizzo della batteria in alcuni tipi di schermi del computer, ad esempio schermi OLED.

Immagine divisa di un'app in tema chiaro a sinistra e in tema scuro a destra.

Stiamo lavorando duramente per ampliare il supporto per la modalità scura senza interrompere le applicazioni esistenti e, a tale scopo, forniamo indicazioni tecniche per l'aggiornamento di un'app di Windows desktop Win32 per supportare le modalità chiara e scura.

Modalità scura o modalità chiara

La Modalità colore nelle impostazioni (che include le modalità chiara e scura) è un'impostazione che definisce i colori generali di primo piano e di sfondo per il sistema operativo e le app.

Mode Descrizione Esempio
Chiaro Sfondo chiaro con un primo piano scuro a contrasto.

In modalità chiara, in genere si visualizzerà testo nero o scuro su sfondi bianchi o chiari.
Screenshot dell'app Sveglie & Orologio in modalità chiara
Scuro Uno sfondo scuro con un primo piano chiaro a contrasto.

In modalità scura, in genere si visualizzerà testo bianco o chiaro su sfondi neri o scuri.
Screenshot dell'app Allarmi & Orologi in modalità scura

Nota

Il motivo per cui usiamo "nero o scuro" e "bianco o chiaro" è perché ci sono colori aggiuntivi, come il colore principale, che possono cambiare le tonalità di vari colori in primo e secondo piano. Quindi potresti vedere testo blu chiaro su uno sfondo blu scuro in alcune parti dell'interfaccia utente, che sarebbe ancora considerato accettabile in un'interfaccia utente in modalità scura.

A causa dell'ampia diversità dell'interfaccia utente in app diverse, la modalità colore e i colori di primo piano e di sfondo rappresentano più linee guida direzionali che regole rigide:

  • Gli elementi in primo piano, le evidenziazioni e il testo devono essere più vicini al colore di primo piano rispetto al colore di sfondo.
  • Le aree di sfondo grandi a tinta unita e gli sfondi di testo devono in genere essere più vicini al colore di sfondo rispetto al colore di primo piano.

In pratica, ciò significa che in modalità scura, la maggior parte dell'interfaccia utente sarà scura e in modalità chiara la maggior parte dell'interfaccia utente sarà chiara. Il concetto di sfondo in Windows è l'area estesa dei colori in un'app o il colore della pagina. Il concetto di primo piano in Windows è il colore del testo.

Suggerimento

Se si ritiene che il colore di primo piano sia chiaro in modalità Scura e scuro in modalità chiara, può essere utile considerare il colore di primo piano come "il colore di testo predefinito".

Abilita il supporto per la modifica della modalità colore

Esistono molti approcci per implementare il supporto per la modalità scura in un'applicazione. Alcune app contengono due set di interfacce utente (una con un colore chiaro e una con un colore scuro). Alcuni framework interfaccia utente di Windows, ad esempio WinUI 3, rilevano automaticamente il tema di un sistema e regolano l'interfaccia utente per seguire il tema del sistema. Per supportare completamente la modalità scura, l'intera superficie di un'app deve seguire il tema scuro.

Ci sono due azioni principali che puoi svolgere nella tua app Win32 per supportare entrambi i temi chiaro e scuro.

  • Scopri quando la modalità scura è abilitata

    Sapere quando la modalità scura è abilitata nelle impostazioni di sistema può aiutarti a sapere quando cambiare l'interfaccia utente dell'app a un'interfaccia utente in modalità scura.

  • Abilita una barra del titolo in modalità scura per le applicazioni Win32

    Non tutte le applicazioni Win32 supportano la modalità scura, quindi Windows offre alle app Win32 una barra del titolo chiaro per impostazione predefinita. Se hai intenzione di supportare la modalità scura, puoi chiedere a Windows di disegnare la barra del titolo scuro quando è abilitata la modalità scura.

Nota

Questo articolo fornisce esempi di modi per rilevare le modifiche del tema di sistema e richiedere una barra del titolo chiara o scura per la finestra dell'applicazione Win32. Non indica informazioni specifiche su come cambiare tonalità ed eseguire il rendering dell'interfaccia utente dell'app usando un set di colori in modalità scura.

Scopri quando la modalità scura è abilitata

Il primo passaggio consiste nel tenere traccia dell'impostazione della stessa modalità colore. In questo modo sarà possibile modificare il codice di disegno e rendering dell'applicazione per usare un set di colori in modalità scura. In questo modo, l'app deve leggere l'impostazione del colore all'avvio e sapere quando cambia durante una sessione dell'app.

A tale scopo in un'applicazione Win32, usa Windows::UI::Color e rileva se un colore può essere classificato come chiaro o scuro. Per usare Windows::UI::Color, devi importare (in pch.h) l'intestazione Windows.UI.ViewManagement da winrt.

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

Includi anche lo spazio dei nomi in main.cpp.

using namespace Windows::UI::ViewManagement;

In main.cpp, usa questa funzione per rilevare se un colore può essere classificato come chiaro.

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

Questa funzione esegue un rapido calcolo della luminosità percepita di un colore e prende in considerazione i modi in cui i diversi canali in un valore di colore RGB contribuiscono alla luminosità dell'occhio umano. Usa la matematica all-integer per la velocità nelle CPU tipiche.

Nota

Questo non è un modello per l'analisi reale della luminosità del colore. È utile per calcoli rapidi che richiedono di determinare se un colore può essere classificato come chiaro o scuro. I colori del tema possono spesso essere chiari o scuri, ma non rispettivamente color bianco puro o nero puro.

Ora che è disponibile una funzione per verificare se un colore è chiaro, è possibile usare tale funzione per rilevare se la modalità scura è abilitata.

La modalità scura è definita come sfondo scuro con un primo piano chiaro a contrasto. Poiché IsColorLight controlla se un colore è considerato chiaro, è possibile usare tale funzione per verificare se il primo piano è chiaro. Se il primo piano è chiaro, la modalità scura è abilitata.

A tale scopo, è necessario ottenere il tipo di colore dell'interfaccia utente in primo piano dalle impostazioni di sistema. Usa questo codice in main.cpp.

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

UISettings ottiene tutte le impostazioni dell'interfaccia utente, incluso il colore. Chiama UISettings.GetColorValue(UIColorType::Foreground) per ottenere il valore del colore di primo piano dalle impostazioni dell'interfaccia utente.

È ora possibile eseguire un controllo per verificare se il primo piano è considerato chiaro (in main.cpp).

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

wprintf(L"\nisDarkMode: %u\n", isDarkMode);
  • Se il primo piano è chiaro, isDarkMode restituirà 1 (true) ovvero la modalità scura è abilitata.
  • Se il primo piano è scuro, isDarkMode restituirà 0 (false) il che significa che la modalità scura non è abilitata.

Per tenere traccia automaticamente del momento in cui l'impostazione della modalità scura cambia durante una sessione dell'app, è possibile eseguire il wrapping dei controlli in questo modo.

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

Il codice completo dovrebbe essere simile al seguente.

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

Quando viene eseguito questo codice:

Se la modalità scura è abilitata, isDarkMode restituirà 1.

Screenshot di un'app in modalità scura.

La modifica dell'impostazione dalla modalità scura alla modalità chiara comporterà la restituzione di 0 da parte di isDarkModeRevoker.

Screenshot di un'app in modalità chiara.

Abilita una barra del titolo in modalità scura per le applicazioni Win32

Windows non sa se un'applicazione può supportare la modalità scura, quindi presuppone che non possa per motivi di compatibilità con le versioni precedenti. Alcuni framework di sviluppo di Windows, ad esempio Windows App SDK, supportano la modalità scura in modo nativo e modificano determinati elementi dell'interfaccia utente senza codice aggiuntivo. Le app Win32 spesso non supportano la modalità scura, quindi Windows offre alle app Win32 una barra del titolo chiara per impostazione predefinita.

Tuttavia, per qualsiasi app che usa la barra del titolo standard di Windows, puoi abilitare la versione scura della barra quando il sistema è in modalità scura. Per abilitare la barra del titolo scura, scegli una funzione Desktop Windows Manager (DWM) denominata DwmSetWindowAttribute nella finestra di primo livello, usando l'attributo della finestra DWMWA_USE_IMMERSIVE_DARK_MODE. (DWM esegue il rendering degli attributi per una finestra.)

Gli esempi seguenti presuppongono che sia presente una finestra con una barra del titolo standard, ad esempio quella creata da questo codice.

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

Prima di tutto, è necessario importare l'API DWM, come illustrato di seguito.

#include <dwmapi.h>

Definisci quindi le macro DWMWA_USE_IMMERSIVE_DARK_MODE sopra la funzione InitInstance.

#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
…

Infine, è possibile usare l'API DWM per impostare la barra del titolo per usare un colore scuro. In questo caso, viene creato un BOOL denominato value e impostato su TRUE. Questo BOOL viene usato per attivare questa impostazione dell'attributo di Windows. Usare quindi DwmSetWindowAttribute per modificare l'attributo della finestra in modo da usare i colori della modalità scura.

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

Ecco una spiegazione più dettagliata di ciò che fa questa chiamata.

Il blocco di sintassi per DwmSetWindowAttribute è simile al seguente.

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

Dopo aver passato hWnd (l'handle alla finestra da modificare) come primo parametro, è necessario passare a DWMWA_USE_IMMERSIVE_DARK_MODE come parametro dwAttribute. Si tratta di una costante nell'API DWM che consente di disegnare il frame di Windows nei colori in modalità scura quando l'impostazione di sistema modalità scura è abilitata. Se si passa alla modalità chiara, sarà necessario cambiare DWMWA_USE_IMMERSIVE_DARK_MODE da 20 a 0 per disegnare la barra del titolo nei colori della modalità chiara.

Il parametro pvAttribute punta a un valore di tipo BOOL (motivo per cui è stato creato il valore BOOL in precedenza). pvAttribute deve essere TRUE per rispettare la modalità scura per la finestra. Se pvAttribute è FALSE, la finestra userà la modalità chiara.

Infine, cbAttribute deve avere le dimensioni dell'attributo impostato in pvAttribute. Per eseguire facilmente questa operazione, passiamo a sizeof(value).

Il codice per disegnare una barra del titolo delle finestre scura dovrebbe avere un aspetto simile al seguente.

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

Quando questo codice viene eseguito, la barra del titolo dell'app deve essere scura:

Screenshot di un'app con barra del titolo scura.

Vedi anche