Решение проблемы с переключением раскладки на Windows 11
Добрый день!
Столкнулся с неприятной проблемой в 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
Создаем ярлык и указываем его на наш файлик со скриптом
Готово.