Ассемблер/дизассемблер клавиатурных раскладок 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 (если включён в раскладке флагом KLLF_ALTGR), он генерирует сочетание клавиш 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,^ ĉ
р, ы,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. Если у вас есть хитрая клавиатура с дополнительными клавишами, с помощью программы можно узнать скан-коды и задействовать эти клавиши в раскладке.

Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 48
  • 0
    Круто, в свое время было бы полезно иметь такой инструментарий (давно пересел за mac). Если оформить такое чудо как удобную gui тулзу можно даже деньги на наших программерских братьях рубить.
    • +5
      Написать аналог, потому что имеющийся софт с нужными возможностями платный, а потом начать этот аналог продавать — это прям перебежка в стан врага :)
      • –3
        Я бы сделал free to use версию, первый месяц бесплатно а потом часть кнопок лочится или нужно платить 0.99 в месяц. А за то что приглашаеш в апу друзей — каждый день подарок, новая кнопка.
        • +3
          нужно платить 0.99 в месяц.

          за каждую кнопку

          • 0
            Это называется shareware.
            Нестóит.
      • 0
        Кажись, Хабр — снова торт! Уже третий исследовательский пост за день)) Круто, чё! Респект!
        • 0

          Да, в виндах без AutoHotkey вообще никак. Раскладку тоже меню по CapsLock, есть варианты более суровые, через WinAPI, но остановился на самом простом:


          $Capslock::Send {alt down}{shift down}{shift up}{alt up}
          +Capslock::Capslock
          • +1
            Теперь можно выбросить подобные костыли!
          • 0
            А есть ли возможность через файлы раскладок повлиять на сочетания переключения раскладок? Настроил в linux'е переключение на английский по LCtrl, на русский — по RCtrl, а в Win7/2008 страдаю. Punto Switcher ставить только ради нестандартного переключения раскладок не вижу смысла.
            • 0
              К сожалению, развесить переключение на два Ctrl нельзя, по крайней мере, используя изложенные средства. Даже сейчас такое «переключение раскладки» внутри одной раскладки является довольно хитрым хаком.

              Возможно, в японской раскладке или системе ввода IME есть более продвинутые средства ввода, которые это позволяют.
              • 0
                Есть RusLat 95, работает на XP и Win7. На 2008 не проверял.
              • 0
                хмы. возможно теперь получится нарисовать полноценный аналог макосной раскладки DQ — дворак с qwerty хоткеями.
                • 0
                  Я думаю, должно получиться, если записать в обычный ряд QWERTY-клавиши, а в ряд с включённым Caps Lock — Dvorak.
                  • 0
                    там немного сложнее, и проблема в том что хоткеи активируются по контролу — я сейчас использую подобную штуку за авторством одного американца, но там судя по всему есть какие-то подводные камни когда софт типа файрфокса лезет в обработку ввода своими кривыми лапами и в итоге некоторых хоткеев получается не существует вообще — Ctrl-C например
                • 0
                  Есть ли возможность прикрепить к какой-нибудь кнопке свой scan code? На клавиатуре(meka g-unit) име.тся 12 дополнительных кнопок, но скан-кодов на них нет(
                  • 0
                    Можно воспользоваться программой get_scancodes, понажимать эти кнопки и посмотреть, какие скан-коды получаются.

                    Если скан-кодов вообще нет, значит, клавиатура ничего не шлёт по нажатию этих кнопок.
                    • 0
                      Скан-кодов нет, но в программе можно забиндить действие по нажатию. Придётся реверсить протокол(
                      Не подскажете программу, которая может слушать то, что посылается в клавиатуру?(USB)
                      • 0
                        А, то есть с клавиатурой идёт специальная программа для дополнительных кнопок? Ну тогда её и реверсить, используя WinAPIOverride, например. Про USB не подскажу.
                        • 0
                          Не подскажете программу, которая может слушать то, что посылается в клавиатуру?(USB)

                          Wireshark в том числе и с USB работает.


                          По поводу ревесить, может быть так, что скрипты пишутся в память клавиатуры, и по нажатию отдаётся запрограммированный поток сканкодов. Т.е. сама по себе кнопка не шлёт вообще ничего. У меня в Aivia Osmium именно так. Был G-Unit, но было это давно и разбирался с этой клавиатурой недолго, поэтому точнее не подскажу.

                          • 0
                            Полагаю, что логика работы этих клавиш определена на железном уровне в контроллере самой клавиатуры. Так бывает, например, с клавишами-модификаторами типа FN, у которых тоже нет скан-кода и система их не видит.
                      • 0
                        поторопился
                        • +1
                          • 0
                            Мне было интересно расковырять формат.
                            В MSKLC делать раскладки, подобные моей — замучаешься, а ряда функций там вообще нет. Редактировать исходный текст гораздо удобнее нащёлкивания кнопок в GUI.
                          • +1
                            Может быть кому-то будет полезно: в Windows можно переназначать клавиши с помощью реестра.
                            Например, я себе повесил на ненужный Scroll Lock клавишу Mute, очень удобно.
                            Подробнее можно прочитать здесь:
                            http://www.howtogeek.com/howto/windows-vista/disable-caps-lock-key-in-windows-vista/
                            https://geektimes.ru/post/75290/
                            • 0
                              А теперь можно это сделать и раскладкой, подменив нужную клавишу в таблице scancode2vk или e0scancode2vk.
                              И без перезагрузки.
                            • 0
                              Мне кажется или есть ещё один недостаток? Word к примеру будет считать весь текст набранный в этой раскладке написанным на русском языке.

                              Соответственно орфография и грамматика будет соответствующая.
                              • 0
                                Word и прочие продукты Office язык определяют не по раскладке же.
                                Да и это опционально — по какому словарю делать проверку. По нажатию F7 появляется окно с нужным выпадающим списком.
                                Так же можно активировать автоопределение языка (от раскладки это тоже не зависит).
                              • 0
                                Пробовал переучить себя на Win+Space, но на некоторых компах стоит Win7 и из-за этого пришлось от этой идеи отказаться.

                                Для переключения по Caps Lock использую Punto Switcher, но бывает иногда (раз в 2 недели) такой баг, что включается режим больших букв и в такой момент всё можно поправить. Зайти в меню punto switcher, выключить переключение по Caps Lock, нажать Caps Lock и вернуть как было.

                                Хочется ваш способ попробовать, но боюсь, что иногда будет вылезать такой же баг с большими буквами и тогда придется делать выход из системы или еще что-то магическое
                                • 0
                                  Полгода пользуюсь, такого бага не наблюдал. Windows 7 64-bit.
                                • +1
                                  Попробовал на Windows 7 x64. Есть некоторые вопросы:
                                  — В режиме EN, дополнительное переключение осуществляется по CAPS Lock, но как в таком случае, включить постоянный CAPS Lock в этой раскладке?
                                  — В режиме EN нет отображения режима раскладки, это так и должно быть? Хотя, я понимаю, что, по сути, он ведь не меняется при переключении CAPS Lock-ом.
                                  — Ну и самое главное, в FAR manager действия, назначенные по Alt+F7 (поиск файла, но на самом деле, там масса хоткеев, завязанных в частности на комбинациях с alt) например, теперь доступны исключительно только по Left-Alt комбинациям (это понятно, почему), хотя в США (НЕ международной) раскладке это можно было делать c любым ALT. Я так понял, что США раскладке не делается различий между ними (т.е. нажатие на любой ALT расценивается как LEFT ALT). Но я привык работать в ФАР с правым ALT и США-раскладкой: (
                                  И в этом варианте данные модификации сразу падают в ценности.
                                  Вопрос — что нужно поменять в asm-файлах? Ну или, если нельзя сделать «слияние» alt как в США-раскладке, то можно ли просто «поменять» левый и правый ALT, что для это нужно изменить в исходнике?
                                  • 0
                                    1. Функция Caps Lock в моей раскладке полностью заменяется — вместо больших букв русские.
                                    2. Индикатором выступает лампочка, а ОС и программы думают, что раскладка никогда не меняется.
                                    3. Если в раскладке присутствует ряд AltGr, то соотвественно, правый Alt им и становится. В обычных раскладках такого ряда нет.
                                    Хорошая мысль! Только что поменял Alt'ы местами и в Far'е работает RAlt+F7. Просто замените VK_LMENU на VK_RMENU и наоборот. Можно оба сделать VK_LMENU.
                                    • 0
                                      Спасибо, у меня всё получилось.
                                      Немного корявый install.bat — если инсталлировать несколько раскладок — то приходится править внутри SET id= и дополнительно константу 00do, которая является параметром реестра «Layout Id». Последний одинаковый параметр у нескольких раскладок не даёт их выбора из трея, видимо ctfmon просто теряется в дублях. Но это мелочи.
                                      Ещё не совсем ясно назначение параметра реестра «Layout text» — в какой ситуации это будет отображаться (US+)?

                                      • 0
                                        Спасибо за замечание — поправил install.bat.

                                        Про «Layout Text» не уверен, если где увидел — не запомнил, увы. Так что пусть будет на всякий случай просто потому, что у других раскладок такое есть.
                                    • 0
                                      Поправочка: если не нравится AltGr, хочется использовать правый Alt как прежде и для ввода дополнительных символов не лень нажимать Ctrl+Alt, то можно из раскладки убрать флаг KLLF_ALTGR, заменив на 0.

                                      Это будет более чистым решением, чем менять Alt'ы местами.
                                      • +2
                                        Да, попробовал и этот вариант, спасибо.
                                        Заметил ещё пару вещей:
                                        — При совместной работе с русской (стандартной) раскладкой punto switcher не хочет делать авто-переключение, если русский текст набирался латинницей, т.е. буквально набираем текст «ghj» — ps переключает язык и текст превращается в «про».
                                        Если у нас альтернативная и Русская раскладки — ничего не происходит. Вероятно, ps не признает текущую (USA-undead) раскладку за нерусскую и не переключается. Казалось бы, мелочь, у меня в ps и так автопереключение выключено, но включено принудительное переключение по Break, когда набираешь текст, видишь, что не то, жмешь Break — ситуация исправляется, удобно. Однако и это тоже не работает.
                                        — Далее уже багофича:
                                        — PhotoShop CS при наборе текста (при редактировании изображения) вводит только латинницу, при переключении вместо кириллицы вводятся знаки вопроса.
                                        — PMView в диалогах сохранения изображений аналогичная ситуация, (в том же фотошопе, в диалогах сохранения/открытия, однако, нет такой проблемы)
                                        — Тем не менее, в очень древнем Cool95 такой проблемы нет. Естественно, все перечисленные программы — 32-битные.
                                        Я компилировал и инсталлировал два варианта dll — c WOW64 = 0 и WOW64 = 1, копировал их в system32 и sysWOW64.

                                        — Ну и, чтобы два раза не вставать, вот что я решил по индикатору:
                                        Перепробовал несколько программок, и остановился на программе KeyboardLEDs © KARPOLAN, в ней есть режим отображения состояния CAPS Lock (и не только) иконкой и/или OSD текстом.
                                        Всё бы ничего, но OSD текст вещает исключительно то, что есть — именно «Caps Lock ON/OFF», в связи с чем проделаны небольшие изменения в exe, чтобы вместо выводился текст «RUS/LAT», не знаю, является ли это нарушением, но если кому то интересно, могут пользоваться совершенно свободно: https://drive.google.com/open?id=0B0jPU_spS-c3bExwcTZOOTRscU0
                                        В архиве оригинальный пак с программой, в подпапке \kbdasm — изменённый exe и инфо по ручному патчу, пара картинок с демонстрацией.
                                        • 0
                                          Нет сюрприза в том, что Punto Switcher не поддерживает гибридную раскладку. Если нужно им пользоваться, пожалуй, лучше разделить раскладку на две и использовать его функцию переключения по Caps Lock. Или написать разработчикам, пусть добавят поддержку =)

                                          В Photoshop CS3 (32-bit) на одном из компьютеров у меня кириллица вводится. Гибридная раскладка зарегистрирована как русская (0419), единственная в системе. Windows 7 64-bit. Раскладку достаточно поставить только в system32.

                                          Попробовал PMView (32-bit), тоже не поймал баг.

                                          Обычно знаки вопроса вместо кириллицы возникают тогда, когда раскладка поставлена в английской локали (0409). Но вот Фотошоп у меня всё равно текст нормально пишет.
                                          • 0
                                            Именно, пока тоже разбирался, но вы меня опередили. Вобщем, тоже нашёл ответ — если регистрировать модифицированную dll как русскую (0xxx0419) — то поведение становится адекватным, а раскладка появляется, естественно, в разделе Русских.
                                    • 0
                                      Хочу на основе стандартной раскладки сделать немного модифицированную — «не выходит каменный цветок».
                                      В win8.1x64 дизасмил оригинальный файл kbdru.dll потом скомпилировал его обратно без всяких правок и прописал под другим именем в реестр, при нажатии «выбрать метод ввода» языковая панель закрывается с небольшим подвисанием компа.
                                      • +1
                                        Нужно было секции ".data" добавить флаг executable.
                                        Только вот теперь firefox раскладки переключает по alt+tab, хотя в системе настроено по ctrl+tab.
                                        • 0
                                          * alt+shift ctrl+shift
                                          • 0
                                            О, этот момент я упустил, забыл поставить флаг executable. Исправил, спасибо!

                                            Насчёт Firefox'а не уверен, что с ним делать, мне несколько раз приходилось его «уговаривать», так как он в раскладку лезет самостоятельно.

                                            Есть мысль: Firefox у вас 32-битный на 64-битной Windows 8? Попробуйте сделать версию раскладки для WOW64 и поместить в C:\Windows\SysWOW64\
                                            • 0
                                              Если 32-битную версию закинуть в SysWOW64 винда её не видит, т.е. в списке выбора раскладок она есть (из реестра читается), но саму dll-ку не видит т.к. кнопка просмотра раскладки не активна и при добавлении этой раскладки используется всё равно стандартная. Теперь даже при удалении кастомной и установки стандартной firefox всё равно переключается по alt+shift.
                                              • 0
                                                разобрался с ff: он у меня под другим (ограниченным в правах) пользователем запускается, отсюда все проблемы, перенастроил под другой учёткой, теперь всё нормально.
                                        • 0

                                          Проблема с сочетаниями AltGr + буква в том, что куча приложений использует такие сочетания, например, тот же фотошоп. В результате всё ломается.

                                          • 0
                                            Можете привести пример? Было бы странно, если бы куча приложений ломалось из-за AltGr, ведь множество системных раскладок её использует.

                                            В том же Фотошопе: если вводим текст, AltGr+W пишет нужный символ. Вне режима ввода это действует, как Ctrl+Alt+W (закрыть все окна). По-моему корректное поведение.
                                            • 0

                                              Не знаю, как вам, а мне не нравится, когда функция зависит от того, где находится курсор. И не все приложения аккурантно отличают, где находится фокус. Я уже не помню деталей. Помню только, что меня поведение раздражало достаточно, чтобы ограничиться в своих раскладках сочетаниями вроде AltGr+;, то есть без букв.

                                              • 0
                                                Хм… Я, вообще говоря, не против того, чтобы в режиме ввода и вне него горячие клавиши работали по разному, но AltGr+W и Ctrl+Alt+W — это больно стрёмная коллизия.
                                                • 0
                                                  В системе AltGr — то же самое, что и Ctrl+Alt, так что это не коллизия, а просто синонимы.

                                                  Уточнил этот факт в статье.

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.