В оригінальній програмі, яка переключає розкладки клавіатур, перша кнопка на новій клавіатурі вводиться зі старою розкладкою. Я чесно намагався звикнути до цього, але не зміг. І тоді вирішив зробити неможливе: виправити цей недолік. Проблема була в тому, що подія
Я так розумію, правильний підхід — це скачати WDK, розібратися як працює клавіатурний фільтр і навчитися передавати з нього повідомлення про поточну клавіатуру, щоб програма встигала переключити розкладку... Якби я був справжнім програмістом, я б так і зробив: уявляю собі вже справжній інсталятор, який вимагає пароль адміністратора, щоб установити клавіатурний фільтр, а після установки перезавантажуватиме систему. Саме так все і працює під Вікнами в реальному житті!
Та я вирішив обійтися тим, що є. Отже, для кожної клавіатурної події спочатку виконується зачіпка на
Символ з кодуванням від чужої клавіатури обробляється при натисканні на кнопку. А відпускання кнопки зазвичай нічого поганого не робить. Отож можна почекати коли кнопку відпущено, передати цей сигнал, визначити клавіатуру, перемкнути, якщо потрібно, розкладку, а потім ввести цей символ ще раз за допомогою
Це працює. Але створює одну незручність: якщо відпустити, наприклад, SHIFT до того, як подію натискання на букву було оброблено (натиснути SHIFT, натиснути букву, відпустити SHIFT, відпустити букву), SHIFT не спрацьовує — і набирається маленька буква. Те саме стосується ALT і CTRL. Подію відпускання обов'язково необхідно передати, бо инакше
Та найцікавіше було попереду. При переході від одної клавіатури до иншої, якщо натиснути одночасно кілька кнопок, вони натискаються з CTRL. Як з'ясувалося, причина в тому, що після повідомлення про зміну розкладки, з клавіатури приходить подія віпускання CTRL. Прапорець виставлений, як подія на реальній клавіатурі, при тому що ніякого CTRL я не торкаюся! Тобто ця подія приходить саме від драйвера, і я навіть уявити боюся чому... Відтак я зрозумів, що моя клавіатурна новація не вносить особливого хаосу в уже цілком хаотичну поведінку системи. Тому після зміни розкладки, я просто виставляю прапорець не зберігати CTRL, ALT і SHIFT у буфер доки буфер не очиститься і позбавляюся цієї проблеми.
Втім, нехорошу поведінку виключити повністю я не зумів. Якщо, наприклад, натиснути SHIFT на одній клавіатурі, а букву на иншій, програма смішно намагається встигнути переключитися двічі, але їй це не вдається. В результаті вводиться маленька буква з розкладки клавіатури, на якій натиснуто SHIFT. Взагалі, якщо потренуватися, можна зробити там переповнення буфера, абощо — та в нормальному режимі працює досить пристойно як для збочення...
Ще один не дуже приємний ефект — символ вводиться після відпускання кнопки, а не після натискання. З цієї ж причини неадекватно обробляється затискання одної кнопки на деякий час. Символи з'являються з запізненням і перший буде зі старої клавіатури. Думаю, якщо ви звикли до сліпого набору, то, можливо, зачіпку краще відключити і просто пристосуватися до неправильного першого символу при переході з одної клавіатури на иншу.
Ну і про неосновне, але найбільш помітне... Я зробив вибір розкладки для кожної мови. Це перетворює програмку на досить таку універсальну штуку. Уявіть, що у вас п'ять клавіатур з різною кількістю кнопок. Це не прикол: у вас може бути ноутбук плюс USB-клавіатура вдома, на роботі, в друзів — всюди різні. І ви набираєте текст десятьма мовами. За допомогою цієї програми ви можете налаштувати для кожної пари клавіатура-мова окрему розкладку з автоматичним переключенням на неї при наборі. Для деяких клавіатур можна задати мови, для яких вони не працюють, — на них не можна буде переключитися за допомогою цієї клавіатури. Для цього при першому натисканні кнопки у таких мовах слід задати розкладку з иншої мови.
Найпростіша конфіґурація: дві мови, — наприклад: українська та англійська, — і дві клавіатури — по одній для кожної мови.
Скачати: програму або код.
Якщо код вас не злякає, буду радий коментарям і пропозиціям.
WM_INPUT
відбувається вже після обробки події натискання на кнопку. Мені ж необхідно було вставити повідомлення про перемикання розкладки до повідомлення про натискання кнопки. Для того, щоб перехопити цю подію, у Вікнах існує зачіпка на WH_KEYBOARD_LL
, яка викликається після обробки клавіши драйвером. Здавалося б, проблем нема, але... в цей момент неможливо визначити фізичну клавіатуру. Очевидно, добрі дрібном'які програмісти вирішили нас уберегти від зайвої інформації...
Я так розумію, правильний підхід — це скачати WDK, розібратися як працює клавіатурний фільтр і навчитися передавати з нього повідомлення про поточну клавіатуру, щоб програма встигала переключити розкладку... Якби я був справжнім програмістом, я б так і зробив: уявляю собі вже справжній інсталятор, який вимагає пароль адміністратора, щоб установити клавіатурний фільтр, а після установки перезавантажуватиме систему. Саме так все і працює під Вікнами в реальному житті!
Та я вирішив обійтися тим, що є. Отже, для кожної клавіатурної події спочатку виконується зачіпка на
WH_KEYBOARD_LL
, а потім обробник події WM_INPUT
який знає, яку розкладку вибрати. Перше, що прийшло в голову, — не ґенерувати подію натискання кнопки, а натомість зберігати всі кнопки за допомогою зачіпки, щоб після перемикання розкладки, відправити їх по черзі за допомогою keybd_event
. Весь прикол в тому, що якщо перервати генерування події натискання кнопки, вернувши зачіпкою -1, то і подія WM_INPUT
не настає! Таким чином, узнати з якої клавіатури прийшов сигнал про натискання кнопки можна тільки після того, як цей сигнал було оброблено.Символ з кодуванням від чужої клавіатури обробляється при натисканні на кнопку. А відпускання кнопки зазвичай нічого поганого не робить. Отож можна почекати коли кнопку відпущено, передати цей сигнал, визначити клавіатуру, перемкнути, якщо потрібно, розкладку, а потім ввести цей символ ще раз за допомогою
keybd_event
. Це призводить до наступного ефекту: якщо ми натискаємо, наприклад, SHIFT отримуємо таку послідовність подій — SHIFT відпущено, SHIFT натиснуто, SHIFT відпущено замість SHIFT натиснуто, а потім відпущено. Сама по собі ця послідовність не має фатальних наслідків. Але разом з відповідними неконтрольованими подіями для CTRL і ALT може переключати в якісь незвичайні режими, коли система думає, що ваш SHIFT натиснуто, у той час, коли ви його відпустили. Вирішення цієї проблеми полягає в тому, що при натисканні цих трьох кнопок, ми завжди створюємо подію.Це працює. Але створює одну незручність: якщо відпустити, наприклад, SHIFT до того, як подію натискання на букву було оброблено (натиснути SHIFT, натиснути букву, відпустити SHIFT, відпустити букву), SHIFT не спрацьовує — і набирається маленька буква. Те саме стосується ALT і CTRL. Подію відпускання обов'язково необхідно передати, бо инакше
WM_INPUT
не відбудеться, а значить можна впустити ланцюг виконання буфера. Тому відправляється подія відпускання, а в буфер записується віртуальне натискання цієї ж кнопки спочатку і відпускання її ж укінці.Та найцікавіше було попереду. При переході від одної клавіатури до иншої, якщо натиснути одночасно кілька кнопок, вони натискаються з CTRL. Як з'ясувалося, причина в тому, що після повідомлення про зміну розкладки, з клавіатури приходить подія віпускання CTRL. Прапорець виставлений, як подія на реальній клавіатурі, при тому що ніякого CTRL я не торкаюся! Тобто ця подія приходить саме від драйвера, і я навіть уявити боюся чому... Відтак я зрозумів, що моя клавіатурна новація не вносить особливого хаосу в уже цілком хаотичну поведінку системи. Тому після зміни розкладки, я просто виставляю прапорець не зберігати CTRL, ALT і SHIFT у буфер доки буфер не очиститься і позбавляюся цієї проблеми.
Втім, нехорошу поведінку виключити повністю я не зумів. Якщо, наприклад, натиснути SHIFT на одній клавіатурі, а букву на иншій, програма смішно намагається встигнути переключитися двічі, але їй це не вдається. В результаті вводиться маленька буква з розкладки клавіатури, на якій натиснуто SHIFT. Взагалі, якщо потренуватися, можна зробити там переповнення буфера, абощо — та в нормальному режимі працює досить пристойно як для збочення...
Ще один не дуже приємний ефект — символ вводиться після відпускання кнопки, а не після натискання. З цієї ж причини неадекватно обробляється затискання одної кнопки на деякий час. Символи з'являються з запізненням і перший буде зі старої клавіатури. Думаю, якщо ви звикли до сліпого набору, то, можливо, зачіпку краще відключити і просто пристосуватися до неправильного першого символу при переході з одної клавіатури на иншу.
Ну і про неосновне, але найбільш помітне... Я зробив вибір розкладки для кожної мови. Це перетворює програмку на досить таку універсальну штуку. Уявіть, що у вас п'ять клавіатур з різною кількістю кнопок. Це не прикол: у вас може бути ноутбук плюс USB-клавіатура вдома, на роботі, в друзів — всюди різні. І ви набираєте текст десятьма мовами. За допомогою цієї програми ви можете налаштувати для кожної пари клавіатура-мова окрему розкладку з автоматичним переключенням на неї при наборі. Для деяких клавіатур можна задати мови, для яких вони не працюють, — на них не можна буде переключитися за допомогою цієї клавіатури. Для цього при першому натисканні кнопки у таких мовах слід задати розкладку з иншої мови.
Найпростіша конфіґурація: дві мови, — наприклад: українська та англійська, — і дві клавіатури — по одній для кожної мови.
- Спочатку вибираємо англійську мову і натискаємо на кнопку «української» клавіатури.
- Ставимо їй розкладку української мови. Програма переключається на українську мову.
- Тепер натискаємо кнопку «англійської» клавіатури і вибираємо їй англійську розкладку.
- Відтепер кнопки на англійській клавіатурі автоматично вводитимуть англійські букви, а української — українські.
Скачати: програму або код.
Якщо код вас не злякає, буду радий коментарям і пропозиціям.
Нема коментарів
Дописати коментар