Індикатор розкладки клавіатури кольором панелі завдань і заголовка вікна у сучасних версіях Windows за допомогою DWM

Індикатор розкладки клавіатури в 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 тут, а релізну версію завантажити тут.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.