Речь пойдет о программе LangBar++, сейчас, как я надеюсь, готовой к выходу из форумного подземелья в свет. Написание программ такого рода принадлежит к одной из неисчерпаемых тем, разработанных в самых разных направлениях. Большая часть таких изысканий оказывается посвящена конкретным неудобствам, особо допекающими автора, и с их устранением исчезает и стимул дальнейшего развития. Вопрос же создания чего-то большего “в одном флаконе” до сих пор висит в воздухе. Не то, что бы я намеревался создать нечто великое в этой области и превзойти легенды. Напротив, я шел тем же путем малых решений, но из периодического возвращения к одной и той же теме постепенно сформировалось нечто целостное, что сейчас и предлагается вашему вниманию.

Прежде всего, я не люблю автоматику, и, подобно многим, здесь присутствующим, почти не могу пользоваться автоматическим исправлением раскладки в обычной жизни. Ручное же использование Punto Switcher и подобных ему программ и скриптов всегда казалось неудобным, и как-то я написал скрипт на Autohotkey, работающий с выделением набранного текста, пока нажата пауза Pause, так что можно последовательно менять несколько последних набранных слов:

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

Это явно не для всех, но привыкнуть можно, тем более что скорость выделения сейчас детально настраивается для любых навыков печати, от самых детских до вполне профессиональных. Исправление раскладки работает в командной строке, FAR, ConEmu и терминале Windows 10-11, причем из-за особенностей этих программ вместо выделения текста по сочетанию Shift+Left производится его забивание:

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

Примерно в то же время мне попался достаточно популярный скрипт Irbis, отрисовывающий флажок раскладки у текстового курсора. Скрипт был доработан, флажок был сделан c настраиваемым размером и прозрачностью, необходимость чего следовала уже из увеличивающегося диапазона разрешений мониторов и возможной полезности для подслеповатых людей:

К флажку была добавлена поддержка командной строки, появилась иконка раскладки в трее, был прикручен вышеописанный скрипт исправления раскладки, и все вместе это было выложено на форуме Ru.Board под именем LangBar++, в полной уверенности отсутствия далеко идущих последствий. Идея понравилась, но общество потребовало дальнейших шагов. И, прежде всего, возможности отображения флажков других раскладок. Следуя излюбленному принципу наименьшего действия, я добавил на такой случай иконку и флажок с вопросительным знаком. Вышло терпимо, но сам этот вопросительный знак не давал мне спокойно жить: программа тихо сползала в многоязычность, и сделать с этим что-то было сложно.

Поскольку же автор имеет права самозащиты, он может взваливать ненужный труд на плечи пользователя. Никаких флажков в ресурсах, как в Punto Switcher - пусть сами выбирают то, что им нравится и с тем живут! Была сделана генерация иконок из тех же png-флажков, а там стало естественным добавить отображение состояния кнопок NumLock и ScrollLock на иконке в трее, как на флажке отображается CapsLock. Визуальные элементы, используемые для этого легко заменяемы, как и флажки, архив которых идет с программой. Не нравится ушастая иконка - можно сделать мигающие глазки или что еще. Имеется интерфейс, отображающий требуемые названия флажков и быстро открывающий папку с ними:

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

Из Punto Switcher потянулся длинный кармический хвост в виде преобразования регистра набранного текста и его транслитерации, сделанных уже с таким же беглым его выделением. В дополнение к переключению раскладки при клике левой кнопкой мыши, флажок получил возможность исправления набранного текста и инверсии раскладки при нажатии на него соответственно правой и средней кнопкой мыши. Все работает с тем же “быстрым выделением”, и, иногда, это удобно.

Кнопка CapsLock обросла множеством настроек. Помимо ее простого выключения или использования в качестве Shift, можно использовать ее для переключения раскладки, ее исправления или инверсии регистра, в последнем случае даже с сохранением ее основной функции. Имеются необходимые настройки и для остальных Lock-клавиш.

Программа отображает флажок не во всех программах (вроде злополучного терминала и “современных” (UWP) приложений), поэтому было решено сделать неподвижный индикатор раскладки. Кроме того, многие не без причин предпочитают самодельный скрипт, отображающий флажок или даже просто цветной прямоугольник в центре экрана - на уровне навыков это проще, не нужно следить ни за кареткой, ни за индикатором в трее. К тому же, его можно сделать достаточно большим, так что какое-то угловое, рассосредоточенное зрение будет само собой фиксировать то, что он показывает. Очевидно, выгода есть и для обычных людей, и для незрячих. Здесь это все та же иконка в трее, только увеличенная, на которой отрисовывается состояние всех Lock-клавиш (два “уха” на NumLock и ScrollLock, голубая “тень” для CapsLock). По умолчанию индикатор прозрачен для кликов, но возможно его использование и в качестве дополнительного переключателя раскладки.

Подобно флажку, индикатор можно включать и выключать по горячим клавишам, но это довольно докучливое дело - он должен появляться там, где он нужен и исчезать там, где нет. Сделан интерфейс, быстро вызывающийся по горячей клавише и позволяющий через перетаскивание иконки создавать правило для данного приложения:

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

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

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

Помимо этого, на левые и правые клавиши Ctrl и Shift возможно повесить четыре настраиваемых раскладки для их быстрой активации. Есть и возможность вызова раскладок по горячим клавишам, автоматически сгенерированным на основании их последовательности. Таким образом, программа получила наиболее мощные возможности для работы с множеством языков ввода.

В описании сказано, что программа “отличается высокой совместимостью”. LangBar++ производит запись виртуальных кодов клавиш, и поэтому не зависит от физического типа клавиатуры и используемых раскладок. Если у вас ужатая клавиатура, вместо кнопки Pause можно использовать сочетание клавиш Shift+Backspace, достаточно удобное ввиду их размера. Настройки флажка, производимые на ПК мышью, на ноутбуке выполняются через отдельный интерфейс. Имеются настройки сглаживания и масштабирования флажка, позволяющие адаптировать программу к достаточно добитым мониторам.

Переключение языка ввода, - часто наиболее существенное, что реально ограничивает использование такого рода программ, - по умолчанию производится посылкой обычных клавиш изменения раскладки, а не “посылкой сообщений” (Post- или SendMessage), как у аналогов, что может приводить к падению приложений, даже таких именитых, как изделия Autodesk. Есть демон, перезапускающий ее при крайне редких, но полностью неисключимых падениях. В наличи бэкап (или сброс плюс бэкап) настроек в каталог программы.

Имеется адаптация к работе на виртуальных машинах. Установленная на хосте версия автоматически блокируется, а запущенная на гостевой системе выполняет основной функционал, ограниченный погрешностями работы горячих клавиш, которых почти нет в продуктах VMware и хватает на VirtualBox.

Программа идет в одном исполняемом файле, откуда возможна установка и распаковка портативной версии. Предусмотрено быстрое копирование настроек и флажков из каталога установки, если в этом возникнет необходимость.

Наконец, программа свободная, код в Autohotkey v1.1 выложен на GitHub. Возможно, вам удастся вывести из нее что-нибудь еще. Успехов!

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


  1. aborouhin
    17.05.2023 17:21
    +1

    Да уж, монументальная работа. Даже не подозревал, что чисто на AutoHotkey можно написать настолько сложную штуку. У меня скрипт, который переключает раскладку по CapsLock и показывает на экране всплывающую надпись "RUS" или "ENG", на полсотни строк, из них половина скопирована из чужих наработок, так я и то утомился его писать, настолько противоестественный язык :)


    1. MountainGoat
      17.05.2023 17:21
      +1

      SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
      SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
      
      CapsLock::SetInputLang(0x0409) ; English (USA)
      +CapsLock::SetInputLang(0x0419) ; Russian
      
      SetInputLang(Lang)
      {
          WinExist("A")
          ControlGetFocus, CtrlInFocus
          PostMessage, 0x50, 0, % Lang, %CtrlInFocus%
      }
      
      isFullScreen()
      {
          WinGetPos ,,, wp, hp, A
          return (wp hp = A_ScreenWidth A_ScreenHeight)
      }
      
      #If isFullScreen()
      LWin::Return
      #If

      Капслок на английский, шифт+капслок на русский, ну и заодно блокирует кнопку "Вынь" в полноэкранных приложениях.


      1. aborouhin
        17.05.2023 17:21
        +1

        Ну мне два разных хоткея неудобно, удобно переключаться одним, но показывать, на что переключились. Так что вот так:

        CapsLock::
        {
        	CloseOSD()
        
        	DetectHiddenWindows, on
        	SetFormat, Integer, H
        	WinGetClass, AWinClass, A
        	If (AWinClass = "ApplicationFrameWindow") {
        		ControlGetFocus, Focused, A
        		ControlGet, WinID, Hwnd, , % Focused, A
        	} Else {
        		WinGet, WinID, ID, A
        	}
        	ThreadID := DllCall("GetWindowThreadProcessId", "UInt", WinID, "UInt", 0)
        	InputLocaleID := DllCall("GetKeyboardLayout", "UInt", ThreadID)
        
        	If (InputLocaleID = 0x4090409) {
        		LayoutID := DllCall("LoadKeyboardLayout", "Str", "00000419", "Int", 1)
        		KBLang = RUS
        	}
        	If (InputLocaleID = 0x4190419) {
        		LayoutID := DllCall("LoadKeyboardLayout", "Str", "00000409", "Int", 1)
        		KBLang = ENG
        	}
         	ControlGetFocus, control, A
        	PostMessage 0x50, 2, %language%, %control%, A ; WM_INPUTLANGCHANGEREQUEST
        
        	MonX := A_ScreenWidth / 2 - 50
        	MonY := A_ScreenHeight / 2 - 20
        	Gui, +AlwaysOnTop +LastFound +Owner
        	Gui, Color, EEAA99
        	Gui, Font, s32, Calibri
        	Gui, Add, Text, cWhite x0 y0, %kblang%
        	WinSet, TransColor, EEAA99
        	Gui, -Caption
        	Gui, Show, X%MonX% Y%MonY% NA, AHK_OSD
        	SetTimer, CloseOSD, 500
        	return
        }
        CloseOSD()
        {
        	Gui, Destroy
        	SetTimer, , Delete
        	return
        }

        Но вообще, конечно, вот такой синтаксис выносит мозг совершенно. Если бы я замахивался на проект такого масштаба, как у автора статьи - всё же выбрал бы написание с нуля на нормальном языке, проще ту часть, которую нам даёт AutoHotkey (установка хука и обёртки над несколькими API) реализовать самому, чем так... IMHO, конечно.


        1. langbarxx Автор
          17.05.2023 17:21

          Скриптовый язык легко справляется с такими задачами - это же не анализ быстрых данных, где можно легко захлебнуться. Олимпийская скорость пять символов в секунду. Частота обновления позиции флажка 25 раз в секунду за глаза. Синтаксис же кто к чему привык и где родился


          1. aborouhin
            17.05.2023 17:21

            В скорости не сомневаюсь, я именно про возможности языка и синтаксис. От вызова внешних функций с указанием типов данных аргументов как строк в виде ещё одних аргументов уже трясёт :) Ну и многострочные конструкции с Gui, скажем, это ж какая боль писать отлаживать, наверное... Я, помнится, давно-давно начинал с VBA, и до сих пор очень много чего у меня написано на bash (гораздо длиннее, чем стóило писать на bash) - но добровольно к этим языкам уже не вернусь. А тут всё настолько хуже... Что заставляет ещё больше восхищаться результатом Вашей работы, впрочем :)


  1. langbarxx Автор
    17.05.2023 17:21

    Автопереключение в программе скорее всего будет, но нужно выработать какой-то бескровный метод осуществления этого ("Образование вводить осторожно, избегая кровопролития..." - М.Е. Салтыков-Щедрин, "История одного города"). Разностный метод Сергея Москалева (такого слова не может быть в этом языке никогда, поэтому мы переключим раскладку!) слишком трудоемок, требует длительной доводки на всяких несуразностях и вызывает ужас у человека, морально не готового убить на это время. Скорее всего, надо перейти к чему-то более простому, связанному с использованием словарей, что позволяет развитие компьютеров за последние 20 лет


    1. aborouhin
      17.05.2023 17:21

      Поддавшись веяниям времени :), решил и для этой задачи проверить ChatGPT. Не справилась:

      Т.е. то, что это был русский, угадала, но почему вместо введённого "На каком языке это написано" появилось какое-то "На первый взгляд всё просто" - загадка.
      Но в принципе, наверное, натренировать нейросеть специально на такую задачу должно быть не очень сложно. А OpenAI API в любом случае из-за скорости ответа не подошёл бы. Другой вопрос, что если писать не только человекочитаемые тексты, а, скажем, код - думаю, с любым подходом false positives будут зашкаливающие.


      1. langbarxx Автор
        17.05.2023 17:21

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


        1. aborouhin
          17.05.2023 17:21

          Как раз в этих случаях у него, по крайней мере, будет больше шансов, чем у чисто словарного подхода.

          Хотя по мне так игра не стóит свеч, решение, которое работает в 99% случаев, но глючит в оставшихся 1%, заставляя исправлять вручную, хуже, чем вообще никакого решения.

          Но тут субъективно, конечно. Мне и ручное исправление неверной раскладки не нужно (ну введу я по ошибке максимум 3-5 символов, прежде чем замечу неладное, быстрее вручную удалить и перенабрать), но успех Punto и последователей намекает, что я в меньшинстве.