Асемблер/дізассемблер клавіатурних розкладок Windows за допомогою flat assembler

розкладка
Знайомий линуксоид дорікнув мені, мовляв, у вінді ні перемикання мови Caps Lock'ом ні, ні навіть розкладку можна відредагувати. Подивився я, і правда, все розкладки містяться у файлах C:\Windows\System32\kbd*.dll, і редагувати таке hex-редактором ну ніяк не назвати зручним.
Як досягти зручності? Для перемикання розкладок Caps Lock'ом можна використовувати всякі навісні програми, важкі кшталт Punto Switcher, або прості начебто lswitch. Для редагування розкладок є MSKLC, але він малофункционален і незручний, а аналоги на зразок KbdEdit або KLM32 платні.
І тоді я вирішив написати на flat assembler'е-код, що збирає DLL розкладки.
За основу була взята розкладка kbdusx.dll у системі вона називається "США Міжнародна". Мені вона сподобалася тим, що в ній є ряд комбінацій для додаткових символів. Не подобалася вона тим, що перетворює клавіші <`~> <6^> <'"> у так звані dead keys, «мертві клавіші». Їх особливість — при натисканні нічого не друкується, але змінюється наступний набраний символ. Таким чином можна вводити латинські букви з диакритикой, для яких немає окремого сполучення клавіш. Але мені, як програмісту, було дуже неприємно «залипання» таких часто використовуваних клавіш, і спочатку я просто обнулив поля в hex-редакторі, відповідальні за мертві клавіші.
Прийшла пора розібратися з форматом раз і назавжди. Спочатку справа йшла неспішно, потім я знайшов kbd.h і кілька прикладів розкладок з Windows Driver Kit.
розкладки
Цікаво, що Microsoft вирішили помістити розкладки в формат DLL, хоча за винятком корейської kbdkor.dll та японської kbdjpn.dll там коду немає зовсім, якщо не вважати що експортується функцію KbdLayerDescriptor, повертає покажчик на головну таблицю з розкладкою.
Таблиця має такий вигляд:
32-bit Windows 64-bit або WOW64
Заголовок Розмір Зміщення Розмір Зміщення
modifiers 4 0x00 8 0x00
vk2wchar 4 0x04 8 0x08
deadkeys 4 0x08 8 0x10
keynames 4 0x0C 8 0x18
keynamesExt 4 0x10 8 0x20
keynamesDead 4 0x14 8 0x28
scancode2vk 4 0x18 8 0x30
scancode2vk_size 1 0x1C 1 0x38
e0scancode2vk 4 0x20 8 0x40
e1scancode2vk 4 0x24 8 0x48
locale_flags 2 0x28 2 0x50
version 2 0x2A 2 0x52
ligature_chars 1 0x2C 1 0x54
ligature_size 1 0x2D 1 0x55
ligatures 4 0x30 8 0x58
type 4 0x34 4 0x60
subtype 4 0x38 4 0x64
Таким чином, файл розкладки містить в собі таблиці назви клавіш, конвертації скан-кодів у віртуальні (0x1C → VK_RETURN), конвертації віртуальних кодів символи, комбінації мертвих клавіш, «лігатури».
Судячи з усього, назви клавіш використовуються рідко, мені не вдалося на своєму комп'ютері знайти програми, яка б виводила їх список з розкладки.
Змінюючи таблицю скан-кодів, можна змінити будь-яку клавішу на іншу. Якщо відразу захотілося перепризначити кнопки живлення (Power, Sleep, WakeUp), то це теж можна, але це не відміняє їх оригінальної функції. Її можна відключити в налаштуваннях електроживлення.
У таблиці символів самий сік. Вона вирішує, до чого призведе натискання клавіш K, Shift+K, AltGr+K, Shift+AltGr+K, впливає на неї Caps Lock, чи використовує він той же ряд символів, що й Shift+K або окремий, впливає на неї Kana; буде символ надрукований відразу, або заноситься в чергу мертвих клавіш, або друкується ряд символів з «лігатури», або чи не станеться нічого.
AltGr — так називається або правий Alt, або поєднання клавіш Ctrl+Alt.
Список мертвих клавіш містить пари символів, які повинні перетворюватися в третій символ. Цей символ може тиражуватися відразу, або знову проходити по списку для подальшого перетворення. Якщо пара символів не найдена в списку, то вона просто надрукується як є. З допомогою ланцюжків мертвих клавіш можна імітувати поведінку Compose Key, але деякі програми, наприклад, Firefox, не розпізнають перетворення далі першого.
Список «лігатури», який по суті є набором макросів, може дозволити набирати до чотирьох символів WCHAR по натисненню клавіші. Насправді, у мене Windows 7 працює до 16 символів, але з украй неприємним винятком: Firefox при натыкании на таку розкладку геть зависає, а якщо розкладка з довгими «лігатурами» системна, то й зовсім перестає запускатися.
Створення розкладки
Спершу я хотів зробити дві зручних розкладок, російську та англійську, придатну як для написання статей, так і програм. Друкарська розкладка Іллі Бірмана хороша, але могло бути ще краще, тим більше якщо робити особисто для себе.
Потім я дізнався про клавішу Kana. Kana — переключающаяся подібно Caps Lock'у кнопка на японській клавіатурі. І тут я вирішив об'єднати англійську і російську розкладки в одну, і перемикатися між ними клавішею Kana. Яку я перепризначив на Caps Lock. Написав просту програму-індикатор для відображення стану Kana лампочкою Caps Lock'а.
У такій об'єднаній розкладки виник один приємний сюрприз: розкладка тепер одна на всю систему, і залишається при перемиканні між програмами, а також «шибко розумні» програми більше не можуть перемикати розкладку за своїм бажанням при редагуванні тексту або переміщення курсору.
один неприємний сюрприз: Psi+ чомусь став з'їдати перший символ, введений після перемикання розкладки натисканням Kana.
Тим не менш, я залишив цю розкладку в архіві разом з індикатором Kana.
Потім я виявив, що Caps Lock'у можна призначити окремий ряд символів і замінив Kana на Caps Lock. Програма-індикатор стала непотрібною, неприємний сюрприз изчез. При переробці виявилося лише одне обмеження: Caps Lock працює тільки з рядами K + Shift+K — на нього можна повісити AltGr+K і т. п.
У спробах вмістити всі мертві клавіші в два ряди (з Kana було чотири), я натрапив на ідею перевернути їх порядок: так, щоб набиралася AltGr+буква, а потім модифікатор. Це дозволило мені призначити набагато більше символів, ніж раніше. Я назвав це «undead keys», «повсталі з мертвих клавіші».
І ось ідеальна розкладка була готова.
Переваги розкладки kbdusru_undead
  1. Перемикання між російською і англійською однією клавішею Caps Lock.
  2. Індикатор Caps Lock показує поточний мову.
  3. Глобальний стан розкладки для всіх додатків.
  4. Неможливість «шибко розумних» програм спонтанно змінювати розкладку.
  5. Можливість вводити літери з диакритикой і купу інших символів.
  6. Можливість легко змінити розкладку за смаком.
Приклад введення деяких додаткових символів
Комбінація клавіш Результат
AltGr+5
AltGr+9 «
AltGr+0 »
AltGr+-
AltGr+=
AltGr+; °
AltGr+, <
AltGr+. >
AltGr+Shift+/ /me
AltGr+a' á
AltGr+e,` è
AltGr+o" ő
AltGr+n,~ -
AltGr+c,^ ĉ
r, s,AltGr+q,', б, а риба
AltGr+c,o ©
AltGr+r,o ®
AltGr+t,m (tm)
AltGr+m,u µ
AltGr+h,s
AltGr+f,2 ½
AltGr+b,f
Установка
Я просто змінюю системний файл C:\Windows\System32\kbdru.dll на свою розкладку, адже вона у всіх відносинах краще. На Windows XP або 2000 в такому випадку потрібно не забути видалити C:\Windows\System32\dllcache\kbdru.dll.
Але якщо вам не до душі такий насильне апгрейд вінди, то розкладку можна скопіювати в папку C:\Windows\System32\ та зареєструвати в системі з допомогою такого reg-файлу:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\07430419]
"Layout Text"="US+RU"
"Layout Display Name"="United States-International + Russian + Extra"
"Layout File"="kbdusru_undead.dll"
"Layout Id"="00d0"

Перша частина коду, 0743 — довільні цифри для унікальної ідентифікації розкладки, а 0419 — код мови «Русский», під яким повинна з'явитися розкладка. Від коду мови залежить поведінка розкладки в неюникодных (ANSI) програмах.
більше
Програмувати на flat assembler'е мені доставляє одне задоволення: потужний мову макросів, красивий і слухняний синтаксис, непотрібність всяких линковщиков і каші параметрів в командному рядку.
Тому я вирішив написати на ньому програму, яка при ассемблировании читає DLL розкладки, а на виході — вихідний код. Дивно, правда? Використовувати асемблер, як дізассемблер. Але міць fasm'а це дозволяє.
В результаті у мене вийшли розкладки, які дозволяють перемикатися між мовами Caps Lock'ом без зовнішніх програм глобально для всієї системи, а також набір інструментів, який дозволяє зручно редагувати розкладки клавіатури Windows.
Все викладено на https://github.com/grompe/kbdasm як суспільне надбання.
Якщо у вас 64-бітна Windows, можна завантажити архів, розпакувати і запустити make.bat, а потім install.bat. Для 32-бітної доведеться спершу підправити файл kbdusru_undead.asm.
Також в архіві є програма get_scancodes. Якщо у вас є хитра клавіатура з додатковими клавішами, за допомогою програми можна дізнатися скан-коди і задіяти ці клавіші в розкладці.
Джерело: Хабрахабр

0 коментарів

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