Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также саму программу AutoHotkey и проблемы её использования)

Проект перевода документации AutoHotkey: перечень переведённых статей и статей в работе.

AutoHotkey и русский язык – дружба навеки (версия 4 от 13 июля 2006 г.)

Автор статьи - Androgen Belkin


Примечание: материал данной статьи подготовлен на релизе AutoHotkey 1.0.44.03 - May 29, 2006.


В первой версии этой статьи мы рассматривали некоторые проблемы использования AutoHotkey в случаях, когда в системе было установлено больше одного (английского) языка. Потом, под административно-художественным руководством The gray Cardinal'а, эта статья была переведена Gourmet на английский. Перевод получился таким добротным (как, на мой взгляд, и все её переводы), а The gray Cardinal был так настойчив, что автор AutoHotkey (этого доброго мужчину зовут Chris Mallett, если вы не знали) взял, да и исправил часть описанных проблем. Но, к сожалению, – не все. Эти неисправленные проблемы и рассматриваются ниже (по сравнению с предыдущим вариантом статьи, полностью переписан раздел, посвященный команде ControlSend). Ну, вперед.


AutoHotkey - очень мощный скриптовый язык. Автоматизировать можно всё что угодно (хоть я и не сторонник таких обобщений, в данном случае – это, похоже, правда). Например, один постоянно загруженный скрипт, заменил мне, по крайней мере, пять постоянно загруженных же программ, и здорово облегчил работу с остальными. Даже и не знаю, как я раньше обходился без AutoHotkey. Одно не хорошо: он не очень "дружит" с русским языком. И если вы с этим пока не сталкивались, то неприятные "сюрпризы" вас еще только ждут. Впрочем, всех этих "сюрпризов" можно с легкостью избежать, достаточно только знать, где можно поскользнуться и посыпать это место песочком. Вот таким "пропесочиванием скользкого" мы и займемся в этой статье.

(Часть здесь написанного уже упоминалась на этом форуме, но The gray Cardinal предложил соединить все в одном месте, расширить описание и осветить темные места).

Прежде, чем мы начнем, замечу, что в статье рассматривается обычная для России ситуация, когда в системе установлены два языка: английский и русский. И большинство случаев неправильной работы горячих клавиш, строк автозамены (Hotstrings и Auto-replace) и команд Send, ControlSend, ControlSendRaw связаны именно с этим двуязычием (кривые руки, конечно, не в счет).

Если у вас установлено не два, а больше языков, (или второй язык не русский, а, например, французский :)) то просто делайте соответствующие поправки.

Приступим. Чтобы ловко обходить возможные проблемы, нужно уверенно различать "две разницы":

  1. Текущую раскладку для какого-либо приложения. Ее вы переключаете клавишами Alt+Shift (или Ctrl+Shift - это у кого как настроено).
  2. Язык ввода по умолчанию (или еще говорят "раскладка по умолчанию"). Это язык, который используется при загрузке компьютера, и с которым запускаются (хоть при старте системы, хоть – в любое другое время) все программы, скрипты - все то, что обычно называют "приложения". Назначается он в Панели управления > Язык и региональные стандарты > вкладка Языки > кнопка Подробнее… > вкладка Параметры > раздел Язык ввода по умолчанию.

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

Примечание: в конце статьи есть скрипт для быстрого переключения языка ввода по умолчанию.

Горячие клавиши

Напишем и запустим такой крошечный скриптик.

^!z:: ; назначаем горячие клавиши Ctrl+Alt+z
MsgBox, Нажата горячая клавиша. ; показываем сообщение
Return ; конец действий горячей клавиши

Теперь нажмем клавиши Ctrl+Alt+z. Если вы увидели сообщение "Нажата горячая клавиша.", значит в вашей Windows язык ввода по умолчанию – английский. А если язык ввода по умолчанию у вас – русский, то при запуске скрипта, вы увидите сообщение:

"Note: The hotkey ^!z:: will not be active because it does not exist in the current keyboard layout."

что означает:

"Внимание: Горячая клавиша ^!z:: не будет активна, потому что она не существует в текущей раскладке клавиатуры."

(Тут написано "в текущей раскладке клавиатуры", но можете не сомневаться: речь идет именно о раскладке по умолчанию. Дело в том, что текущая раскладка переключается уже после запуска приложения, а вот запускается приложение (в нашем случае – скрипт) всегда и только с раскладкой по умолчанию).


Отсюда проблема.

Если назначаемая клавиша может иметь и другую раскладку, то эта клавиша становится зависимой от раскладки (языка) по умолчанию.

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

Из формулировки проблемы ясно, что она не возникает, если вы назначаете "независимую" клавишу. Например, такое назначение не зависит от раскладки и сработает всегда:

^!F11:: ; назначаем горячие клавиши Ctrl+Alt+F11

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

  1. назначать клавиши и на английском, и её русской "сожительницей" на клавиатуре, или…
  2. назначать горячие клавиши через скан-код. Как определить скан-код клавиши, описано, например, в переведенной Дедом Мазаем статье http://www.script-coding.com/AutoHotkey/KeyList.html, в разделе "Специальные клавиши". Там речь идет о клавишах, отсутствующих в списке стандартных клавиш, но никто не мешает нам поступить, как там написано, и для стандартных клавиш.

В нашем примере, для 1-го варианта, перед первой строкой (или после неё, это не важно), добавьте строку:

^!я:: ; назначаем горячие клавиши Ctrl+Alt+z

А для 2-го варианта вместо первой строки напишите:

^!sc02C:: ; назначаем горячие клавиши Ctrl+Alt+z

Конечно, назначение горячей клавиши через скан-код (sc), гораздо универсальнее. Поэтому именно этот метод я вам и рекомендую.

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

Идем дальше.

Автозамены (Hotstrings и Auto-replace)

Здесь проблема другая. Автозамены не зависят от раскладки по умолчанию, зато зависят от текущей раскладки того приложения, где используется автозамена. Чтобы понять, о чем это я, напишем и запустим такой пример автозамены из справки к AutoHotkey:

::btw::by the way. ; назначаем автозамену

Теперь запускаем Блокнот и используем в нем нашу автозамену, напечатав btw. Если Блокнот сейчас в английской раскладке, то автозамена сработает. Однако, если раскладка русская, то печататься будет не btw, а иец – русские буквы-соседи на клавиатуре, и автозамена работать откажется наотрез. Оно, вроде, так и должно быть, но это неудобно, мы же не переключаем раскладку каждый раз, когда нажимаем, например, Ctrl+C (Photoshop – не в счет :)). Вот, чтобы так было и с автозаменами, их нужно назначать двуязычно (назначить автозамену через скан-код не получится).

::btw::by the way. ; назначаем автозамену для английской раскладки
::иец::by the way. ; назначаем автозамену для русской раскладки

Добавлю, что если вы захотите использовать какие-либо управляющие клавиши (скажем, Ctrl+V) непосредственно в тексте автозамены (в некоторых случаях это очень удобно), то нужно учесть то, что я предлагаю учесть в команде Send.

Команда Send

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

Send, ^{sc02E} ; нажать CTRL+С (такая команда будет работать всегда)
Send, ^c ; нажать CTRL+С (такая - будет работать,
; только если текущая раскладка в целевом приложении – английская)

Подчеркиваю, что речь идет только об управляющих клавишах. Обычный текст высылается без ошибок. Без ошибок же работает и команда SendRaw, т.к. не высылает управляющих клавиш (так и была задумана), поэтому пользоваться ей можно смело.

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

#IfWinActive, ahk_class Notepad
F3::
; переключаем в английскую раскладку последнее найденное окно (Блокнот в нашем случае)
SendMessage, 0x50,, 0x4090409
; высылаем всякие комбинации клавиш
Send, Русский - English.+{Home}^c+{End} Вставляем сюда скопированное: ^v{ENTER}
Return ; конец действий горячей клавиши

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

Команда ControlSend (ControlSendRaw)

Тут такая особенность: нормально высылается только текст из той же раскладки, что и текущая раскладка в целевом приложении. Т.е. если высылаемый текст на русском, то счастье нам будет, только если и целевое приложение – в русской раскладке. Иными словами, нам нужно синхронизировать язык высылаемого текста и язык (раскладку) целевого приложения. Это легко сделать, если язык высылаемого текста заранее известен:

#IfWinActive, ahk_class Notepad ; будем работать в Блокноте
F3::
SendMessage, 0x50,, 0x4190419,, ahk_class Notepad ; переключаем в русскую раскладку Блокнот
ControlSend, Edit1, Первая строка.{ENTER}, ahk_class Notepad ; высылаем первую строку на русском
SendMessage, 0x50,, 0x4090409,, ahk_class Notepad ; переключаем в английскую раскладку Блокнот
ControlSend, Edit1, Second String.{ENTER}, ahk_class Notepad ; высылаем вторую строку на английском
Return

Если же язык высылаемого текста заранее неизвестен (например, мы получаем этот текст в процессе выполнения скрипта), то так просто нам не выкрутиться. Однако не все потеряно. Я написал пару функций для исправления глюков ControlSend (ControlSendRaw). Функции называются ControlSend_MixLang и ControlSendRaw_MixLang. Для ситуаций, когда нам не нужно высылать контролу управляющих клавиш, а нужно выслать только текст, подойдет ControlSendRaw_MixLang. А для высылки управляющих клавиш, можно использовать ControlSend_MixLang. Напомню, как подключать функции: сохраняем приведенные функции как отдельный скрипт, а затем в том скрипте, где вы намерены их использовать, подключаем их так (путь, разумеется, указываете свой):

#Include D:\Program_2\AutoHotkey\HScripts\ControlSend(Raw)_MixLang.ahk

Собственно функции:

;*****************************************************************************
; AutoHotkey Version:  1.0.44.03
; Автор:               Androgen Belkin
; Имя скрипта:         ControlSend(Raw)_MixLang.ahk (v.1.0)
;*****************************************************************************
; Функции, заменяющие некорректно работающие команды ControlSend и ControlSendRaw.
;*****************************************************************************

; Функция ControlSendRaw_MixLang (она попроще и подходит только для высылки текста):
ControlSendRaw_MixLang( Control="", Keys="", WinTitle="", WinText="", ExcludeTitle="", ExcludeText="" )
{
    Loop, parse, Keys ; обработать в цикле высылаемую строку
    {
        Transform, Current_Asc, Asc, % A_LoopField ; перевести символ в ASCII
        If ( Current_Asc >= 192 AND Current_Asc <= 255 ) ; если символ из русской раскладки, то...
        {
            SendMessage, 0x50,, 0x4190419,, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
            ; переключить раскладку на русский в целевом окне
            ControlSendRaw, % Control, % A_LoopField, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
            ; выслать текущий символ из обрабатываемой строки
            Continue ; продолжить цикл
        }
        ; если символ не из русской раскладки, то...
        SendMessage, 0x50,, 0x4090409,, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
        ; переключить раскладку на английский в целевом окне
        ControlSendRaw, % Control, % A_LoopField, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
        ; выслать текущий символ из обрабатываемой строки
    } ; конец цикла
} ; конец функции
; ============================================================================

; Функция ControlSend_MixLang (подходит для высылки и текста и управляющих символов)
ControlSend_MixLang( Control="", Keys="", WinTitle="", WinText="", ExcludeTitle="", ExcludeText="" )
{
    ; АНАЛИЗИРУЕМ И СОРТИРУЕМ ВЫСЫЛАЕМЫЙ ТЕКСТ
    ; Разбить строку на разноязычные части и сложить эти части в массив
    ArrayCount = 1 ; инициализировать счетчик массива
    Loop, parse, Keys ; обработать высылаемую строку
    {
        Current_Symbol := A_LoopField ; сохранить текущий символ в переменную
        Transform, Current_Asc, Asc, %Current_Symbol% ; перевести текущий символ в ASCII
        If ( Current_Asc >= 192 AND Current_Asc <= 255 ) ; если текущий символ из русской раскладки, то...
        {
            If Previous = EN ; если предыдущий символ из английской раскладки, то...
            {
                String_RU = ; очистить русскую строку
                ArrayCount += 1 ; увеличить счетчик массива
                Array%ArrayCount% := String_EN ; вписать в новый элемент массива АНГЛИЙСКУЮ строку
            }
            String_RU := String_RU . Current_Symbol ; добавить текущий символ в РУССКУЮ строку
            Array%ArrayCount% := String_RU ; вписать в текущий элемент массива РУССКУЮ строку
            Previous = RU ; выставить указатель, что предыдущий символ был "русским"
        }
        Else ; если текущий символ из английской раскладки
        {
            If Previous = RU ; если предыдущий символ из русской раскладки, то...
            {
                String_EN = ; очистить английскую строку
                ArrayCount += 1 ; увеличить счетчик массива
                Array%ArrayCount% := String_RU ; вписать в новый элемент массива РУССКУЮ строку
            }
            String_EN := String_EN . Current_Symbol ; добавить текущий символ в АНГЛИЙСКУЮ строку
            Array%ArrayCount% := String_EN ; вписать в текущий элемент массива АНГЛИЙСКУЮ строку
            Previous = EN
        } ; конец добавления текущего символа в массив
    } ; конец цикла

    ; ВЫСЫЛАЕМ ОТСОРТИРОВАННЫЙ ТЕКСТ
    Loop, %ArrayCount% ; читаем строки из массива
    {
        Array_String := Array%A_Index% ; вынимаем из массива строку
        Transform, Current_Asc, Asc, %Array_String% ; переводим первый символ строки в ASCII
        If ( Current_Asc >= 192 AND Current_Asc <= 255 ) ; если символ из русской раскладки, то...
            SendMessage, 0x50,, 0x4190419,, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
            ; переключить раскладку на русскую в целевом окне
        Else ; если символ из английской раскладки, то...
            SendMessage, 0x50,, 0x4090409,, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
            ; переключить раскладку на английскую в целевом окне
        ControlSend, % Control, % Array_String, % WinTitle, % WinText, % ExcludeTitle, % ExcludeText
        ; высылаем фрагмент в подготовленное окно
    }
} ; конец функции
; ============================================================================

А теперь - примеры использования этих функций:

F4::
SetKeyDelay, -1, 0 ; убираем задержку
String = Первая строка. Second String. Разный mixed text.{ENTER 2}
ControlSend_MixLang( "Edit1", String, "ahk_class Notepad" ) ; вызываем функцию
Return

или

F4::
SetKeyDelay, -1, 0 ; убираем задержку
String = %Clipboard% ; высылаемый текст будет текстом из буфера
ControlSend_MixLang( "Edit1", String, "Безымянный ahk_class Notepad" ) ; вызываем функцию
Return

или

F4::
SetKeyDelay, -1, 0 ; убираем задержку
String = Нажали F4! ; сначала высылаем этот текст
ControlSendRaw_MixLang( "Edit1", String, "ahk_class Notepad" ) ; вызываем функцию
String = {ENTER}==========={ENTER 2} ; теперь высылаем это (текст и управляющие символы)
ControlSend_MixLang( "Edit1", String, "ahk_class Notepad" ) ; вызываем функцию
Return

Обратите внимание: команда ControlSend(Raw) высылает текст медленнее, чем Send. Автор AutoHotkey сделал задержку для ControlSend умышленно, для увеличения надежности этой команды. Однако ни в таком виде, ни даже если задержку еще увеличить командой SetKeyDelay, все равно не получается 100% надежности (очень редко, но бывает, что неверно пропечатывается регистр букв). Я провел серию экспериментов с разными задержками, и обнаружил, что частота появления этого глюка не зависит от задержки (по крайней мере, на моем компе и с теми приложениями, куда я высылал тексты). Поэтому я предпочитаю задержку убирать вообще.

Наконец в некоторых случаях можно использовать вместо ControlSend(Raw) команду Send(Raw). Такой способ лишает нас удобств команды ControlSend, состоящих в том, что эта команда позволяет высылать тексты-клавиши контролам (управляющим элементам окна) без активизации окна, которому эти контролы принадлежат. Однако иногда окно можно безболезненно активизировать, установить фокус на нужный контрол и выслать ему текст Send'ом, работающим более надежно:

WinActivate, ahk_class Notepad ; активизируем окно Блокнота
ControlFocus, Edit1, ahk_class Notepad ; ставим фокус на нужный контрол
Send, by the way. И дополнение на русском. ; высылаем нужный текст

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

А зато теперь, команда – душевный отдых: ControlSetText

Эта команда прекрасно работает при любых условиях, для любой раскладки и для любых символов, и не требует заботы.

Она заменяет ВЕСЬ ТЕКСТ контрола на указанный вами. Использовать её можно не только для того, чтобы изменить, например, надпись на кнопке (полезного применения чего я не вижу), а и для того, чтобы заполнять какие-нибудь контролы-поля, или чтобы вставлять какие-нибудь пути к чему-нибудь, например, при автоматизации установки каких-либо программ. Я так "привязался" к этой команде, что, при написании скрипта, всегда ищу, в первую очередь, возможность использовать именно её :)

С проблемными для нашего человека командами AutoHotkey мы разобрались, теперь – факультатив.

Начну с того, что если вы используете какой-нибудь автоматический переключатель раскладок клавиатуры, например, PuntoSwitcher, то проявите осторожность. Хотя обычно проблем не бывает, но учесть не мешало бы. Вот, допустим, захотите вы командой Send выслать английские буквы ghbvth (мало ли зачем, это же я для примера), а PuntoSwitcher распознает их как слово "пример", и обязательно поправит, а это не то, что вам нужно, а скрипт продолжает работу… Это может закончиться нехорошо. Избежать этого можно, либо совсем отключив автокоррекцию раскладки, и корректировать её по горячей клавише, либо назначить в PuntoSwitcher'е горячие клавиши на отключение автокоррекции, и перед "сомнительными" командами нажимать их скриптом (отключив автокоррекцию), а потом опять нажимать (включив автокоррекцию). Например, так:

Send, ^!+= ; нажимаем Ctrl + Alt + Shift + =, для отключения автокоррекции PuntoSwitcher'а
Send, AutoHotkey, ghbvth ; наш странный текст
Send, ^!+= ; нажимаем Ctrl + Alt + Shift + =, для включения автокоррекции PuntoSwitcher'а

А можно отключать автокоррекцию высылкой сообщений, (мне больше нравится этот способ):

DetectHiddenWindows, On ; искать в скрытых окнах...
; отключение автокоррекции (если была включена)
SendMessage, 0x0111, 21000,,, Punto Switcher Main Window
Send, AutoHotkey, ghbvth ; наш странный текст
; включение автокоррекции (если была отключена)
SendMessage, 0x0111, 21000,,, Punto Switcher Main Window

Кстати, у PuntoSwitcher'а конвертация неправильно введенных символов жестко прошита на клавишу Break, а в силу особенностей моей клавы и её расположения, мне нажимать Break неудобно. Я написал скрипт, который переназначает конвертацию на двойное нажатие (как двойной клик) клавиши Ctrl:

~Control:: ; Control (ДВОЙНОЕ нажатие) - конвертировать введенные символы в punto switcher
if (A_PriorHotkey <> "~Control" or A_TimeSincePriorHotkey > 300)
; если предыдущая клавиша - не Control,
; или со времени нажатия Control прошло больше 300 миллисекунд, то...
{
    KeyWait, Control
    ;ожидать, пока клавиша не будет отпущена
    ;(чтобы исключить срабатывание от простого удержания нажатой клавиши)
    Return ; закончить обработку горячей клавиши после отжатия клавиши
}
; а вот если предыдущая клавиша - Control,
; и со времени нажатия Control прошло НЕ больше 300 миллисекунд, то...
KeyWait, Control
; ожидать пока клавиша не будет отпущена
; (чтобы исключить срабатывание от клавиши CTRL + исправляемые punto switcher'ом буквы)
Send, {Break} ; переключить раскладку
Return ; закончить обработку горячей клавиши

Теперь рассмотрим пару примеров, когда нам скриптом нужно изменить текущую раскладку окна. Вот так активное окно - в английскую раскладку:

SendMessage, 0x50,, 0x4090409,, A ; переключаем в английскую раскладку активное окно

Примечание: отличие команды SendMessage от PostMessage в том, что SendMessage ожидает ответа от того окна, которому высылается сообщение. Ожидание длится 5 секунд. За это время целевое окно обычно успевает обработать посланную команду и сообщить свой ответ. Содержание ответа (во многих случаях) не имеет значения. Важно то, что наш скрипт не продолжится, пока не получит этот ответ (ну, или пока не истекут 5 секунд). А PostMessage не ждет ничего. Поэтому там, где в результате высылки сообщений не возникают диалоговые окна, я рекомендую использовать SendMessage, а не PostMessage. Смена раскладки - как раз такой случай (если, конечно, вы не являетесь обладателем уникальной программы, выбрасывающей диалоговое окно с сообщением "Мне изменили раскладку. Продолжить?").

А в следующем примере - конкретное окно, а хоть бы и Блокнота (будто бы его кто-то использует), переключим в русскую раскладку. Ну, допустим, мы хотим скриптом же, вызвать меню Файл. Мы, конечно, можем Блокноту выслать Alt + Ф, но если он сейчас в английской раскладке, то высланное не словит. Сначала его нужно переключить в русскую раскладку. Поступим так (Блокнот, естественно, должен быть запущен):

WinActivate, ahk_class Notepad ; активируем окно Блокнота
SendMessage, 0x50,, 0x4190419,, ahk_class Notepad ; переключаем в русскую раскладку Блокнот
Send, !ф ; нажимаем Alt + Ф (вызвать меню Файл)

Пример выше – только для иллюстрации. Вызывать пункты всяческих меню "Файл", "Правка" и т.д. (на любом языке), лучше командой WinMenuSelectItem. И причина, по которой я об этом рассказываю здесь, такая: если у проги, в которой вы хотите вызвать пункты меню, есть многоязычный интерфейс, то чтобы быть уверенным, что переключившись в другой язык (не раскладку, а интерфейс программы), вы все равно сможете вызвать нужный вам пункт меню, нужно использовать не имена пунктов меню, а их номера.

WinMenuSelectItem, ahk_class Notepad,, Справка, О программе
; вызвать в Блокноте меню о программе, используя имена пунктов
WinMenuSelectItem, ahk_class Notepad,, 5&, 3&
; вызвать в Блокноте меню о программе, используя номера пунктов

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

Замечу, что команда WinMenuSelectItem работает не со всеми окнами, и тогда можно попробовать использовать вызов меню с помощью SendMessage (как это сделать, описано, например, здесь: http://www.script-coding.com/AutoHotkey/SendMessages.html). Или поступить так, как мы это делали для Блокнота четырьмя абзацами выше. А если и это не поможет, тогда, увы, - мышкой (скриптовой, конечно).

А что, если мы хотим, чтобы какое-либо окно автоматически переключалось в нужную раскладку? Например, у меня раскладка по умолчанию – русская, поэтому Total Commander запускается в русской раскладке. Меня это устраивает, но я часто пользуюсь быстрым поиском в ТС, и окошко быстрого поиска открывается тоже, разумеется, в русской раскладке, а вот это меня не устраивает (обычно я ищу по английским буквам). Можно, конечно, переключить раскладку и "вручную", но ведь есть AutoHotkey! Вот и попросим его. Создаем таймер, по которому будут выполняться всяческие автоматизации окон, и вписываем его где-нибудь в автовыполняющуюся секцию скрипта.

#Persistent ; скрипт будет запущен постоянно
;(если после автовыполняющейся секции у вас есть горячие клавиши или автозамены,
;то эта директива - лишняя)
SetTimer, Auto_Window, 200 ; переходить к указанной подпрограмме через каждые 0.2 секунды
Return ; закончить автовыполняющуюся часть

А теперь сама подпрограмма автоматизации окон.

Auto_Window:
;метка входа таймера автоматизации окон (эту подпрограмму можно размещать
;в любом месте скрипта, мне удобно размещать подпрограммы в конце, но это не обязательно)
 
; TOTAL COMMANDER: ПЕРЕКЛЮЧИТЬ РАСКЛАДКУ В БЫСТРОМ ПОИСКЕ
IfWinActive, ahk_class TQUICKSEARCH ; если активно окно Быстрого поиска в ТС, то...
{
    if Win_QS = ; если окно только что активизировалось, то...
    {
        SendMessage, 0x50,, 0x4090409,, ahk_class TQUICKSEARCH
        ; переключить раскладку на английскую в окне Быстрого поиска
        Win_QS = 1 ; выставить указатель, что окно уже активно
    }
}
Else ; если окно НЕ активно, то...
    Win_QS = ; выставить указатель, что окно НЕ активно
 
; TOTAL COMMANDER: ЗАКРЫТИЕ ОКНА "ДИСК НЕ НАЙДЕН"
IfWinExist, ahk_class TDRIVEDLG ; если существует окно "Диск не найден" в Тотале, то...
WinClose, ahk_class TDRIVEDLG ; закрыть окно "Диск не найден"
 
Return ; конец подпрограммы по таймеру

Как, надеюсь, понятно – скрипт проверяет, активизировалось окно Быстрого поиска только что, или оно уже тут давно (давнее, чем прошел предыдущий цикл по таймеру). Это нужно для того, что если я захочу поискать в этом окне на русском, то я переключу раскладку "руками" и скрипт мне не будет мешать. Само собой, что так можно поступать с любыми окнами (например, с тем же Photoshop'ом).

А вот еще на тему русского языка (не совсем про AutoHotkey, но может кому-то будет полезно). Иногда, при копировании в буфер из некоторых англоязычных (хоть, иногда, и русифицированных) программ, и последующей вставки куда-нибудь, вдруг оказывается, что вставляемый текст весь в вопросах или кракозябрах. Если у вас так бывает, то скопируйте текст ниже, вставьте его в блокнот, и сохраните с любым именем и расширением reg. Получится файл реестра, который нужно запустить-подтвердить, и перезагрузиться. Помогает решить проблему с кракозябрами в 99,8 % случаев.

REGEDIT4
; Файл реестра для исправления возможных проблем с отображением русских шрифтов в Windows 2k/XP/2k3
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"1250"="c_1251.nls"
"1251"="c_1251.nls"
"1252"="c_1251.nls"
"1253"="c_1251.nls"
"1254"="c_1251.nls"
"1255"="c_1251.nls"
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontMapper]
"ARIAL"=dword:000000cc
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes]
"Arial,0"="Arial,204"
"Comic Sans MS,0"="Comic Sans MS,204"
"Courier,0"="Courier New,204"
"Courier,204"="Courier New,204"
"MS Sans Serif,0"="MS Sans Serif,204"
"Tahoma,0"="Tahoma,204"
"Times New Roman,0"="Times New Roman,204"
"Verdana,0"="Verdana,204"

Обратите внимание, что если у вас 9x, Me или NT4, то вам нужен другой файл, вот он:

REGEDIT4
; Файл реестра для исправления возможных проблем с отображением русских шрифтов в Windows 9x/Me/NT4
; Может также потребоваться добавить в файл Win.ini следующие строки (не забудьте убрать точки с запятой):
;
; [FontSubstitutes]
; Arial,0=Arial,204
; Comic Sans MS,0=Comic Sans MS,204
; Courier,0=Courier New,204
; Microsoft Sans Serif,0=Microsoft Sans Serif,204
; Tahoma,0=Tahoma,204
; Times New Roman,0=Times New Roman,204
; Verdana,0=Verdana,204
 
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Nls\Codepage]
"1250"="cp_1251.nls"
"1251"="cp_1251.nls"
"1252"="cp_1251.nls"
"1253"="cp_1251.nls"
"1254"="cp_1251.nls"
"1255"="cp_1251.nls"

Ну и напоследок пара скриптиков для русско-английских пользователей (для нас то есть).

Сначала скрипт для облегчения переводческой работы (например, для тех, кто самоотверженно переводит справку AutoHotkey).

;*****************************************************************************
; AutoHotkey Version:  1.0.33.0
; Автор:               Androgen
; Имя скрипта:         Перевести в PromtX.ahk (v.1.1)
;*****************************************************************************
; Перевести в PromtX или в X-Translator PLATINUM
;*****************************************************************************
; Пользуемся так: выделяем что-то, что хотим перевести,
; нажимаем горячие клавиши вызова скрипта, и - получаем перевод.
; Горячие клавиши можно назначить на скрипт обычными средствами Windows,
; а можно - вставить содержимое этого скрипта
; в скрипт, запущенный у вас постоянно (если таковой имеется), и назначить их в нем.
; ПРИМЕЧАНИЕ: PromtX может автоматически переводить изменившийся буфер обмена,
; но мне вовсе не нужно, чтобы его окно
; выскакивало всякий раз, когда я что-нибудь скопирую в буфер.
; Кроме того, для этой его фишки нужно, чтобы он был уже запущен, а для этого скрипта - это не обязательно.
; И PromtX не чистит форматирование скопированного текста (см. комментарии ниже)
 
; ========== НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ ==========
PrmtX_Path = %A_ProgramFiles%\X-Translator PLATINUM\XTRAPL\PrmtXP.exe ; укажите здесь путь к PromtX
;~ PrmtX_Path = %A_ProgramFiles%\PRMT6\PRMTX\PrmtX.exe ; укажите здесь путь к PromtX
PrmtX_Window =  - X-Translator PLATINUM ; фрагмент имени окна PromtX
;~ PrmtX_Window =  - PromtX ; фрагмент имени окна PromtX
; ========== КОНЕЦ НАСТРОЕК ПОЛЬЗОВАТЕЛЯ ==========
 
IfNotExist, %PrmtX_Path% ; проверяем правильность пути к PromtX
{
    MsgBox, Неверно указан путь: "%PrmtX_Path%". ; показать сообщение
    ExitApp ; закончить скрипт
}
 
Translate_String = Чтобы прервать
;фрагмент текста строки состояния "Чтобы прервать процесс перевода, нажмите ESC."
SetTitleMatchMode, 2 ; сравнивать с любой частью заголовка окна
DetectHiddenWindows, On ; искать в скрытых окнах, чтобы "поднимать" свернутый в трей PromtX
Menu, Tray, Icon, %PrmtX_Path%, 1 ; установить иконку скрипта в трее как у PromtX
Clipboard = ; очищаем буфер
Loop ; скопировать выделенное в буфер (в цикле, если одного раза будет почему-то недостаточно)
{
    Send, ^{sc02E} ; нажать CTRL + С (копировать в буфер)
    ClipWait, 1 ; подождать появления содержимого в буфере максимум 1 секунды
    if ErrorLevel = 0 ; если ДОЖДАЛИСЬ содержимого в буфере, то...
        Break ; закончить цикл
    ; если содержимого в буфере не дождались, то продолжаем
    if A_Index = 3 ; если цикл уже выполнился 3 раза, то...
    {
        MsgBox, Не удается скопировать текст в буфер обмена. ; показать сообщение
        ExitApp ; закончить скрипт
    }
}
 
; Если текст скопирован из, например, справки или браузера, то он, вероятно,
; содержит форматирование, и тогда
; скопированный текст, и перевод, будут начинаться примерно так:
; ОбычныйТерминСписокопределенийАдресЦитатыФорматированный
; Избавляемся от форматирования следующей командой:
Clipboard = %Clipboard% ; преобразуем форматированный текст в гладкий
IfWinNotExist, %PrmtX_Window% ; если окно PromtX'а НЕ существует, то...
        Run, %PrmtX_Path% ; запустить PromtX
WinWait, %PrmtX_Window%,, 5 ; ожидать появления окна PromtX не более 5 секунд
if ErrorLevel <> 0 ; если так и не дождались окна, то...
{
    MsgBox, Не дождались окна %PrmtX_Window%
        ExitApp ; конец скрипта
}
WinActivate, %PrmtX_Window% ; активизировать окно
WinWaitActive, %PrmtX_Window% ; пождать активизации окна
Loop ; в цикле ожидается начало перевода в окне PromtX
{
        ControlSend,, {F11}, %PrmtX_Window% ; нажать "перевести содержимое буфера обмена"
        ; (используется ControlSend, а не Send,
        ; чтобы гарантировать нажатие клавиши именно для окна PromtX)
        StatusBarGetText, StatusBar_Text, 1, %PrmtX_Window%
        ; получить текст строки состояния (сама строка сост. может быть и скрытой)
        IfInString, StatusBar_Text , %Translate_String% ; если перевод начался, то...
            Break ; закончить цикл
}
ExitApp ; конец скрипта

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

Примечание: новую версию этого скрипта вы можете взять здесь: AutoHotkey: скрипт для переключения языка по умолчанию.

;*****************************************************************************
; AutoHotkey Version:  1.0.41.01
; Автор:               Androgen
; Имя скрипта:         Переключить язык по умолчанию.ahk (v.1.3)
;*****************************************************************************
; Проверить и, если нужно - переключить, язык ввода по умолчанию (тот, что при загрузке Windows).
;*****************************************************************************
 
; ========== НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ ==========
Name_Lang_Serv_Win = Языки и службы текстового ввода
; как у вас называется это окно (я встречал и другие названия)
; ========== КОНЕЦ НАСТРОЕК ПОЛЬЗОВАТЕЛЯ ==========
 
#NoTrayIcon ; не показывать иконку скрипта в трее
RegRead, Load_Lang, HKEY_CURRENT_USER, Keyboard Layout\Preload, 1
; прочитать, какая раскладка по умолчанию
if Load_Lang = 00000419 ; если русская, то...
{
        MsgBox, 1, Внимание., Текущий язык ввода по умолчанию - русский.`n`nИзменить на АНГЛИЙСКИЙ ?
        ; оформляем сообщение
    IfMsgBox, OK ; если "OK", то...
        Key_Action = {Up} ; эта клавиша будет высылаться контролу
        ; для смены раскладки на английскую (если нужно - поправьте)
    else ; если кнопка подтверждения не нажата, то...
        Exit ; завершить скрипт
}
if Load_Lang = 00000409 ; если английская, то...
{
        MsgBox, 1, Внимание., Текущий язык ввода по умолчанию - английский.`n`nИзменить на РУССКИЙ ?
        ; оформляем сообщение
    IfMsgBox, OK ; если "OK", то...
        Key_Action = {Down} ; эта клавиша будет высылаться контролу
        ; для смены раскладки на русскую (если нужно - поправьте)
    else ; если кнопка подтверждения не нажата, то...
        Exit ; завершить скрипт
}
if (Load_Lang <> 00000419 AND Load_Lang <> 00000409)
; если раскладки по умолчанию не русская и не английская, то...
{
        MsgBox, 0, Внимание!, %A_Space%Текущий язык НЕ АНГЛИЙСКИЙ и НЕ РУССКИЙ.`n`n
        , Скрипт рассчитан на работу с этими раскладками.`n`n
        , Измените настройки скрипта. ; оформляем сообщение
        Exit ; завершить скрипт
}
 
Run, RunDll32.exe shell32.dll`,Control_RunDLL input.dll
; запустить апплет "Языки и службы текстового ввода"
WinWait, %Name_Lang_Serv_Win%,, 5
; подождать окно "Языки и службы текстового ввода" не более 5 секунд
If ErrorLevel <> 0 ; если окна так и не дождались, то...
{
    MsgBox, Не дождались окна: "%Name_Lang_Serv_Win%"`n`n
    , Проверьте в скрипте "НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ" ; оформляем сообщение
        Exit ; завершить скрипт
}
; если окно появилось, то...
ControlSend, ComboBox1, %Key_Action%, %Name_Lang_Serv_Win% ; выбрать язык
Sleep, 100 ; пауза для надежности переключения раскладки
;~ pause ; для проверки переключения раскладки, раскомментируйте эту строку,
; а директиву #NoTrayIcon (в начале скрипта) - закомментируйте
metka0: ; метка для повторного клика, если понадобится
ControlClick, Button10 ; кликнуть "OK"
if ErrorLevel <> 0 ; если контрол не был готов (а такое случается), то...
    goto, metka0 ; повторить клик
Exit ; завершить скрипт

Здесь я вынужден с вами попрощаться. Я старался быть кратким, поэтому "за бортом" осталось множество нюансов. Однако основные особенности совместной работы AutoHotkey и русского языка мы рассмотрели. Надеюсь, что что-то из написанного окажется вам полезным. И надеюсь, что разработчики AutoHotkey и впредь будут учитывать, что их замечательным продуктом пользуются не только "однораскладочники". И тогда эта (изрядно сократившаяся) статья станет ненужной вовсе.

А вот еще на тему русского языка и AutoHotkey. Позвольте выразить признательность и благодарность тем, кто "не щадя живота" переводит для нас справку. Страна должна знать своих героев. Это semechka (к сожалению, не было повода упомянуть ее раньше, но вклад ее от этого не становится меньше), Дед Мазай (хоть и упоминавшийся, но явно недостаточно), Gourmet (благодаря которой проблем у многораскладочников - и не только русскоязычных - стало меньше вдвое) и The gray Cardinal (хоть и не замеченный в переводах статей, но собравший нас всех здесь под своим недремлющим и доброжелательным оком и квалифицированной рукой, и чей труд невозможно переоценить).

Переводчики всех стран, присоединяйтесь!

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.