Добрый день!
Столкнулся с неприятной проблемой в Windows 11: при быстром переключении раскладки (Alt+Shift) язык меняется не всегда. Сразу после перезагрузки ПК все работает, но проблема появляется через какое‑то время.
Я просмотрел форумы и похожие обсуждения, но готового решения не нашел — поэтому делюсь тем, что сработало у меня.
В чем суть проблемы
По ощущениям (и по комментариям других пользователей), стандартный механизм Windows 11 иногда не успевает корректно обработать/отрисовать переключение раскладки при быстрых нажатиях.
Косвенное подтверждение: переключение через Win+Пробел при этом работает стабильно.
Что обычно советуют, но мне не помогло
отключить залипание клавиш;
перезапустить
ctfmon.exe;переустановить языки/раскладки.
В моем случае эффекта не было.
Решение
Я отказался от стандартного механизма переключения и сделал его через AutoHotkey v2.
Скачать: https://www.autohotkey.com/
Варианты
Punto Switcher — простой вариант, можно переключать одной клавишей или автоматически. Но для разработки автопереключение часто неудобно.
AutoHotkey v2 — гибко, быстро и предсказуемо. Этот вариант я и выбрал.
Настройка AutoHotkey
Устанавливаем AutoHotkey v2
Скрипт перехватывает нажатие Alt+Shift и выполняет переключение раскладки напрямую через API Windows, обходя стандартный механизм смены языка в Windows 11. За счет этого переключение между RU и EN срабатывает стабильнее при быстром наборе, без пропусков и задержек, которые иногда возникают у штатного переключателя.
Также в скрипте есть защита от двойного срабатывания, чтобы при одном нажатии язык менялся ровно один раз.
Создаем файлик скрипта в любом удобном месте, и называем например LangSwitch.ahk
Вставляем и сохраняем:
#Requires AutoHotkey v2.0 #SingleInstance Force ; Переключение между RU и EN по Alt+Shift (в любом порядке нажатия) ~*LAlt::TrySwitch() ~*RAlt::TrySwitch() ~*LShift::TrySwitch() ~*RShift::TrySwitch() TrySwitch() { static lastTick := 0 if !(GetKeyState("Alt", "P") && GetKeyState("Shift", "P")) return ; Защита от двойного срабатывания при одновременных событиях клавиш now := A_TickCount if (now - lastTick < 150) return lastTick := now ToggleRuEn() } ToggleRuEn() { static RU := 0x0419 static EN := 0x0409 hwnd := WinActive("A") if !hwnd return ; Текущая раскладка потока активного окна threadId := DllCall("GetWindowThreadProcessId", "Ptr", hwnd, "UInt*", 0, "UInt") hkl := DllCall("GetKeyboardLayout", "UInt", threadId, "UPtr") langId := hkl & 0xFFFF target := (langId = RU) ? EN : RU targetHKL := (target << 16) | target ; WM_INPUTLANGCHANGEREQUEST DllCall("PostMessage", "Ptr", hwnd, "UInt", 0x50, "Ptr", 0, "Ptr", targetHKL) }
Перед запуском скрипта рекомендую отключить стандартный механизм смены раскладки:
Заходим в Параметры → Время и язык → Ввод → Дополнительные параметры клавиатуры → Сочетания клавиш для языков ввода.
Нажимаем на «Переключить язык ввода», справа снизу «Сменить сочетание клавиш» — и выбираем в колонках «Не назначено»
Далее можем его запустить, ну и для удобства добавить в автозагрузку —
Нажимаем Win + R, пишем shell:startup
Создаем ярлык и указываем его на наш файлик со скриптом
Готово.
P.s спасибо MikaBelkin за уточнения в комментариях, если запускать скрипт через C:\Program Files\AutoHotkey\v2\AutoHotkey64_UIA, то он будет работать везде, в том числе и в программах, запущенных с правами администратора через UAC. Только надо, чтобы Autohotkey был установлен в Program Files. Документация: https://www.autohotkey.com/docs/v2/Program.htm#Installer_uiAccess
