Индикатор раскладки клавиатуры цветом панели задач и заголовка окна в современных версиях Windows при помощи DWM

в 7:24, , рубрики: .net, api, WinAPI, разработка под windows, раскладка клавиатуры

Индикатор раскладки клавиатуры в Windows — довольно незаметная штука. Набранные на автомате не в той раскладке буквы всегда расстраивают. По крайней мере, меня. Поэтому мне всегда хотелось иметь настолько заметный индикатор текущей раскладки клавиатуры, насколько это вообще возможно. Ну хотя бы такой, с которым не нужно бегать взглядом по экрану.

Идеальным вариантом было бы пристроить небольшой индикатор прямо рядом с курсором в поле ввода, но это оказалось сложной задачей: некоторые приложения вообще не используют системный курсор. Простым и достаточно удобным решением проблемы оказалась смена цвета панели задач и заголовка окна во всей системе. Как оказалось, это можно делать программно при помощи недокументированных возможностей Desktop Window Manager API…

Итак, мы хотим менять цвет темы Windows (цвет панели задач и заголовков окон) для того, чтобы максимально наглядно видеть текущую раскладку клавиатуры. Мы будем менять цвет темы Aero, то есть поддерживаются только версии, начиная с Vista.

Первым делом мы запускаем монитор текущей раскладки клавиатуры. Он устанавливает Windows Shell Hook (WH_SHELL) для того, чтобы отслеживать смену раскладки. Если быть точным, то отслеживается не изменение раскладки, а изменение языка ввода. К сожалению, такое решение не подходит для людей, которые используют несколько разных раскладок для одного (например, японского) языка. В обработчике мы реагируем только на событие HSHELL_LANGUAGE и посылаем нашему основному приложению информацию о новом выбранном языке простым сообщением Windows.

Маленькая техническая особенность заключается в том, что обработчик shell hook обязательно должен быть размещен в DLL, а никак не в исполняемом файле. Поэтому установка обработчика вынесена в маленькую, написанную на C++ библиотеку Hooker.

Тут есть несколько важных моментов, касающихся, во-первых, 32- и 64-битных версий Windows, а во-вторых, UAC и «режима администратора».

Дело в том, что для того, чтобы перехватывать событие смены языка и в 32- и в 64-битных приложениях в 64-битной версии Windows, необходимо отдельно установить 32- и 64-битный обработчики. Поэтому библиотечка Hooker и контролирующее ее приложение HookerWatcher собираются для обеих архитектур, и основное приложение запускает обе версии.

Отдельную проблему представляет из себя «режим администратора». Фактически, приложения, работающие от имени администратора, полностью отделены от приложений без повышенных привилегий. Поэтому для того, чтобы подсветка текущего языка ввода работала и в этой изолированной среде, в режиме администратора shell hooks для обеих архитектур нужно устанавливать еще раз. Этим я заниматься уже не стал: при необходимости можно просто запустить второй экземпляр всего приложения «от имени администратора», и все будет работать как следует.

Для того, чтобы управлять цветом темы Windows мы будем использовать появившееся в Vista API Desktop Window Manager. Именно эта библиотека управляет отображением окон в последних версиях Windows.

  • DwmIsCompositionEnabled – проверяем, что DWM работает;
  • DwmGetColorizationParameters – получаем текущие цвета темы Windows;
  • DwmSetColorizationParameters – устанавливаем текущие цвета темы Windows.

Настройка цвета определяется структурой WDM_COLORIZATION_PARAMS, не описанной в документации DWM и найденной в немецком разделе форума MSDN. Для простоты в настройках приложения мы предлагаем пользователю самостоятельно изменить цвета темы Windows и указать, что текущий цвет нужно использовать для одного основного языка, либо для всех остальных. То есть, в настройках приложения мы храним только два экземпляра структуры WDM_COLORIZATION_PARAMS – для «основного» языка и для всех остальных.

Основное приложение использует Windows Forms, состоит из одной формы с перегруженным методом WndProc, в котором и обрабатываются сообщения, полученные от монитора текущего языка. Получив уведомление о смене языка, приложение устанавливает цвет темы Windows методом DwmSetColorizationParameters.

Кстати, в Windows 7 можно было наблюдать довольно забавное поведение индикатора текущего языка в быстром поиске в меню «Пуск»: после ввода символа в русской раскладке язык на мгновение переключался на английский и обратно. И, соответственно, при вводе очередной буквы мигал индикатор. А встроенный индикатор раскладки реагировал с заметной задержкой, и у него такой проблемы с морганием не было. В Windows 8 встроенный индикатор работает уже мгновенно.

С исходниками можно познакомиться на GitHub здесь, а релизную версию скачать тут.

Автор: Codenamed

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js