На дворе 2022 год, и, казалось бы, всё, что касается такой воспомогательной функции, как переключение языков ввода, уже должно быть давным-давно написано… Но, нет предела стремлению к совершенству. Началось с мелочи: у меня в системе установлены три языка – русский, английский и китайский. Переключались они всегда в цикле по сочетанию Alt+Shift и нужны были все три постоянно. Всё было хорошо, пока в какой-то момент (примерно полгода назад), китайский не “выпал” – стал требоваться редко и начал мешать при переключении Ru-En. А отключать его насовсем в мои планы не входило…

И тому была причина: “китаизация” ввода под Windows – это вообще отдельная история и отдельный мир. В этом мире по-прежнему используются разные программы а-ля “русификаторы”, точно, как у нас было когда-то. Встроенный в систему китайский ввод настолько плох, что им не пользуется никто, все сразу ставят свою программу. А поскольку встроенным вводом никто не пользуется, он и не эволюционирует – существует чисто для галочки, а не для практического применения… Вот. И я установил себе прекрасный (на мой взгляд) Thunisoft Huayu Pinyin и ломать настроенное совсем не хотелось.

А хотелось совсем немного: чтобы по привычному мне сочетанию Alt+Shift переключались русский и английский, а китайский, оставаясь в системе, пропускался и включался отдельной кнопочкой. Вроде, ничего сверхъестественного я не желал, правда? Однако, оказалось, что средствами Windows такое настроить нельзя. Можно на каждый язык сделать отдельную кнопку, а вот циклическое переключение будет перебирать их все… Да, в "десятке" это точно так же, как и во всех предыдущих версиях. Ну, ладно, нет так нет, думаю – найду сторонний переключатель. И не нашел. Всевозможные свитчеры предлагали что угодно, но только не нужную мне функцию. Это было настолько неожиданно, ведь задача кажется такой простой, очевидной и востребованной. Лично знаком с человеком, у которого шесть языков установлено, он их переключает мышкой в панели задач...

Ни сходу, ни специально засев в интернете для поиска, готового решения найти не смог. В сети находились только вопросы, о том, как сделать такое переключение, с пропуском какого-то языка. Ответов было не слишком много, но кое-какие всё же были. Самым подходящим мне показался совет написать скрипт на AutoHotkey. Это довольно известная и мощная программа со встроенным скриптовым языком для создания различных макрокоманд . Более того, скрипт можно скомпилировать в exe-файл и далее он будет жить уже самостоятельно, без AutoHotkey в системе. Мой скрипт перехватывает нажатие Alt+Shift и эмулирует нажатие сочетаний Ctrl+9 и Ctrl+0, к которым я привязал русский и английский, соответственно. Исходный код скрипта:

ru := DllCall("LoadKeyboardLayout", "Str", "00000419", "Int", 1)

SwitchLang()
{
 global ru
 w := DllCall("GetForegroundWindow")
 pid := DllCall("GetWindowThreadProcessId", "UInt", w, "Ptr", 0)
 l := DllCall("GetKeyboardLayout", "UInt", pid)
 if (l = ru) 
  {
   Send {LCtrl Down}{0 Down}{0 Up}{LCtrl Up}
  } 
 else 
  {
   Send {LCtrl Down}{9 Down}{9 Up}{LCtrl Up}
  }   
}

!~LShift UP::
{
 if GetKeyState("Alt") 
  {   
   SwitchLang()   
  }  
 Exit
}

~LAlt UP::
{
 if GetKeyState("Shift") 
  {   
   SwitchLang()
  }  
 Exit
}

Своей цели я добился, но, всё же, полоноценным это решение назвать было нельзя. Оно больше походит на заплатку или "взлом системы" исключительно под мою задачу. И так же оно не работает в консольном окне. Так что, поиск продолжился.

Через некоторое время, где-то в обсуждениях встретил упоминание о программе ReCaps. В этой программе наконец-то нашлась нужная функция – можно было настроить циклическое переключение избранных языков, но, правда, только на клавишу CapsLock. Конечно, хотелось бы сохранить привычное сочетание Alt+Shift… Написал автору письмо с вопросом, можно ли так сделать? Автор программы, Siaržuk Žarski, ответил и прислал тестовую версию, где сочетание клавиш уже можно было менять. Программа понравилась, с удовольствием принял участие в beta-тестировании. В конце декабря вышел релиз, ReCaps v.0.9.0.3480. Обновил исходную бету до текущей версии и продолжил пользоваться. В ней так же нет поддержки переключения языка в консоли, но зато, это уже полнофункциональный менеджер языков ввода с возможностью собирать их в группы и настраивать циклическое переключение для каждой группы отдельно. Для изменения настроек не требуется программирование, можно просто дать человеку-не программисту ссылку на программу и сказать: "Установи вот это и настрой переключение как тебе удобно"

Окно настроек ReCaps. Русский и английский включены, китайский пропускается.
Окно настроек ReCaps. Русский и английский включены, китайский пропускается.


Вот такие два способа, как управлять переключением языков, если их в системе больше двух, мне удалось найти. Надеюсь, кому-то это окажется полезным.

Комментарии (48)


  1. rrrad
    07.01.2022 09:56

    А в консоли что работает? Системное переключение по тем же клавишам? Или как-то по другому?


    1. Yko2007 Автор
      07.01.2022 10:11

      В консоли работает только системное переключение. А перехват Alt+Shift ни в скрипте, ни в программе ReCaps не работает. Естественно, Alt+Shift при этом уже не является системным, оно освобождается в настройках, чтоб его можно было перехватывать...


      1. sukhe
        07.01.2022 11:27

        Как это не работает? Только-что проверил

        Alt & Shift::
        MsgBox Hello!
        return

        Выскакивает окошко с сообщением, языки не переключаются.

        А вообще, языки можно пропускать, чтобы их не было в цикле переключения.
        Только их нужно не прямо в языки добавлять, а зайти в настройки одного или всех языков и там уже добавить нужную клавиатуру.
        То есть, языки "первого уровня" будут переключаться по Alt+Shift. А внутри каждого языка раскладки клавиатур будут переключаться по Ctr+Shift (или какую вы там настроите комбинацию).

        Может это и не совсем то, что вы хотели, но это готовые системные средства без сторонних программ.


        1. Yko2007 Автор
          07.01.2022 17:43
          +1

          Я начал было смотреть в сторону раскладок, но бросил. Помня, как иногда переклинивает переключатель в Windows, решил оставить всё максимально стандартно и просто и обойтись сторонней программой. Мне просто нужно было добиться пропускания китайского при переключении по Alt+Shift... В Windows в эти настройки ещё ведь и не попадешь одним кликом ))


        1. Yko2007 Автор
          07.01.2022 17:55

          Да, спасибо за поправку! Именно, что нажатие клавиш перехватывает, не работает именно переключение


  1. aborouhin
    07.01.2022 10:15
    +1

    Я в своё время решал более простую задачу - просто переключение между двумя языками через CapsLock. Пробовал и скрипты AutoHotkey, и ReCaps, и lswitch, и какой-то caps-min-shift (это имя exe'шника, не помню, где его добыл). У всех этих вариантов был один недостаток - в один прекрасный момент они переставали работать, что лечилось только выгрузкой (убийством процесса) свитчера и его повторным запуском. Возможно, это связано с тем, что дело было на ноуте, который часто отправлялся в гибернацию/сон, но бесило жутко.

    В итоге решилось ремаппингом CapsLock на Win+Space через PowerToys - это железобетонный вариант, который пока ни разу не подводил.

    Интересно, сейчас у ReCaps уже нет этой проблемы? А то решение с PowerToys имеет свои ограничения.


    1. Yko2007 Автор
      07.01.2022 10:30
      +1

      Тьфу-тьфу за полгода ReCaps не слетал. Несколько раз за это время переключение заклинивало, но расклинивалось системным переключателем Win+Space и дальше продолжало работать без перезапуска программы. С чем было связано - не отследил.


    1. iClo
      07.01.2022 10:38
      +1

      PowerToys тоже костыль костыльный. Win+Space при переключении показывает свитчер языков, что в случае с двумя языками совсем ненужная вещь. И при активной печати это часто сбоит. То CapsLock чуть передержишь и дважды язык меняется, то интерфейс windows подтормозит и переключится с задержкой. Есть возможность переключать без свитчера по shift+ctrl(именно в таком порядке), но PowerToys отказывается так мапить кнопки.

      PS Проверил рекапс, работает прекрасно!


      1. aborouhin
        07.01.2022 10:45

        Ну вот как раз всплывающее окошко как раз и бесит, да, когда быстро набираешь русский текст с английскими терминами, например, оно в углу мелькает как ненормальное :( Других проблем не замечал, так что для меня сейчас это лучший вариант.


      1. mSnus
        08.01.2022 21:19

        А при вводе пароля на входе в Винду он работает?


    1. Fodin
      07.01.2022 14:14

      В ту же коллекцию keyla. Просто в произвольные моменты перестает переключать. Комп стационарный, в сон вгоняю постоянно вместо выключения.


      1. orcy
        08.01.2022 08:24

        Тоже пользовался keyla и когда она перестала работать у меня думал починить (яжпрограммист), но вместо этого настроил autohotkey.


    1. perfect_genius
      07.01.2022 22:35
      +1

      А чем не нравится kbdxenru от хабровчанина?


      1. aborouhin
        07.01.2022 23:56

        Ну, наверное, тем, что когда я эти все варианты перебирал, его не нашёл :) Насколько подсказывает быстрое гугление, это раскладка, сделанная с помощью MS Keyboard Layout Creator. Точно помню, что эту софтину я ставил, ковырялся с ней, но удовлетворительного результата не достиг. Но уже не помню, почему именно.

        Надо посмотреть как-нибудь на досуге и на этот вариант, спасибо.


        1. perfect_genius
          08.01.2022 11:09

          Единственное, что мне неприятно в ней — что диод горит на русскую раскладку, когда хотелось бы наоборот.


    1. p07a1330
      08.01.2022 19:15

      Поставить в планировщике задач их перезапуск каждые сутки - не решило бы проблему?


  1. dzmitry_li
    07.01.2022 10:49
    +3

    А я пользуюсь группами переключения: по Alt+Shift переключаю "En" и "Be/Ru"; в группе "Be/Ru" по Ctrl+Shift переключаю "Be" и "Ru".

    И это стандартная функция в Windows 10 (в Windows 7 тоже есть, но в группе переключается только мышкой)


  1. armid
    07.01.2022 11:33

    @Yko2007 Какую комбинацию вы поставили на китайский язык?


    1. Yko2007 Автор
      07.01.2022 17:26

      Сейчас, когда почти не пользуюсь китайским, при надобности включаю его по Win+Space или вообще мышкой. Когда пользовался активно, то была карусель Ru-En-Ch на Alt+Shift


  1. cepera_ang
    07.01.2022 11:34

    Разве это не то, что вам нужно?



    Просто запихать популярные раскладки в один "язык" (т.е. в "языке" англиский будет и русская и английская раскладка), а оставшийся — в отдельный. Правда только сейчас понял, что там нельзя добавить сильно отличающуюся раскладку (т.е. кириллицу в "английский"), но можно наверное сделать свою раскладку как бы для английского, но с русскими буквами в layout creator'e.


    У меня другая проблема — пользуюсь колемаком, но грёбаная винда зачем-то автоматически добавляет раскладки всех используемых языков (English US — язык системы, English UK — язык всяких форматов даты и т.д.).


    1. Yko2007 Автор
      07.01.2022 17:28

      Вот о том и речь, что системными настройками "чисто" это не делается... Я посмотрел-посмотрел на возможные варианты и отправился искать стороннюю программу


  1. boulder
    07.01.2022 13:08
    +1

    Послушайте, ну есть же стандартный способ переключения — вешаем разные языки на Alt+Shift+1, Alt+Shift+2 и так далее. Или даже используя Ctrl-Shift, если неохота пальцы "корячить".


    1. Yko2007 Автор
      07.01.2022 17:30

      Конечно так можно. Но у меня задача была сохранить привычное переключение на Alt+Shift. Ну, вот, нравится мне оно. И при этом чтоб третий язык не мешал. Но и чтоб не удалять его из системы насовсем - изредка бывает нужет


      1. perfect_genius
        07.01.2022 22:30

        А Caps Lock'ом пользуетесь?


  1. ten-thousandth
    07.01.2022 16:01

    Спасибо!
    Чем Thunisoft Huayu Pinyin лучше 搜狗输入, какие преимущества?


    1. Yko2007 Автор
      07.01.2022 17:35

      Рекламу и новости не показывает. (У меня версия 7.1.3.154). После того, как Google Pinin приказал долго жить, тоже пользовался 搜狗, но там удалял модуль показа рекламы, который был отдельным экзешником. В итоге, оно изредка ругалось, но это было меньшее зло чем постоянно всплывающие баннеры... Возможно, была возможность их просто отключить в настройках, но что-то тогда не нашёл где...


  1. Nibi
    07.01.2022 16:01

    Под Win7 пользуюсь Mahou. Между двумя раскладками переключаюсь Ctrl+Shift, третью включаю Alt+Shift. Заодно решается вопрос с переключением раскладок во ВСЕХ окнах, как в десятке. Т.е. если в одном окне включил EN, то при переходе к другому тоже будет EN (автоматом быстро переключается).


  1. stalinets
    07.01.2022 17:23

    Пользуюсь MKey, но программка уже заброшена и не развивается. Также бывают некоторые глюки с ней:

    1) Иногда она подвисает и перестаёт работать, надо через интерфейс в трее выключить и включить.

    2) Через несколько тысяч нажатий она выкидывает окно с просьбой доната, в норме активный пользователь ПК должен видеть такое окно 1-2 раза в год, но у меня есть USB-устройство, которое постоянно передаёт данные, воспринимаемые этой программкой как нажатия на клавиатуру, и окошко выскакивает несколько раз в день, что бесит.

    3) Иногда фактический язык и отображаемый в трее не совпадают.

    4) В некоторых текстбоксах (консоли, переименования файлов и папок в некоторых случаях) она не работает.

    Надо будет попробовать Recaps.

    А ещё лучше было бы, если б производители клавиатур стали с обратной стороны клавиатуры прикручивать маленький ползунковый переключатель, меняющий функцию CapsLock со стандартной на переключение языка (при этом Shift+CapsLock работало бы как стандартный CapsLock)...


    1. cepera_ang
      07.01.2022 17:49

      А ещё лучше было бы, если б производители клавиатур

      Соберите сами на базе QMK :) Тем более, что есть практически готовые варианты и в прошивку можно хоть 20 функций на любую кнопку повесить.


    1. dikey_0ficial
      07.01.2022 20:13

      Недавно задумался, зачем современному пользователю компьютеров/телефонов нужен капслок. В голову приходят лишь идеи о sql-запросах и кликбейтных заголовках


  1. yurybx
    07.01.2022 17:52

    Устал от этих костылей. Хочу клавиатуру, на которой будет три кнопки: укр, рус, англ.


    1. cepera_ang
      07.01.2022 17:53

      Так сделайте :) Три свитча, 3д печатный корпус, ардуинка, QMK :)


      И готовые продаются: https://aliexpress.ru/item/1005001708911988.html?sku_id=12000017242086277


      image


    1. toxicdream
      08.01.2022 18:55

      AutoHotkey-ем сделал перехват клавиш CapsLock, SrollLock и Pause/Break и "конвертацию" в "стандартные" Ctrl+Shift+1/2/3 на которых висят нужные мне En/Ru/Kk


    1. toxicdream
      08.01.2022 20:46

      В Вин10 работает везде железобетонно!

      #Persistent
      #SingleInstance
      #KeyHistory 0
      #NoEnv
      #HotkeyModifierTimeout 100
      
      SetNumLockState, AlwaysOn
      SetCapsLockState, AlwaysOff
      SetScrollLockState, AlwaysOff
      
      CapsLock::^+1
      Pause::^+2
      ScrollLock::^+3
      
      return


  1. mvalery
    07.01.2022 17:58
    +1

    Я мечтаю подсоединить вспомогательную клавиатуру на которую назначены все языки которыми я пользуюсь. Чтобы переключать одним нажатием.
    К сожалению, готового решения нет. Либо исполнять танец с бубнами, устанавливая и самостоятельно приспосабливая софт для второй клавиатуры, либо покупать специальную клавиатуру, к которой прилагается готовый софт.


    1. Alexeyslav
      09.01.2022 12:16

      Вообще-то есть. и давно. Есть программируемые клавиатуры, как для кассовых аппаратов там на каждую кнопку можно назначить любую последовательность нажатий кнопок. Но тогда это было длвольно специализированное изделие и дорогое. Сейчас же их можно самому сделать, на ардуине, например.


  1. shavluk
    07.01.2022 18:00

    Ппоблема трех раскладок решается двумя языками ввода, и для одного из них две раскладки клавиатуры. Язык ввода переключается ctrl-shift, а раскладка в пределах языка alt-shift. En, Ru, Ua. Английский (En)и украинский языки (две раскладки Ukr Ua и Ukr Ru).

    Я настроил себе переключение тоже через AutoHotKey. Но я поборол проблемы с консолью.

    Язык ввода меняю через длинное нажатие на LShift / RShift, предыдущую раскладку сохраняю.


    1. Yko2007 Автор
      07.01.2022 18:35

      А как побороли переключение в консоли?


      1. shavluk
        07.01.2022 18:42

        Пример ниже


      1. shavluk
        07.01.2022 18:46

        Возможно я не совсем понимаю понятие "консоль". У меня в FAR и cmd переключает


    1. shavluk
      07.01.2022 18:39
      +1

      Вот пример моего скрипта:

      ; Переключение языков по Shift, с сохранением раскладки для языка
      ; Левый - Английский
      ; Правый - Украинский, текущая клавиатура (на язык повешено 2 раскладки)
      #NoEnv
      #SingleInstance force
      
      Process Priority,, High
      
      layouts := GetLayoutList()
      
      ~LShift Up::
        if (A_PriorKey = "LShift") 
          SwtichLang(layouts, 1033) ; English
      return
      
      ~RShift Up::
        if (A_PriorKey = "RShift") 
          SwtichLang(layouts, 1058) ; Ukraine
      return
      
      ;~LShift Up::
      ;  if (A_PriorKey = "LShift") 
      ;    SwtichLang(layouts, 0)
      ;return
      
      SwtichLang(ByRef layouts, LangId) {
        InputLocaleID := GetKeyboardLayout()
        lang := InputLocaleID & 0x0000FFFF 
      
        if (LangId == 0) {
          prev := 0
          for index, element in layouts {
            if (index == lang && prev != 0) {
              SwtichLang(layouts, prev)
              return
            } else 
              prev := index
          }
          if (prev != 0) {
            SwtichLang(layouts, prev)
            return
          }
        } else
        if (lang != LangId) {
          layouts[lang] := InputLocaleID  ; Сохраняем раскладку текущего языка
          newLocale := layouts[LangId]
      
          kbd_msg(Format("{:U}", GetLangName(LangId)))
      ;    Send, {Ctrl Down}{Shift Down}{Shift Up}{Ctrl Up}
          ControlGetFocus, ctl
          PostMessage 0x50, 3, %newLocale%, %ctl%, A
        }
      }
      
      GetKeyboardLayout() {
         hWnd := WinExist("A")
      
         WinGetClass, winClass
         if ((winClass != "ConsoleWindowClass") || (b := SubStr(A_OSVersion, 1, 2) = "10"))  {
            if b {
               dhw_prev := A_DetectHiddenWindows
               DetectHiddenWindows, On
               hWnd := WinExist("ahk_exe conhost.exe")
               DetectHiddenWindows, % dhw_prev
            }
            threadId := DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0)
            lyt := DllCall("GetKeyboardLayout", Ptr, threadId, UInt)
            return lyt
         }
         else {
            WinGet, consolePID, PID
            DllCall("AttachConsole", Ptr, consolePID)
            VarSetCapacity(lyt, 16)
            DllCall("GetConsoleKeyboardLayoutName", Str, lyt)
            DllCall("FreeConsole")
            return lyt
         }
      }
      
      GetLayoutList() {
          aLayouts := []
          size := DllCall("GetKeyboardLayoutList", "UInt", 0, "Ptr", 0)
          VarSetCapacity(list, A_PtrSize*size)
          size := DllCall("GetKeyboardLayoutList", Int, size, Str, list)
          Loop % size { ; для каждого языка сохраняем одну раскладку
              aLayout := NumGet(list, A_PtrSize*(A_Index - 1))
              lang := aLayout & 0x0000FFFF
              if (aLayouts[lang] == null) 
                aLayouts[lang] := aLayout 
          }
          Return aLayouts
      }
      
      GetLangName(LocID, FullName = false) {
        static SISO639LANGNAME            := 0x0059 ; ISO abbreviated language name, eg "EN"
        static LOCALE_SENGLANGUAGE        := 0x1001 ; Full language name, eg "English"
      
        LCType := FullName ? LOCALE_SENGLANGUAGE : SISO639LANGNAME
        Size := (DllCall("GetLocaleInfo", UInt, LocID, UInt, LCType, UInt, 0, UInt, 0) * 2)
        VarSetCapacity(localeSig, Size, 0)
        DllCall("GetLocaleInfo", UInt, LocID, UInt, LCType, Str, localeSig, UInt, Size)
        Return localeSig
      }
      
      kbd_msg(text) {
        no_detect_window := -1
        ToolTip, %text%, A_CaretX + 10, A_CaretY - 20
        SetTimer, KbdRemoveToolTip, -1000
        return
          
        KbdRemoveToolTip:
        ToolTip
        no_detect_window := 1
        return
      }


      1. xaosxaos2
        08.01.2022 17:01

        Что-то слишком тяжеловато что-ли. У меня попроще, только на контралах левая английская правая русская, ну и системное ctrl+shift switch.
        ControlGetFocus, ctl
        PostMessage 0x50, 3, %newLocale%, %ctl%, A

        ммм зачем? прекрасно работает просто
        PostMessage 0x50, 0x0, %newLocale%,, A


      1. Yko2007 Автор
        08.01.2022 23:50

        Действительно, это работает в консоли! Спасибо большое!


      1. Yko2007 Автор
        08.01.2022 23:51

        Действительно, это работает в консоли! Спасибо большое!


  1. rg_software
    08.01.2022 01:17
    +1

    Автор, понимаю вашу боль, сам замучился с аналогичной задачей. На сегодняшний день нашёл таки хороший софт Keymanager, который вроде как все решает.


  1. Tsentr
    08.01.2022 19:01

    Спасибо


  1. IGR2014
    08.01.2022 19:15

    Win + [пробел]


  1. GlebZki
    08.01.2022 23:57

    После многих лет поиска решения, нашёл удобный вариант прямого переключения раскладки клавитуры с помощью двух-кнопчного сочетания Alt+1, Alt+2, Alt-3, ...
    Имплементация - на AutoHotkey, скрипт долщен быть запущен с повышенными привилегиями для тех у кого включен UAC. Работает везде, включая RDP, VNC, консоль и т.д.
    Список кодов для нужного языка - здесь: Default Input Profiles (Input Locales) in Windows | Microsoft Docs.

    #Persistent						 ; Do not get killed by errors
    #InstallKeybdHook	     ; Install keyboard hook for extended hotkeys
    #UseHook               ; Do not open Windws Start Menu on Win-kepress
    
    en := DllCall("LoadKeyboardLayout", "Str", "00000409", "Int", 1)
    ru := DllCall("LoadKeyboardLayout", "Str", "00000419", "Int", 1)
    he := DllCall("LoadKeyboardLayout", "Str", "0000040D", "Int", 1)	
    
    !1::									;  Alt+1				: US keyboard
    	WinWait, A
    	WinWaitActive, A
    	ControlGetFocus, ctl, A
    	PostMessage, 0x50, 0, %en%, %ctl%, A
    	PostMessage, 0x50, 0, %en%,, A
    	Return
    
    !2::									;  Alt+1				: Hebrew keyboard
    	WinWait, A
    	WinWaitActive, A
    	ControlGetFocus, ctl, A
    	PostMessage, 0x50, 0, %he%, %ctl%, A
    	PostMessage, 0x50, 0, %he%,, A
    	Return
    	
    !3::									;  Alt+1				: Russian keyboard
    	WinWait, A
    	WinWaitActive, A
    	ControlGetFocus, ctl, A
    	PostMessage, 0x50, 0, %ru%, %ctl%, A
    	PostMessage, 0x51, 0, %ru%,, A
    	Return