Уведомление / способ подписки для изменения темы Windows 10

Как yolu, возможно, заметил, MS представила в Windows 10 современный вид «тематики», касающийся основных элементов ОС, таких как меню «Пуск» и панель задач. В более новых версиях вы можете выбрать «светлую» тему в качестве альтернативы черной теме по умолчанию.

Мне было интересно, есть ли API или крючок для элегантной и (что более важно) эффективной проверки в реальном времени на предмет изменений темы (не нашел ничего в документах MS по этому поводу, но достаточно часто эти драгоценные камни довольно скрыты там ИМХО).

Конкретная проблема: если у вас есть настольное приложение со значком на панели задач, высока вероятность, что вы создали его ярким. Почти все современные значки Windows имеют такой стиль (простой и белый, обеспечивающий хорошую читаемость на черной панели задач). Теперь вы можете предоставить другую версию в более темном стиле для светлой темы, но как заметить, когда применить это на лету?

Мне известен ключ реестра в HCU (Software / Microsoft / Windows / CurrentVersion / Themes / Personalize), который я использую прямо сейчас. Однако слепая проверка изменений каждые x миллисекунд кажется довольно неудобной.

Если такой возможности нет, я также рад услышать несколько идей по более эффективной реализации такой проверки.


person dfuchs    schedule 02.09.2019    source источник
comment
Класс WinRT UISettings предоставляет ColorValuesChanged событие. Начиная с этого ответа, я смог быстро собрать консольное приложение C ++ / WinRT, которое подписывается на это событие. Я оставляю это, чтобы сделать это реальным ответом для людей, более разбирающихся в C ++ / WinRT.   -  person zett42    schedule 02.09.2019
comment
Возможный дубликат Как определить подсветку Windows 10 / темный режим в приложении Win32?   -  person Christian.K    schedule 03.09.2019
comment
@ Christian.K Не совсем ИМХО, хотя есть некоторые совпадения. Следует различать тему приложения (фреймворк / API UWP) и системную тему - я воспользуюсь подсказкой от Strive Sun ATM   -  person dfuchs    schedule 03.09.2019


Ответы (1)


Метод 1. Используйте RegNotifyChangeKeyValue.

Уведомляет вызывающего абонента об изменениях атрибутов или содержимого указанного раздела реестра.

Метон 2: используйте WM_SETTINGCHANGE.

Приложения должны отправлять WM_SETTINGCHANGE всем окнам верхнего уровня, когда они вносят изменения в системные параметры. (Это сообщение нельзя отправить непосредственно в окно.) Чтобы отправить сообщение WM_SETTINGCHANGE всем окнам верхнего уровня, используйте функцию SendMessageTimeout с параметром hwnd, установленным на HWND_BROADCAST.

Я предпочитаю использовать второй метод, который я пробовал и успешно работал.

Пример минимального кода :

case WM_SETTINGCHANGE:
    {
        if (!lstrcmp(LPCTSTR(lParam), L"ImmersiveColorSet"))
        {
            //theme has been changed
        }
    }
person Strive Sun    schedule 02.09.2019
comment
Если явно не указано иное, реестр не является общедоступным программным интерфейсом. - person IInspectable; 02.09.2019
comment
@IInspectable thx, я предлагаю OP использовать второй метод для обнаружения изменений темы. - person Strive Sun; 03.09.2019
comment
@Strive Sun MSFT Спасибо за подсказку! Совершенно забыл про RegNotifyChangeKeyValue, но никогда не знал о WM_SETTINGCHANGE. Второй подход выглядит очень многообещающим для этого. - person dfuchs; 03.09.2019
comment
@ StriveSun-MSFT Где вы нашли ImmersiveColorSet в документации Microsoft? Ни Google, ни я не находим его ни в чем, на что ссылается WM_SETTINGCHANGE, кроме подобных ответов. Я рад, что нашел ответ, но хотел бы знать, что он задокументирован и, вероятно, останется надежным. - person Steve Valliere; 08.05.2020