Win32 uygulamalarında Koyu ve Açık temaları destekleme

Windows, Windows ayarlarında kişiselleştirme seçeneği olarak Açık ve Koyu temaları destekler. Windows varsayılan olarak Açık modu kullanır, ancak kullanıcılar koyu modu seçebilir ve bu da kullanıcı arabiriminin büyük bir kısmını koyu renge dönüştürür. Kullanıcılar, düşük ışıklı ortamlarda gözlerde daha kolay olduğundan veya genel olarak daha koyu bir arabirimi tercih ettiğinden bu ayarı tercih edebilir. Ayrıca, daha koyu ui renkleri OLED ekranlar gibi bazı bilgisayar ekranlarında pil kullanımını azaltabilir.

Soldaki açık temada bir uygulamanın bölünmüş görüntüsü ve sağda koyu tema.

Mevcut uygulamaları bozmadan Koyu mod desteğini genişletmek için çok çalışıyoruz ve bu amaçla hem Açık hem de Koyu modlarını desteklemek için Win32 masaüstü Windows app güncelleştirmeye yönelik teknik rehberlik sağlıyoruz.

Koyu mod ile Açık mod karşılaştırması

Ayarlardaki Renk Modu (Açık ve Koyu modları içerir), işletim sistemi ve uygulamalar için genel ön plan ve arka plan renklerini tanımlayan bir ayardır.

Modül Açıklama Örnek
Işık Açık bir arka plan ve karşıt koyu bir ön plan.

Açık Modda genellikle beyaz veya açık arka planlarda siyah veya koyu metin görürsünüz.
Açık modda Alarmlar ve Saat uygulamasının ekran görüntüsü
Koyu Kontrast oluşturan açık bir ön plana sahip koyu arka plan.

Koyu modda, genellikle siyah veya koyu arka planlarda beyaz veya açık metin görürsünüz.
Koyu modda Alarmlar ve Saatler uygulamasının ekran görüntüsü

Uyarı

"Siyah veya koyu" ve "beyaz veya açık" kullanmamızın nedeni, çeşitli ön plan ve arka plan renklerini tonlayabilen Vurgu rengi gibi ek renklerin olmasıdır." Bu nedenle, kullanıcı arabiriminin bazı bölümlerinde koyu mavi arka planda açık mavi metin görebilirsiniz ve bu da Koyu mod kullanıcı arabirimi olarak kabul edilebilir.

Farklı uygulamalarda kullanıcı arabiriminin çok çeşitli olması nedeniyle renk modu, ön plan ve arka plan renkleri, sabit bir kuraldan çok yönlü bir yönerge olarak tasarlanmıştır:

  • Ön plan öğeleri, vurgular ve metinler arka plan rengine göre ön plan rengine daha yakın olmalıdır.
  • Büyük, düz arka plan alanları ve metin arka planları genellikle arka plan rengine ön plan renginden daha yakın olmalıdır.

Pratikte bu, Koyu modda kullanıcı arabiriminin çoğunun koyu, Açık modda ise kullanıcı arabiriminin çoğunun açık olacağı anlamına gelir. Windows'ta arka plan kavramı, bir uygulamadaki geniş renk alanı veya sayfa rengidir. Windows'ta ön plan kavramı metin rengidir.

Tavsiye

Ön plan renginin Koyu modda açık ve Açık modda koyu olmasını kafa karıştırıcı bulursanız, ön plan rengini "varsayılan metin rengi" olarak düşünmenize yardımcı olabilir.

Renk modlarını değiştirme desteğini etkinleştirme

Bir uygulamada Koyu mod desteği uygulamak için birçok yaklaşım vardır. Bazı uygulamalar iki kullanıcı arabirimi kümesi içerir (biri açık renkli, diğeri koyu renkli). WinUI 3 gibi bazı Windows UI çerçeveleri bir sistemin temasını otomatik olarak algılar ve kullanıcı arabirimini sistem temasını izleyecek şekilde ayarlar. Koyu modu tam olarak desteklemek için bir uygulamanın yüzeyinin tamamı koyu temayı takip etmelidir.

Win32 uygulamanızda hem Açık hem de Koyu temaları desteklemek için yapabileceğiniz iki temel şey vardır.

  • Koyu modun ne zaman etkinleştirildiğini bilin

    Sistem ayarlarında Koyu modun ne zaman etkinleştirildiğini bilmek, uygulama kullanıcı arabiriminizi Koyu mod temalı bir kullanıcı arabirimine ne zaman değiştirebileceğinizi bilmenize yardımcı olabilir.

  • Win32 uygulamaları için Koyu mod başlık çubuğunu etkinleştirme

    Tüm Win32 uygulamaları Koyu modu desteklemediğinden Windows, Win32 uygulamalarına varsayılan olarak açık bir başlık çubuğu sağlar. Koyu modu desteklemeye hazırsanız, Koyu mod etkinleştirildiğinde Windows'dan bunun yerine koyu başlık çubuğunu çizmesini isteyebilirsiniz.

Uyarı

Bu makalede, sistem teması değişikliklerini algılamanın ve Win32 uygulamanızın penceresi için açık veya koyu başlık çubuğu istemenin yollarının örnekleri sağlanır. Koyu mod renk kümesi kullanarak uygulama kullanıcı arabiriminizi yeniden boyama ve işleme ile ilgili ayrıntıları kapsamaz.

Koyu modun ne zaman etkinleştirildiğini öğrenme

İlk adım, renk modu ayarının kendisini izlemektir. Bu, uygulamanızın boyama ve işleme kodunu Koyu mod renk kümesi kullanacak şekilde ayarlamanıza olanak sağlar. Bunu yapmak için uygulamanın başlangıçta renk ayarını okuması ve bir uygulama oturumu sırasında renk ayarının ne zaman değiştiğini bilmesi gerekir.

Bir Win32 uygulamasında bunu yapmak için Windows::UI::Color kullanın ve bir rengin light veya dark olarak sınıflandırılabileceğini algılayın. Windows::UI::Colorkullanmak için, winrt'ten pch.h üst bilgisini Windows.UI.ViewManagementiçinde içeri aktarmanız gerekir.

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

Ayrıca bu ad alanını main.cppekleyin.

using namespace Windows::UI::ViewManagement;

içinde main.cpp, bir rengin açık olarak sınıflandırılabilir olup olmadığını algılamak için bu işlevi kullanın.

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

Bu işlev, bir rengin algılanan parlaklığını hızlı bir şekilde hesaplar ve RGB renk değerindeki farklı kanalların insan gözüne ne kadar parlak göründüğüne katkıda bulunma yollarını dikkate alır. Tipik CPU'larda hız için all-integer matematik kullanır.

Uyarı

Bu, renk parlaklığının gerçek analizi için bir model değildir. Bir rengin açık veya koyu olarak sınıflandırılıp sınıflandırılmadığını saptamanızı gerektiren hızlı hesaplamalar için iyidir. Tema renkleri genellikle açık olabilir, ancak saf beyaz veya koyu olmayabilir, ancak saf siyah olamaz.

Artık rengin açık olup olmadığını denetleyebileceğiniz bir işleviniz olduğuna göre, Koyu modun etkinleştirilip etkinleştirilmediğini algılamak için bu işlevi kullanabilirsiniz.

Koyu mod, karşıtlıklı açık ön plana sahip koyu arka plan olarak tanımlanır. Bir rengin açık kabul edilip değerlendirilmediğini denetlediğinden IsColorLight , ön planın açık olup olmadığını görmek için bu işlevi kullanabilirsiniz. Ön plan açıksa Koyu mod etkinleştirilir.

Ön planın kullanıcı arabirimi renk türünü sistem ayarlarından almak için bunu yapmanız gerekir. Bu kodu içinde main.cpp kullanın.

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

UISettings , renk dahil olmak üzere kullanıcı arabiriminin tüm ayarlarını alır. Ui ayarlarından ön plan renk değerini almak için UISettings.GetColorValue(UIColorType::Foreground) öğesini çağırın.

Artık ön planın (main.cpp) hafif kabul edilip edilmediğini görmek için bir kontrol çalıştırabilirsiniz.

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

wprintf(L"\nisDarkMode: %u\n", isDarkMode);
  • Ön plan açıksa, isDarkMode Koyu modun etkin olduğu anlamına gelen 1 (true) olarak değerlendirilir.
  • Ön plan koyuysa, isDarkMode Koyu modun etkin olmadığı anlamına gelen 0 (false) olarak değerlendirilir.

Uygulama oturumu sırasında Koyu mod ayarının ne zaman değiştiğini otomatik olarak izlemek için, denetimlerinizi şöyle kaydırabilirsiniz.

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

Tam kodunuz şöyle görünmelidir.

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

Bu kod çalıştırıldığında:

Koyu mod etkinleştirildiyse, isDarkMode 1 olarak değerlendirilir.

Koyu modda bir uygulamanın ekran görüntüsü.

Ayarın Koyu moddan Açık moda isDarkModeRevoker değiştirilmesi 0 olarak değerlendirilir.

Açık modda bir uygulamanın ekran görüntüsü.

Win32 uygulamaları için Koyu mod başlık çubuğunu etkinleştirme

Windows, bir uygulamanın Koyu modu destekleyebileceğinden emin olmadığından geriye dönük uyumluluk nedeniyle destekleyemediğini varsayar. Windows App SDK gibi bazı Windows geliştirme çerçeveleri Koyu modu yerel olarak destekler ve ek kod olmadan belirli kullanıcı arabirimi öğelerini değiştirir. Win32 uygulamaları genellikle Koyu modu desteklemez, bu nedenle Windows varsayılan olarak Win32 uygulamalarına açık bir başlık çubuğu sağlar.

Ancak standart Windows başlık çubuğunu kullanan tüm uygulamalar için sistem Koyu moddayken başlık çubuğunun koyu sürümünü etkinleştirebilirsiniz. Koyu başlık çubuğunu etkinleştirmek için, DWMWA_USE_IMMERSIVE_DARK_MODE pencere özniteliğini kullanarak üst düzey pencerenizde DwmSetWindowAttribute adlı bir Masaüstü Windows Yöneticisi (DWM) işlevini çağırın. (DWM, bir pencere için öznitelikleri işler.)

Aşağıdaki örneklerde, bu kod tarafından oluşturulan gibi standart başlık çubuğu içeren bir pencereniz olduğu varsayılır.

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

İlk olarak, DWM API'sini aşağıdaki gibi içeri aktarmanız gerekir.

#include <dwmapi.h>

Ardından işlevinizin DWMWA_USE_IMMERSIVE_DARK_MODE üzerindeki makroları tanımlayınInitInstance.

#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
…

Son olarak, başlık çubuğunu koyu renk kullanacak şekilde ayarlamak için DWM API'sini kullanabilirsiniz. Burada, BOOL adlı bir value oluşturulup TRUEolarak ayarlanır. Bu BOOL , bu Windows öznitelik ayarını tetiklemede kullanılır. Ardından, pencere özniteliğini Koyu mod renklerini kullanacak şekilde değiştirmek için kullanırsınız DwmSetWindowAttribute .

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

Bu çağrının ne yaptığına ilişkin daha fazla açıklama aşağıdadır.

DwmSetWindowAttribute söz dizimi bloğu şöyle görünür.

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

İlk parametreniz olarak hWnd'ı (değiştirmek istediğiniz pencere tutamacını) geçirdikten sonra, DWMWA_USE_IMMERSIVE_DARK_MODE parametresini dwAttribute olarak geçirmeniz gerekir. Bu, DWM API'sinde, Koyu mod sistem ayarı etkinleştirildiğinde Windows çerçevesinin Koyu mod renklerinde çizilmesine olanak tanıyan bir sabittir. Açık moda geçerseniz, başlık çubuğunun açık mod renklerinde çizilmesi için 20'den 0'a değiştirmeniz DWMWA_USE_IMMERSIVE_DARK_MODE gerekir.

pvAttribute parametresi BOOL türünde bir değeri gösterir ve bu yüzden BOOL değerini daha önce oluşturdunuz. pvAttribute'ın pencere için Koyu modu onurlandırması amacıyla TRUE olması gerekir. Eğer pvAttributeFALSE ise, pencere Açık Mod kullanacaktır.

Son olarak, cbAttribute içinde ayarlanan pvAttributeözniteliğin boyutuna sahip olması gerekir. Bunu kolayca yapmak için, sizeof(value) geçiririz.

Koyu renkli pencere başlık çubuğu çizme kodunuz şöyle görünmelidir.

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

Bu kod çalıştırıldığında uygulama başlık çubuğu koyu olmalıdır:

Koyu başlık çubuğuna sahip bir uygulamanın ekran görüntüsü.

Ayrıca bakınız