Переключение только между двумя языками в Windows по стандартной комбинации клавиш Alt+Shift

Программер что-то программит на своем прогаммистскомНачав изучать китайский язык, я столкнулся с довольно неприятнейшей проблемой, связанной с невероятной косностью разработчиков Windows. При использовании только одного языка в системе никаких проблем не возникает. Раскладку клавиатуры переключать не нужно. Если применяется два языка, то всё немного сложнее. Например, если пользователь русскоязычный, то он в основном пишет на русском языке, но периодически вынужден переключаться на английский, так как большинство команд в системе на английском языке, плюс всякие термины, наподобие IPv6, тоже пишутся на английском языке. Тут всё прозаично, типовая комбинация переключения между двумя языками Shift+Alt работает отлично. Но ровно до тех пор, пока в системе всего два языка. А вот когда их становится больше, начинаются проблемы, связанные с докучающим пользовательским неудобством.

При изучении китайского языка, разумеется, в систему был установлен дополнительный язык — китайский. Более того, для того чтобы писать на pīnyīn (английскими буквами по-китайски с тонами), мне пришлось установить еще один язык — японский, для которого была сделана соответствующая Пиньину раскладка. Итого в системе образовалось целых 4 полноценных языка.

Циклически переключаться между ними по Shift+Alt — занятие довольно скучное, никогда точно не знаешь, на каком из языков остановился. Да и переключиться с текущего языка на предыдущий можно, только перещелкнув все остальные языки по очереди. Очень неудобно. Настолько неудобно, что хочется завести отдельный компьютер только для китайского. А что будет, когда к китайскому присоединится арабский? Нужно же мозги тренировать и развивать.

Альтернативно циклическому переключению можно использовать переключение путем выбора конкретного языка по уникальной комбинации клавиш, например Alt+Shift+0 для русского языка, а Alt+Shift+9 для английского. Однако выбор в стандартном приложении для переключения раскладки клавиатуры и языка в Windows не такой богатый. Наиболее удобные комбинации, при которых не нужно выворачивать пальцы, обычно выглядят как Ctrl+1, Ctrl+2 и так далее. И такое переключение отлично работает, за исключением некоторых приложений, активно использующих вкладки, например браузеры, многовкладочные текстовые редакторы и тому подобное. В них подобная комбинация выполняет функцию переключения между вкладками. И совсем не хочется, переключая язык, переключаться еще и между вкладками.

Казалось, что подобная чехарда с языками довольно легко исправляется указанием основных языков, между которыми и происходит циклическое переключение (в моем случае это русский и английский языки), а уже при необходимости можно переключиться на дополнительные языки при помощи более сложной процедуры. Такой механизм реализован в большинстве Linux-дистрибутивов и в MacOS. Но в Windows ожидать подобного не стоит. Всё потому, что закостенелые владельцы продукта даже и мысль не могут допустить, что такое может кому-то понадобиться.

Попытаться исправить проблему с переключением можно сторонними переключателями клавиатуры для Windows. Я перепробовал их несколько, в основном те, что до сих пор поддерживаются авторами. Но только PuntoSwitcher более-менее адекватно справился с задачей переключения основной пары языков. PuntoSwitcher изначально разрабатывался как средство для автоматического переключения языка в зависимости от набираемого текста. Русский и английский тексты имеют свои особенности, благодаря которым можно программным способом попытаться понять, на каком языке пользователь хотел ввести текст, а не по факту ввел. Более того, в PuntoSwitcher есть возможность настроить свое переключение между языками и даже ограничить языки, между которыми будет происходить переключение. Но выбрать традиционную комбинацию в виде Shift+Alt для переключения языков в PuntoSwitcher нельзя, так как она зарезервирована системой именно для переключения языков. Зато можно использовать другую удобную комбинацию в виде Ctrl+Space. Кстати, комбинация Ctrl+Space — довольно удобна, привыкание к ней происходит очень быстро.

И всё бы хорошо, можно было бы пользоваться PuntoSwitcher, даже отключив автоматическое переключение, если бы не Word из пакета Microsoft Office. Word — единственная программа, в которой комбинация Ctrl+Space приводит к полной невозможности использования этого приложения. Изначально в Word данная комбинация задействована для функции отмены примененных стилей выбранного текста. Её можно отключить, если найти нужную комбинацию в настройках Word. Но даже отключение функции не решает полностью проблему при переключении по Ctrl+Space в PuntoSwitcher. Word начинает залипать, даже если попробовать переключиться на другой язык просто в системном диалоге сохранения файла. И единственным способом, как можно победить подобную несовместимость между Word и PuntoSwitcher — внести Word в исключения PuntoSwitcher (там раскладка не будет переключаться при помощи PuntoSwitcher). Работает, но жутко неудобно. Word подвержен этой напасти даже в самой последней на данный момент версии — 2024.

Поскольку все остальные переключатели были сделаны разработчиками для решения своих конкретных нужд и сейчас уже не поддерживаются, то и использовать их особого смысла нет. Что-то поменяется или что-то перестает работать, и всё, придется еще раз искать, как же переключаться между основными языками, а не по всему установленному набору. Остается только выдохнуть и использовать другие средства, как можно более штатные или как можно более универсальные. Одним из таких вариантов является переключение языка посредством встроенных средств Windows, а именно скриптом на языке PowerShell.

# Коды языков
$ruLang = "0419"  # Русский
$enLang = "0409"  # Английский

# Получаем текущий язык
$currentLanguage = Get-WinUserLanguageList

# Если текущий язык русский, переключаем на английский
if ($currentLanguage.LanguageTag -eq "ru-RU") {
    Set-WinUserLanguageList -LanguageList $enLang -Force
}
# Если текущий язык английский, переключаем на русский
else {
    Set-WinUserLanguageList -LanguageList $ruLang -Force
}

Скрипт на PowerShell (расширение .ps1) лаконичен и выполняет свои функции на все 100%. Единственное, что скрипт нужно как-то вызывать при нажатии нужной комбинации кнопок. В Windows единственным способом вызвать скрипт или программу без привлечения внешних средств является способ создания ярлыка для скрипта и назначение ему комбинации клавиш. В качестве вызываемой программы используем примерно следующую строку: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File "C:\Users\xxx\ks.ps1". Второй параметр как раз и указывает местоположение скрипта.

Настройка вызова скрипта через ярлык

Примерно так выглядит ярлык для вызова скрипта PowerShell

Всё работает, за исключением двух моментов:

  1. Для запуска скрипта каждый раз вызывается его интерпретатор, ему передается на выполнение скрипт. Скрипт выполняется. На все эти операции тратятся ресурсы компьютера, могут быть подтормаживания просто из-за того, что скрипт давно не вызывался и он уже выгружен из кэша.
  2. Для вызова скрипта через ярлык нельзя назначить нашу любимую комбинацию Shift+Alt (или Alt+Shift, кому как удобнее). Она зарезервирована для переключения языков, поэтому штатными средствами никак ее не вызвать.

Хорошо, что есть средства поинтереснее. Программисты — народ до невозможности ленивый и изобретают многочисленные способы, как можно упростить себе жизнь за компьютером. Так и был придуман пакет AutoHotKey, сокращенно AHK. Пакет предназначен для выполнения скриптов по автоматизации различных действий с клавиатурой с очень большим набором функций. На основе AHK можно решить искомую задачу по переключению языков нужной комбинацией клавиш на клавиатуре. Например, для своих целей я разработал следующий скрипт для версии 2, а скрипты для 1 и второй версий не совместимы по синтаксису, AHK:

#Requires AutoHotkey v2.0
#SingleInstance Force
eng := 1033 ; Английский
rus := 1049 ; Русский
!LShift::
{
    ; Получаем идентификатор текущей раскладки клавиатуры
    hkl := DllCall("GetKeyboardLayout", "UInt", DllCall("GetWindowThreadProcessId", "UInt", WinExist("A"), "UInt", 0))
    ; Извлекаем язык из идентификатора раскладки
    langID := hkl & 0xFFFF ; Младшие 16 бит содержат идентификатор языка
    ;MsgBox ("Текущий язык:" . langID) ; Выводим идентификатор языка если надо посмотреть его
    if (langID = eng) {
        SendInput "!+0" ; переключаемся на русский через нажатие клавиш переключения Cntrl+Shift+0
        PostMessage(0x50, 1, 0x04190419, , "A") ; переключаемся через отправку команды с кодом RU через WM_INPUTLANGCHANGEREQUEST (не работает в окнах типа SaveAs)
    } else {
        SendInput "!+9" ; переключаемся на английский через нажатие клавиш переключения Cntrl+Shift+9
        PostMessage(0x50, 1, 0x04090409, , "A") ; переключаемся через отправку команды с кодом EN через WM_INPUTLANGCHANGEREQUEST (не работает в окнах типа SaveAs)
    }
    ; Исправляем проблему с непечатанием большой буквы, если отжать Alt
    KeyWait( 'Alt' ), Send('{Shift down}')
    KeyWait('Shift'), Send( '{Shift up}' )
}

В скрипте язык можно переключить двумя способами (и все по нажатию левого Shift и Alt):

  1. Через вызов специального системного сообщения посредством команды PostMessage, в примере скрипта эта возможность включена.
  2. Через эмуляцию нажатия клавиш Alt+Shift+0 и Alt+Shift+9. Эти комбинации используются для включения русского и английского языков в языковой панели Windows, а комбинация Alt+Shift для переключения языков в языковой панели, наоборот, отключена. И эта возможность тоже включена.

Возможны и другие варианты переключения, например, через вызов системной DLL с передачей информации о необходимости смены языка туда, либо через вызов функции PowerShell. Но я остановился именно на эмуляции нажатия и отправкой системного сообщения, так как эта комбинация работает в том числе и в диалогах сохранения файлов, на рабочем столе и прочих неочевидных местах (в отличие от только одного варианта с PostMessage или SendInput). Если с таким задвоенным способом переключения возникают проблемы, то достаточно закомментировать лишний и перезапустить скрипт. При необходимости переключения на другие языки я использую опять же штатную функцию переключения через WinKey+Space, языки переключаются циклически, что мне и требуется.

Скрипт AHK можно запускать как скрипт, передавая его самому интерпретатору AutoHotKey, а он регистрируется как исполняющая программа для файлов с расширением .ahk. Либо скомпилировать скрипт в исполняемый файл и запускать его как обычную программу. Запуск в автоматическом режиме можно осуществлять либо через папку автозапуска Windows, либо через планировщик. Я запускаю его через планировщик по событию начала сессии в системе (Log on).

Настройка языковой панели для корректного выполнения скрипта при переключении через эмуляцию нажатия кнопок

Настройка языковой панели для корректного выполнения скрипта при переключении через эмуляцию нажатия кнопок

При работе скрипта (как скомпилированного, так и запускаемого через интерпретатор) есть нюанс. Если он запущен не с административными привилегиями, то он не сможет переключать язык в программе, запущенной в режиме администратора. Для исправления ситуации необходимо запустить скрипт (или его скомпилированную версию) с административными правами. Тут важно доверять разработчикам AHK, так как программа с административными правами может натворить много интересного в системе. Но все исходные коды AHK доступны в открытом доступе на GitHub, поэтому любой специалист может с ними ознакомиться и убедиться, что никаких «закладок» в программе нет (или, наоборот, есть). Либо просто использовать WinKey+Space для переключения языка в тех случаях, когда AHK не срабатывает.

И тут есть нюанс. Я печатаю на клавиатуре довольно быстро и «слепым» методом, спасибо Шахиджаняну. Поэтому после переключения языка, если мне требуется набрать следующее слово с большой буквы, то я не отжимаю клавишу Shift, а только отпускаю Alt.

; Исправляем проблему с непечатанием большой буквы, если отжать Alt
KeyWait( 'Alt' ), Send('{Shift down}')
KeyWait('Shift'), Send( '{Shift up}' )

Поэтому вот этот кусочек кода в скрипте позволяет именно так и поступить. После отпускания Alt, если все еще нажат Shift, я могу вводить текст большими буквами.

; Замена стрелок в Obsidian
#HotIf WinActive("ahk_exe Obsidian.exe")
    :B*:-Ю::→
    :B*:Б-::←
#HotIf

В качестве небольшого бонуса привожу крошечный кусочек кода, который позволяет, не переключая раскладку, заменять набранные в русском языке последовательности ‘-Ю’ и ‘Б-’ на ‘→’ и ‘←’ соответственно. Прямо на лету. Код можно добавить в скрипт переключателя клавиатуры. Срабатывает он только в приложении Obsidian.

Дополнительные материалы для самостоятельного изучения:

  1. Официальный сайт AutoHotKey.
  2. GitHub-репозиторий AutoHotKey.
  3. Форум для помощи по 2 версии AutoHotKey.
  4. Список кодов языков в Windows.
  5. Раскладка для китайского Пиньина в японском.
  6. Punto Switcher.
  7. Клавиатурный тренажёр Шахиджаняна.
  8. Wiki по AHK 1.x на русском языке.

Опубликовано автором в следующих категориях:
Soft

Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии