Re: AHK: Break и Shift+Break как в пунто свитчере
Тем не менее, им многие до сих пор пользуются, например.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Тем не менее, им многие до сих пор пользуются, например.
Ну это клинические случаи, надо им бить по рукам, отсутствием поддержки в своих прожектах. Наставлять, как говорится, на путь истинный.
А вот RegExReplace() ничем не лучше, по-моему, перебора символов, вряд ли этот вариант лучше по производительности.
Хотя, выглядит всё же, вроде, логичнее, имеет смысл заменить.
Ну это клинические случаи, надо им бить по рукам, отсутствием поддержки в своих прожектах. Наставлять, как говорится, на путь истинный.
Ну всё же разработчики от ANSI-версии пока не отказались, так что рано "бить по рукам" . Другое дело, когда упорно продолжают использовать basic-версию.
Только не очень понятно наличие стольких точек в строках, зачем они?
Вопрос ещё актуален?
В общем-то да, почему не так:
ConvertRegistr(Text)
{
static Chars := "ёйцукенгшщзхъфывапролджэячсмитьбюqwertyuiopasdfghjklzxcvbnm"
. "ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮQWERTYUIOPASDFGHJKLZXCVBNM"
Loop, parse, Text
NewText .= (found := InStr(Chars, A_LoopField, 1))
? SubStr(Chars, found - 59, 1) : A_LoopField
Return NewText
}
Баг головного мозга, надо поправить.
А я подумал — для красоты.
К сожалению, нет
У меня тоже что-то с кодировкой стало. Скрипт сохранён как UTF-8 без BOM, но почему-то из анг. получаются кракозябры, а кирилица вообще не меняется.
ќР†ЎРС!
Даже не знаю после чего изменилось. Может после обновления Windows?
Скрипты должны сохраняться только с BOM в любом формате из ANSI, UTF-8, UTF-16.
У меня тоже что-то с кодировкой стало. Скрипт сохранён как UTF-8 без BOM, но почему-то из анг. получаются кракозябры, а кирилица вообще не меняется.
ќР†ЎРС!
Даже не знаю после чего изменилось. Может после обновления Windows?
Тоже самое. Слово "Windows" набранное русской раскладкой "Цштвщцы", скриптом переделывается в "??????".
Скрипт сохраняю в UTF-8 c галкой BOM. Windows 8.1 64bit.
У меня семёрка, с таким не сталкивался. Попробуйте это почитать. И ещё здесь вариант решения подобных проблем в прошлых версиях Windows правкой реестра (в последней трети страницы).
Только что проэкспериментировал, что при сохранении скрипта в UTF-8 без BOM действительно делает из латинских символов кракозябры, а с кириллицей ничего не делает. Советую сохранять скрипты в ANSI. Если в юникоде — то обязательно с BOM.
В выложенном скрипте меня не устраивало, что когда после написанного слова ставится пробел, и нажимается клавиша изменения раскладки, то изменения не происходили (это так задумано или нет?) К примеру, punto switcher изменяет текст в данном случае.
Сильно в коде не разбирался, но не понял зачем такой усложненной код в функции GetWord начиная со 130 строки (цикл While A_Index < 10). Поэтому начиная с этой строки и до конца фунции я заменил код на
else
{
Send ^+{left}
SendInput, ^{vk43}
ClipWait, 0
if !ErrorLevel
Return Clipboard
}
Теперь скрипт изменяет слово даже после поставленного после него пробела...
когда после написанного слова ставится пробел... то изменения не происходили (это так задумано или нет?)
Да, так и задумано, после пробела скрипт сработает, если только выделить предыдущий текст.
не понял зачем такой усложненной код
Скрипт многократно тестировался на разных сайтах и текстовых редакторах, где разная реакция на отправку клавиш. Если у вас лучше работает ваш вариант, то почему нет. А я в данном случае предпочитаю пользоваться правилом «работает — не трогай».
Да, так и задумано, после пробела скрипт сработает, если только выделить предыдущий текст
Все-таки это не совсем верный подход с точки зрения "юзер-френдли" интерфейса. Пользователь набрал слово, перевел его по хоткею в другую раскладку - работает. Снова набрал слово, отделил пробелом - жмет хоткей - а программа ему в ответ: "Извини, я понимаю, что именно ты хочешь сделать, но у тебя предыдущее слово - ПРОБЕЛ, извини, такие правила."
Пример с пешеходами. В Советском Союзе делали для них дорожки по утвержденному плану, и ставили грозные таблички "По газону не ходить!!!". В Германии сначала смотрели, где люди протоптали дорожки наиболее удобными маршрутами, а потом их асфальтировали. У вас налицо склонность к 1му варианту. ))
Дорожки так проложили в каком-то советском институте. А про Германию не очень верится. Там же орднунг. Айн-цвай-драй-полицай.
Может кто то сочтёт полезным переводить начало слов в верхний регистр:
ConvertTitle(delimiters = " ")
{
SelText := GetWord(TempClipboard)
SelText := RegExReplace(SelText, "(.)", Format("{:Ts}", SubStr(SelText, 1, 1)), , 1), pos := 1
While (pos := RegExMatch(SelText, "S)[\Q" delimiters "\E][a-zа-яё]", M, pos))
SelText := RegExReplace(SelText, ".", Format("{:Ts}", SubStr(M, 2, 1)), , 1, ++pos)
Clipboard := SelText
SendInput, ^{vk56} ; Ctrl + V
Sleep, 200
Clipboard := TempClipboard
}
Например в кодинге можно использовать свои разделители:
ConvertTitle(" {[._""`n")
ab_ab ab{ab.ab"ab[ab`nab
Заменит здесь все "a" на титульные.
Собственно изначальный вопрос и не задал:
delimiters := "`n {([,._"""
SelText = абв_абв абв{абв.абв"абв[абв`nабв,абв
SelText := RegExReplace(SelText, "(.)", Format("{:Ts}", SubStr(SelText, 1, 1)), , 1), pos := 1
While (pos := RegExMatch(SelText, "S)[\Q" delimiters "\E][a-zа-яё]", M, pos))
SelText := RegExReplace(SelText, ".", Format("{:Ts}", SubStr(M, 2, 1)), , 1, ++pos)
; или SelText := SubStr(SelText, 1, pos) Format("{:Ts}", SubStr(M, 2, 1)) SubStr(SelText, ++pos+1)
MsgBox % SelText
Можно ли упростить?
teadrinker
В последней версии строку из символов /// или {{{ не переводит, хотя например [[[ или /{[ переводит.
Фигурные скобки добавлю, а по поводу слешей — так они могут быть и в русской, и в английской раскладке, если текст состоит только из них — непонятно, куда переводить. Можно ориентироваться на текущую раскладку, конечно, но не стопроцентный вариант — вдруг юзер уже сам перевёл в другую.
Добавил недостающие символы. Если невозможно определить раскладку языка, исходя из анализа напечатанных символов, скрипт ориентируется на текущую раскладку окна.
Как исправить следующие ошибки:
1. :^ (шифт-6) не перекодируется.
2. (iban-6) перекодируется на (iban-(шифт-6)
3. http://ф перекодируется на реезЖ..ф - хотя я набрал только "ф" и, по логике, должно получиться http://a
И как сделать:
4. Мне нужна перекодировка СТРОГО на раскладку, противоположную текущей (например, если смесь тех и этих букв, я именно раскладкой укажу нужное направление).
5. Без учёта пробелов и переводов строк, а то перекодируется лишнее, а в текстовых полях на некоторых сайтах делается лишний перевод строки.
По-моему, если от набранного слова отошёл - нечего мудрить, перекодируешь его через выделение.
Спасибо, вообще очень классный и нужный скрипт. Я сам писал такой, но там не было смены регистра, и он не работает с AHK_L.
PS. Посмотрел и разобрался. Спасибо.
1. :^ (шифт-6) не перекодируется.
Почему-то забыл эти символы добавить в набор, отредактировал в Коллекции.
Кстати, велосипед ConvertRegistr() можно заменить на StringUpper/StringLower.
Наверное можно подсократить:
text := "пРИВЕТ"
msgbox % RegExReplace(text, "([А-ЯЁA-Z])|([а-яёa-z])", "$L1$U2")
Да, так работает, интересное решение.
teadrinker, упустил момент с разнорегистровым текстом.
А по-польски слабо список символов составить? :trollface
MsgBox % StringInvertCase("cZEŚĆ W jĘZYKU pOLSKIM")
StringInvertCase(str) {
Loop, Parse, str
{
StringUpper charUpper , A_LoopField
StringLower charLower , A_LoopField
charInvert := (charUpper == A_LoopField) ? charLower : charUpper
strInvert .= charInvert
}
Return strInvert
}
А по-польски слабо список символов составить?
Ну, это вряд ли пригодится. Хотя универсальность, конечно, приятна. Если бы ещё это как-то эффектно решить. Стал думать, можно ли как-то определить регистр символа? Ничего в голову не приходит.
Можно глянуть как устроена StringUpper в коде. Наверняка не списком перечисляют весь юникод :-).
Можно ещё Translit добавить, полезно например вставить в путь к файлу.
Translit() {
Static RU := "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
, ENG := ["A","B","V","G","D","E","Yo","Zh","Z","I","Y","K","L","M","N","O"
,"P","R","S","T","U","F","Kh","Ts","Ch","Sh","Sch","'","I","","E","Yu","Ya"]
If (SelText := GetWord(TempClipboard)) = ""
Return Clipboard := TempClipboard
Loop, Parse, SelText
If p := (RU ~= "Si)\Q" A_LoopField "\E")
Translit .= (A_LoopField ~= "S)[А-ЯЁ]") ? ENG[p] : Format("{:L}", ENG[p])
Else
Translit .= A_LoopField
Clipboard := Translit
SendInput, ^{vk56} ; Ctrl + V
Sleep, 200
Clipboard := TempClipboard
}
Было б не плохо обновить в теме http://forum.script-coding.com/viewtopic.php?id=7186 полностью код, со всеми изменениями. Мне лично не хватает конвертирование "Заглавные Буквы" и "Первая заглавная". Пока чайник, не выходит написать код самому, помогите плиз.
Не асилил читать всю тему, извините, если повторюсь.
Не работает последний вариант вашего скрипта у меня.. нажимаю перевод и получаю вместо слова привет из английской раскладки:
ghbdtn
вот это :
§РРЇћ‘
может кодировка поехала в скрипте ??
Убедитесь, что установлена актуальная версия AHK, и что скрипт сохранен в кодировке UTF-8 c BOM.
А по-польски слабо список символов составить? :trollface
Оказалось не слабо:
MsgBox % StringInvertCase("cZEŚĆ W jĘZYKU pOLSKIM", langID := 0x415)
StringInvertCase(str, langID) {
VarSetCapacity(buff, 256, 0), VarSetCapacity(key, 2)
layout := DllCall("LoadKeyboardLayout", "Str", "0000" . Format("{:04X}", langID), "UInt", 0)
Loop, Parse, str
{
res := DllCall("VkKeyScanEx", UShort, Ord(A_LoopField), UInt, layout, UShort)
vk := res & 0xFF, shift := res >> 8
NumPut(shift ? 0 : 128, buff, 16, "Char")
DllCall("ToUnicodeEx", UInt, vk, UInt, 0, Ptr, &buff, Str, key, Int, 2, UInt, 0, Ptr, layout)
invertedStr .= key
}
Return invertedStr
}
stealzy, а у вас польская раскладка установлена?
Ты про то, что сопоставление символов можно брать из установленных раскладок?
Ну да, я предполагаю. Сейчас код выше у меня работает, но символами из английской раскладки. Установил в языковой панели польскую — ничего не изменилось, наверное ещё языковой пакет нужен, но пока не устанавливал.
Обычный польский показывает латиницу, попробуй в нём азербайджан.
Например "E" латинская.
Нет, а что?
устроена StringUpper в коде. Наверняка не списком перечисляют
А может и списком перечисляют для восточноевропейских языков через таблицы трансляции. В любом случае я за стандартную библиотеку.
StringInvertCase(str, langID)
Раз у вас не юникод, то второй параметр наверно нужен, но логичнее тогда передавать encoding.
Используется стандартная функция CharLower/CharUpper.
стандартная функция
Я и не сомневался. Под ее капотом вполне вероятно таблицы трансляции.
P.S. 8 лет теме, 5 лет комменту с ConvertRegistr(Text), 3 года комменту с StringInvertCase.
Может лет через пять кому-то снова будет не слабо и мы увидим новый виток обсуждения преобразования регистра, если все это еще будет существовать.
Вроде мой код корректно работает, конкретно с польским что-то непонятное, но например с немецким, если установить немецкую раскладку, получается. öÄü —> ÖäÜ
Может лет через пять кому-то снова будет не слабо и мы увидим новый виток обсуждения преобразования регистра
Мне именно сейчас понадобилось реализовать универсальный вариант, и не только для преобразования регистра, но и раскладки, регистр был только для примера.
Раз у вас не юникод, то второй параметр наверно нужен, но логичнее тогда передавать encoding.
Можете пояснить эту мысль?
конкретно с польским что-то непонятное
Я установил польский и скачал пакет. Но если печатать на польском, то все символы один в один как инглиш. У тебя как?
teadrinker, не понял что значит преобразование раскладки?
Encoding - кодировка, как единственная нужная информация для однозначной идентификации текста.
serzh82saratov, а там вся фишка в диакритических знаках - сочетания с Alt.
В общем поляков в *опу со своими "фишками", ну и китаёз. Делаем для нормальных (адекватных) национальностей. А эти пускай с китайского на польский сами пишут, одним разом, чтобы потом ни в коем случае, темы не поднимать, а то блин всякие привыкли через 5 лет отвечать, позор то какой, ой-ой-ой.
Но если печатать на польском, то все символы один в один как инглиш. У тебя как?
Я на Win 7 пробовал, там если так выбрать
тогда все латинские, а если отметить чекбокс Дополнительно, ещё ветка разворачивается, и если там выбрать
тогда диакритические знаки появляются. Но при нажатии Shift + [клавиша с диакритическим знаком] вместо того же знака в верхнем регистре появляется другой знак.
Поставил немецкую — там всё нормально.
Encoding - кодировка, как единственная нужная информация для однозначной идентификации текста.
Путаете, это не тот случай. Кодировка нужна, когда символы задаются цифровым кодом, а в данном случае они однозначно задаются графически.
не понял что значит преобразование раскладки?
А весь топик-то о чём? Изначально задача была изменить раскладку текста, написанного в неправильной раскладке: ghbdtn —> привет.
Удалено.
А весь топик-то о чём?
Просто думал раз написали функцию StringInvertCase(str, langID) про регистр продолжаем, конкретно в ней без раскладок и языков проще обойтись.
Вроде мой код корректно работает, конкретно с польским что-то непонятное
Просто в твоём коде не учтены все модификаторы:
StringInvertCase("nNńŃ", langID := 0x415)
StringInvertCase(str, langID) {
VarSetCapacity(buff, 256, 0), VarSetCapacity(key, 2)
layout := DllCall("LoadKeyboardLayout", "Str", "0000" . Format("{:04X}", langID), "UInt", 0)
Loop, Parse, str
{
res := DllCall("VkKeyScanEx", UShort, Ord(A_LoopField), UInt, layout, UShort)
vk := res & 0xFF, shift := res >> 8
msgbox % shift
NumPut(shift ? 0 : 128, buff, 16, "Char")
DllCall("ToUnicodeEx", UInt, vk, UInt, 0, Ptr, &buff, Str, key, Int, 2, UInt, 0, Ptr, layout)
invertedStr .= key
}
Return invertedStr
}
1
Either SHIFT key is pressed.
2
Either CTRL key is pressed.
4
Either ALT key is pressed.
8
The Hankaku key is pressed
16
Reserved (defined by the keyboard layout driver).
32
Reserved (defined by the keyboard layout driver).
Ага, точно, правильно так:
shift := (res >> 8)&1
Но всё равно у меня с польской диакритикой не работает.
Еще надо ALT, Ctrl и Hankaku добавлять в NumPut.
Вроде вышло:
MsgBox, % StringInvertCase("nNńŃ", langID := 0x415)
StringInvertCase(str, langID) {
VarSetCapacity(buff, 256, 0), VarSetCapacity(key, 2)
layout := DllCall("LoadKeyboardLayout", "Str", "0000" . Format("{:04X}", langID), "UInt", 0)
Loop, Parse, str
{
res := DllCall("VkKeyScanEx", "UShort", Ord(A_LoopField), "UInt", layout, "UShort")
vk := res & 0xFF, modifiers := res >> 8
shift := modifiers & 1, ctrl := modifiers & 2, alt := modifiers & 4, hankaku := modifiers & 8
for k, v in {ctrl: 0x11, alt: 0x12, hankaku: 0xF3}
NumPut(%k% ? 128 : 0, buff, v, "Char")
NumPut(shift ? 0 : 128, buff, 0x10, "Char")
DllCall("ToUnicodeEx", "UInt", vk, "UInt", 0, "Ptr", &buff, "Str", key, "Int", 2, "UInt", 0, "Ptr", layout)
invertedStr .= key
}
Return invertedStr
}
Теперь ещё вопрос остался, как первые четыре цифры в названии раскладки определять, они не всегда "0000".
Через список из реестра?
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts
Есть 00000415 и 00010415. Как понять, какая нужна? Мне нужно как-то соотнести значения вида 0x04150415 и "00000415".
Можно, конечно, запускать LoadKeyboardLayout, перебирая "0000", "0001" ... до тех пор, пока не получим в результате существующую раскладку, но, кроме того, что это не элегантное решение, оно ещё и много времени занимает.
Как я понимаю, надо загружать дефолтную раскладку:
An application can and will typically load the default input locale identifier or IME for a language and can do so by specifying only a string version of the language identifier.
https://docs.microsoft.com/en-us/window … ardlayouta
Cписок дефолтных раскладок тут:
https://docs.microsoft.com/en-us/window … uage-packs
Нет, дефолтная не пойдет для задачи смены раскладки.
А как по-другому?
Например с польской 00000415 и 00010415 - это не названия раскладок, а их значения.
Названия же у 00000415 будет такое же, а у 00010415 - d0010415.
Названия, после установки, можно посмотреть здесь:
HKEY_CURRENT_USER\Keyboard Layout\Preload
Но с такой раскладкой данный код уже не работает
MsgBox, % StringInvertCase("nNńŃ", langID := 0x415)
StringInvertCase(str, langID) {
VarSetCapacity(buff, 256, 0), VarSetCapacity(key, 2)
msgbox % layout := DllCall("LoadKeyboardLayout", "Str", "d0010415", "UInt", 0)
Loop, Parse, str
{
msgbox % res := DllCall("VkKeyScanEx", "UShort", Ord(A_LoopField), "UInt", layout, "UShort")
vk := res & 0xFF, modifiers := res >> 8
shift := modifiers & 1, ctrl := modifiers & 2, alt := modifiers & 4, hankaku := modifiers & 8
for k, v in {ctrl: 0x11, alt: 0x12, hankaku: 0xF3}
NumPut(%k% ? 128 : 0, buff, v, "Char")
NumPut(shift ? 0 : 128, buff, 0x10, "Char")
DllCall("ToUnicodeEx", "UInt", vk, "UInt", 0, "Ptr", &buff, "Str", key, "Int", 2, "UInt", 0, "Ptr", layout)
invertedStr .= key
}
Return invertedStr
}
Например с польской 00000415 и 00010415 - это не названия раскладок, а их значения.
Не знаю насчёт понятия "значение", у раскладки есть layout name, которое можно получить функцией GetKeyboardLayoutName, это как раз значение вида "00000415", и есть locale id, которое выдаёт функция GetKeyboardLayout. С layout name по моему текущему опыту функция LoadKeyboardLayout всегда работает. Проблема только в том, что GetKeyboardLayoutName работает только со своей веткой, поэтому приходится сначала сменить раскладку своей ветки, другого способа получить layout name я пока не нашёл.
Да, действительно, проверил - с названиями раскладок я ошибся.
Но так не работает:
MsgBox, % StringInvertCase("nNńŃ", langID := 0x415)
StringInvertCase(str, langID) {
VarSetCapacity(buff, 256, 0), VarSetCapacity(key, 2)
msgbox % layout := DllCall("LoadKeyboardLayout", "Str", "00010415", "UInt", 0)
Loop, Parse, str
{
msgbox % res := DllCall("VkKeyScanEx", "UShort", Ord(A_LoopField), "UInt", layout, "UShort")
vk := res & 0xFF, modifiers := res >> 8
shift := modifiers & 1, ctrl := modifiers & 2, alt := modifiers & 4, hankaku := modifiers & 8
for k, v in {ctrl: 0x11, alt: 0x12, hankaku: 0xF3}
NumPut(%k% ? 128 : 0, buff, v, "Char")
NumPut(shift ? 0 : 128, buff, 0x10, "Char")
DllCall("ToUnicodeEx", "UInt", vk, "UInt", 0, "Ptr", &buff, "Str", key, "Int", 2, "UInt", 0, "Ptr", layout)
invertedStr .= key
}
Return invertedStr
}
А почему ты именно "00010415" подставляешь, а не "00000415"? Может, у тебя и нету первой. Раскладка должна быть установлена.
У меня все 2 польские раскладки установлены со всеми опциями.
А использую я ее для проверки того, что твоим способом нельзя переконвертировать при любой раскладке, а похоже только при дефолтной.
Сейчас не могу проверить, но русская у меня не дефолтная установлена.
С русской mnemonic, например с буквой ё тоже не сработает.
Тут всё расписано:
Further proof that VkKeyScanEx sucks
Ну, пока что всё равно нет другого способа переконвертировать символ из одной раскладки в другую.
А чем массивы не устраивают?
А как на все раскладки массивы сделаешь?
Ну если много свободного времени и желания, то можно сделать.
Только зачем на все?
Нужен универсальный вариант. Раскладки могут быть самодельные, так что на все не получится.
Ну тогда задача невыполнима.
Почему, выполнима на 90%.
Можно попробовать увеличить процент, подгружая dll раскладки и анализируя его алгоритм, по типу Microsoft Keyboard Layout Creator.
https://www.codeproject.com/Articles/43 … or-in-32-6
http://archives.miloush.net/michkap/arc … 81107.html
Спасибо, попробую разобраться.
Ну, пока что всё равно нет другого способа переконвертировать символ из одной раскладки в другую.
Это вроде работает (не для иероглифов), например из QWERTY в AZERTY.
Или тут есть что поправить, упростить?
string = Россия-2020:`nвыживайте как сможете
Global oSymbols := SymbolsListCreate()
MsgBox % str2 := Translate(string, oSymbols["RUS"], oSymbols["ENU"])
MsgBox % Translate(str2, oSymbols["ENU"], oSymbols["RUS"])
Return
Translate(string, inhkl, outhkl) {
Loop, Parse, string
{
If !sc := oSymbols[inhkl].chartocode[Ord(A_LoopField)]
newstring .= A_LoopField
Else
newstring .= oSymbols[outhkl].sctochar[sc]
}
Return newstring
}
SymbolsListCreate() {
Static MAPVK_VK_TO_VSC := 0
arr := {}
for hkl, LayoutName in GetKeyboardLayoutList()
{
arr[hkl] := {}, arr[hkl].sctochar := {}, arr[hkl].chartocode := {}, arr[LayoutName] := hkl
for min, max in {0x30:0x5A,0xBA:0xE2}
loop % max - min + 1
{
vk := min + A_Index - 1
If !sc := DllCall("MapVirtualKeyEx", "Uint", vk, "Uint", MAPVK_VK_TO_VSC, "Ptr", hkl, "Uint")
Continue
Char := GetKeyChar(vk, sc, hkl, 0), _Char := GetKeyChar(vk, sc, hkl, 1)
If (Char = "" && _Char = "")
Continue
arr[hkl].sctochar[sc] := Char, arr[hkl].sctochar[-sc] := _Char
arr[hkl].chartocode[Ord(Char)] := sc, arr[hkl].chartocode[Ord(_Char)] := -sc
}
}
Return arr
}
GetKeyChar(vk, sc, HKL, Shift = 0) {
Static state, _ := VarSetCapacity(state, 256, 0)
, char, __ := VarSetCapacity(char, 4, 0)
If Shift
NumPut(-128, state, 0x10 , "Char")
Else
NumPut(0, state, 0x10 , "Char")
n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
, "ptr", &state, "ptr", &char, "int", 1, "uint", 0, "ptr", HKL)
Return StrGet(&char, n, "utf-16")
}
GetKeyboardLayoutList() {
VarSetCapacity(List, A_PtrSize*5)
Size := DllCall("GetKeyboardLayoutList", Int, 5, Str, List)
Locales := []
Loop % Size
Locales[Locale := NumGet(List, A_PtrSize*(A_Index - 1)) & 0xFFFF] := GetLangName(Locale)
Return Locales
}
GetLangName(Locale, LCType := 3) {
Size := DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, UInt, 0, UInt, 0) * 2
VarSetCapacity(lpLCData, Size, 0)
DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, Str, lpLCData, UInt, Size)
Return lpLCData
}
Я сейчас не в теме уже немного, давно не занимался данным вопросом. Помню, что основные проблемы были, когда нужно было перевести в другую раскладку символы с диакритикой.
serzh82saratov
Это вроде работает (не для иероглифов), например из QWERTY в AZERTY.
Или тут есть что поправить, упростить?
Это новая и последняя версия конвертации en-ru-en, которая заменяет предыдущую?
Функцию Translate() нужно запускать по горячей клавише, когда неправильно введенный текст выделен?
Это новая и последняя версия конвертации en-ru-en, которая заменяет предыдущую?
Насколько помню, то да.
Функцию Translate() нужно запускать по горячей клавише, когда неправильно введенный текст выделен?
А в чём тут вопрос, когда по горячей клавише запускаете, что не так?
А в чём тут вопрос, когда по горячей клавише запускаете, что не так?
Эта программа заменяет функционал Punto Switcher. Punto Switcher работает так: выделить введенный текст в неправильной раскладке и нажать горячую клавишу. Поэтому оформлять программу нужно в таком же виде.
Ваша версия полностью отличается от предыдущей, которая оформлена правильно, с горячими клавишами и там понятно что и когда запускается. Поэтому я пытаюсь понять, как у вас выделенный текст передается в функцию Translate(). Там он передается через Clipboard.
выделить введенный текст в неправильной раскладке и нажать горячую клавишу
Не знаю о чём вы, код так и используется.
Функцию Translate() нужно запускать по горячей клавише, когда неправильно введенный текст выделен?
А, вы же про код из#179, а я про коллекцию думал. Тот не помню зачем писал, тест какой то был.
stuermer
Тут вопрос про GetKeySC возник, и я вспомнил, в #179 вроде моё решение про то чтобы работало со всеми раскладками а не только англ <> рус которые забиты в скрипте в коллекции. Но этот код я не добавлял в скрипт.
serzh82saratov
Тогда добавьте, если не трудно, тогда будет универсальная версия в коллекции скриптов. У меня как раз не англ <> рус. Он переключает между любыми двумя установленными в системе раскладками?
Тот скрипт не мой, не мне и добавлять. Универсальная версия конечно хорошо, но строчку с символами для своего языка можете сами добавить. Только там ещё может возникнуть вопрос как определить в какой раскладке текст, а это уже другой вопрос, его тоже надо решить для уни версии.
я вспомнил, в #179 вроде моё решение про то чтобы работало со всеми раскладками
Я так понял, что #179 ваш, а тот, что в коллекции не ваш.
#179 удобнее, т.к. нужно только подставить раскладки из системы, а не отдельные символы. Можно было бы просто заменить ConvertText() на вашу Translate(), но у вас запуск Translate() идет с 2 параметрами исходной и конечной раскладки, а ConvertText() из коллекции использует 1 параметр для противоположной раскладки "OppositeLayout". Это соответствует функционалу PuntoSwitcher по горячей клавише.
Это соответствует функционалу PuntoSwitcher по горячей клавише.
А если три языка, как PuntoSwitcher считает на какой изменить?
Там есть опция, между какими языками переключаться. Если нет в системе EN, то можно назначить вместо EN - DE, т.е. другую латиницу. Но функционал с 3 языками это необязательно.
Упрощенный вариант фунции GetWord() из коллекции и её вызова :
SwitchKeysLocale()
{
SelText := GetWord()
Clipboard := ConvertText(SelText, Layout)
SendInput, ^{vk56} ; Ctrl + V
Sleep, 50
SwitchLocale(Layout)
}
SwitchReg()
{
SelText := GetWord()
Clipboard := ConvertReg(SelText)
SendInput, ^{vk56} ; Ctrl + V
}
GetWord()
{
SetKeyDelay, 0
SendInput, ^{vk43}
Sleep, 100
if (Clipboard != "")
Return Clipboard
SendInput, +{Right}
}
Если нет в системе EN, то можно назначить вместо EN - DE, т.е. другую латиницу
Значит в ней все списки символов с соответствием скан кодов забита, например Q английская и Q французкая это разные клавиши, хотя код символа одинаковый.
Снова приходим к тому что нужны списки, если как в PuntoSwitcher надо. А значит мой код нужно использовать для получения списка языка, а скрипт переделывать под скан коды, это уже не просто вставить мои функции в код.
Упрощенный вариант фунции GetWord() из коллекции и её вызова :
Чем лучше, просто короче код?
Примерно так без ConvertRegistr.
Global oSymbols := {}
SymbolsListCreate("ENU", "RUS")
Return
^PGDN::SwitchKeysLocale() ; Ctrl + Page Down
+PGDN::SwitchRegistr() ; Shift + Page Down
SwitchKeysLocale()
{
SelText := GetWord(TempClipboard)
Clipboard := ConvertText(SelText, Layout)
SendInput, ^{vk56} ; Ctrl + V
Sleep, 50
SwitchLocale(Layout)
Sleep, 50
Clipboard := TempClipboard
}
SwitchRegistr()
{
SelText := GetWord(TempClipboard)
Clipboard := ConvertRegistr(SelText)
SendInput, ^{vk56} ; Ctrl + V
Sleep, 200
Clipboard := TempClipboard
}
GetWord(ByRef TempClipboard)
{
SetBatchLines, -1
SetKeyDelay, 0
TempClipboard := ClipboardAll
Clipboard =
SendInput, ^{vk43}
Sleep, 100
if (Clipboard != "")
Return Clipboard
While A_Index < 10
{
SendInput, ^+{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if RegExMatch(Clipboard, "P)([ \t])", Found) && A_Index != 1
{
SendInput, ^+{Right}
Return SubStr(Clipboard, FoundPos1 + 1)
}
PrevClipboard := Clipboard
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
{
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
Return Clipboard
Else
{
SendInput, +{Right 2}
Return PrevClipboard
}
}
SendInput, +{Right}
s := SubStr(Clipboard, 1, 1)
if s in %A_Space%,%A_Tab%,`n,`r
{
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
Return Clipboard
}
Clipboard =
}
}
ConvertText(Text, ByRef OppositeLayout)
{
RegExReplace(Text, "i)[A-Z@#\$\^&\[\]'`\{}]", "", LatCount)
RegExReplace(Text, "i)[А-ЯЁ№]", "", CyrCount)
if (LatCount != CyrCount) {
CurrentLayout := LatCount > CyrCount ? oSymbols.Langs[1] : oSymbols.Langs[2]
OppositeLayout := LatCount > CyrCount ? oSymbols.Langs[2] : oSymbols.Langs[1]
}
else
{
threadId := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
landId := DllCall("GetKeyboardLayout", Ptr, threadId, Ptr) & 0xFFFF
if (oSymbols.Langs[1] = landId)
CurrentLayout := oSymbols.Langs[2], OppositeLayout := oSymbols.Langs[1]
else
CurrentLayout := oSymbols.Langs[1], OppositeLayout := oSymbols.Langs[2]
}
Return Translate(Text, CurrentLayout, OppositeLayout)
}
SwitchLocale(Layout)
{
ControlGetFocus, CtrlFocus, A
PostMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, Layout, %CtrlFocus%, A
}
ConvertRegistr(string)
{
}
Translate(string, inhkl, outhkl) {
Loop, Parse, string
{
If !sc := oSymbols[inhkl].chartocode[Ord(A_LoopField)]
newstring .= A_LoopField
Else
newstring .= oSymbols[outhkl].sctochar[sc]
}
Return newstring
}
SymbolsListCreate(L1, L2) {
Static MAPVK_VK_TO_VSC := 0
oSymbols := {}
oSymbols.Langs := []
for hkl, LayoutName in GetKeyboardLayoutList()
{
If (LayoutName != L1 && LayoutName != L2)
Continue
oSymbols.Langs[2 - (LayoutName = L1)] := hkl
oSymbols[hkl] := {}, oSymbols[hkl].sctochar := {}, oSymbols[hkl].chartocode := {}, oSymbols[LayoutName] := hkl
for min, max in {0x30:0x5A,0xBA:0xE2}
loop % max - min + 1
{
vk := min + A_Index - 1
If !sc := DllCall("MapVirtualKeyEx", "Uint", vk, "Uint", MAPVK_VK_TO_VSC, "Ptr", hkl, "Uint")
Continue
Char := GetKeyChar(vk, sc, hkl, 0), _Char := GetKeyChar(vk, sc, hkl, 1)
If (Char = "" && _Char = "")
Continue
oSymbols[hkl].sctochar[sc] := Char, oSymbols[hkl].sctochar[-sc] := _Char
oSymbols[hkl].chartocode[Ord(Char)] := sc, oSymbols[hkl].chartocode[Ord(_Char)] := -sc
}
}
}
GetKeyChar(vk, sc, HKL, Shift = 0) {
Static state, _ := VarSetCapacity(state, 256, 0)
, char, __ := VarSetCapacity(char, 4, 0)
If Shift
NumPut(-128, state, 0x10 , "Char")
Else
NumPut(0, state, 0x10 , "Char")
n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
, "ptr", &state, "ptr", &char, "int", 1, "uint", 0, "ptr", HKL)
Return StrGet(&char, n, "utf-16")
}
GetKeyboardLayoutList() {
VarSetCapacity(List, A_PtrSize*5)
Size := DllCall("GetKeyboardLayoutList", Int, 5, Str, List)
Locales := []
Loop % Size
Locales[Locale := NumGet(List, A_PtrSize*(A_Index - 1)) & 0xFFFF] := GetLangName(Locale)
Return Locales
}
GetLangName(Locale, LCType := 3) {
Size := DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, UInt, 0, UInt, 0) * 2
VarSetCapacity(lpLCData, Size, 0)
DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, Str, lpLCData, UInt, Size)
Return lpLCData
}
Тут надо RegEx под свой язык переделать.
ConvertText(Text, ByRef OppositeLayout)
{
RegExReplace(Text, "i)[A-Z@#\$\^&\[\]'`\{}]", "", LatCount)
RegExReplace(Text, "i)[А-ЯЁ№]", "", CyrCount)
Тут языки указать.
SymbolsListCreate("ENU", "RUS")
Чем лучше, просто короче код?
Убрал лишнее из GetWord() - восстановление старого буфера и проверки.
Тут надо RegEx под свой язык переделать.
Кто-то может под немецкий переделать? Я в Perl не силен.
Буквы хжэ -> üöä соответственно.
Убрал лишнее из GetWord() - восстановление старого буфера и проверки
Это на любителя.
Добавил ConvertRegistr, но с ним теперь такая штука, он был предназначен для исправления с неправильным CapsLock, а теперь как с неправильным Shift, например "5" теперь меняется на "%".
#SingleInstance Force
#Persistent
#NoEnv
Global oSymbols := {}
SymbolsListCreate("ENU", "RUS")
Return
^PGDN::SwitchKeysLocale() ; Ctrl + Page Down
+PGDN::SwitchRegistr() ; Shift + Page Down
SwitchKeysLocale()
{
SelText := GetWord(TempClipboard)
Clipboard := ConvertText(SelText, Layout)
SendInput, ^{vk56} ; Ctrl + V
Sleep, 50
SwitchLocale(Layout)
Sleep, 50
Clipboard := TempClipboard
}
SwitchRegistr()
{
SelText := GetWord(TempClipboard)
Clipboard := ConvertRegistr(SelText)
SendInput, ^{vk56} ; Ctrl + V
Sleep, 200
Clipboard := TempClipboard
}
GetWord(ByRef TempClipboard)
{
SetBatchLines, -1
SetKeyDelay, 0
TempClipboard := ClipboardAll
Clipboard =
SendInput, ^{vk43}
Sleep, 100
if (Clipboard != "")
Return Clipboard
While A_Index < 10
{
SendInput, ^+{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if RegExMatch(Clipboard, "P)([ \t])", Found) && A_Index != 1
{
SendInput, ^+{Right}
Return SubStr(Clipboard, FoundPos1 + 1)
}
PrevClipboard := Clipboard
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
{
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
Return Clipboard
Else
{
SendInput, +{Right 2}
Return PrevClipboard
}
}
SendInput, +{Right}
s := SubStr(Clipboard, 1, 1)
if s in %A_Space%,%A_Tab%,`n,`r
{
Clipboard =
SendInput, +{Left}^{vk43}
ClipWait, 1
if ErrorLevel
Return
Return Clipboard
}
Clipboard =
}
}
ConvertText(Text, ByRef OppositeLayout)
{
RegExReplace(Text, "i)[A-Z@#\$\^&\[\]'`\{}]", "", LatCount)
RegExReplace(Text, "i)[А-ЯЁ№]", "", CyrCount)
if (LatCount != CyrCount) {
CurrentLayout := LatCount > CyrCount ? oSymbols.Langs[1] : oSymbols.Langs[2]
OppositeLayout := LatCount > CyrCount ? oSymbols.Langs[2] : oSymbols.Langs[1]
}
else
{
threadId := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
landId := DllCall("GetKeyboardLayout", Ptr, threadId, Ptr) & 0xFFFF
if (oSymbols.Langs[1] = landId)
CurrentLayout := oSymbols.Langs[2], OppositeLayout := oSymbols.Langs[1]
else
CurrentLayout := oSymbols.Langs[1], OppositeLayout := oSymbols.Langs[2]
}
Return Translate(Text, CurrentLayout, OppositeLayout)
}
SwitchLocale(Layout)
{
ControlGetFocus, CtrlFocus, A
PostMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, Layout, %CtrlFocus%, A
}
ConvertRegistr(string) {
Loop, Parse, string
{
r := oSymbols.Registr[Ord(A_LoopField)]
newstring .= (r = "") ? A_LoopField : r
}
Return newstring
}
Translate(string, inhkl, outhkl) {
Loop, Parse, string
{
If !sc := oSymbols[inhkl].chartocode[Ord(A_LoopField)]
newstring .= A_LoopField
Else
newstring .= oSymbols[outhkl].sctochar[sc]
}
Return newstring
}
SymbolsListCreate(L1, L2) {
Static MAPVK_VK_TO_VSC := 0
oSymbols := {}
oSymbols.Langs := []
oSymbols.Registr := {}
for hkl, LayoutName in GetKeyboardLayoutList()
{
If (LayoutName != L1 && LayoutName != L2)
Continue
oSymbols.Langs[2 - (LayoutName = L1)] := hkl
oSymbols[hkl] := {}, oSymbols[hkl].sctochar := {}, oSymbols[hkl].chartocode := {}, oSymbols[LayoutName] := hkl
for min, max in {0x30:0x5A,0xBA:0xE2}
loop % max - min + 1
{
vk := min + A_Index - 1
If !sc := DllCall("MapVirtualKeyEx", "Uint", vk, "Uint", MAPVK_VK_TO_VSC, "Ptr", hkl, "Uint")
Continue
Char := GetKeyChar(vk, sc, hkl, 0), _Char := GetKeyChar(vk, sc, hkl, 1)
If (Char != "")
{
oSymbols[hkl].sctochar[sc] := Char
oSymbols[hkl].chartocode[Ord(Char)] := sc
If (_Char != "")
oSymbols.Registr[Ord(Char)] := _Char
}
If (_Char != "")
{
oSymbols[hkl].sctochar[-sc] := _Char
oSymbols[hkl].chartocode[Ord(_Char)] := -sc
If (Char != "")
oSymbols.Registr[Ord(_Char)] := Char
}
}
}
}
GetKeyChar(vk, sc, HKL, Shift = 0) {
Static state, _ := VarSetCapacity(state, 256, 0)
, char, __ := VarSetCapacity(char, 4, 0)
If Shift
NumPut(-128, state, 0x10 , "Char")
Else
NumPut(0, state, 0x10 , "Char")
n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
, "ptr", &state, "ptr", &char, "int", 1, "uint", 0, "ptr", HKL)
Return StrGet(&char, n, "utf-16")
}
GetKeyboardLayoutList() {
VarSetCapacity(List, A_PtrSize*5)
Size := DllCall("GetKeyboardLayoutList", Int, 5, Str, List)
Locales := []
Loop % Size
Locales[Locale := NumGet(List, A_PtrSize*(A_Index - 1)) & 0xFFFF] := GetLangName(Locale)
Return Locales
}
GetLangName(Locale, LCType := 3) {
Size := DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, UInt, 0, UInt, 0) * 2
VarSetCapacity(lpLCData, Size, 0)
DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, Str, lpLCData, UInt, Size)
Return lpLCData
}
Кто-то может под немецкий переделать? Я в Perl не силен.
Буквы хжэ -> üöä соответственно.
RegExMatch(Char, "(*UCP)[^\W\d_]")
И этот ответ, породил решение этого
Добавил ConvertRegistr, но с ним теперь такая штука, он был предназначен для исправления с неправильным CapsLock, а теперь как с неправильным Shift
И самое интересное, теперь этот ответ не нужен, то есть RegEx, работать должно без него, само собой.
SymbolsListCreate без параметров выводит все установленные раскладки в буфер обмена.
Нужные раскладки можно менять не перезапуская скрипт, запустив SymbolsListCreate с нужными.
/*
Смена раскладки написанного текста
Модификация этого скрипта https://forum.script-coding.com/viewtopic.php?pid=102343#p102343
v1.2
С генерацией раскладок
http://forum.script-coding.com/viewtopic.php?pid=157311#p157311
*/
#SingleInstance Force
#Persistent
ListLines Off
SetBatchLines -1
#NoEnv
Global oSymbols := {}
; SymbolsListCreate() ; Все раскладки в буфер обмена
SymbolsListCreate("ENU", "RUS")
Return
^PGDN::SwitchKeysLocale() ; Ctrl + Page Down
+PGDN::SwitchRegistr() ; Shift + Page Down
; Esc:: ExitApp
SwitchKeysLocale()
{
SelText := GetWord(TempClipboard)
If SelText =
Return Clipboard := TempClipboard
Clipboard := ConvertText(SelText, Layout)
SendInput {LCtrl Down}{vk56}{LCtrl Up} ; "V"
Sleep, 50
SwitchLocale(Layout)
Sleep, 50
Clipboard := TempClipboard
}
SwitchRegistr()
{
SelText := GetWord(TempClipboard)
If SelText =
Return Clipboard := TempClipboard
Clipboard := ConvertRegistr(SelText)
SendInput {LCtrl Down}{vk56}{LCtrl Up} ; "V"
Sleep, 200
Clipboard := TempClipboard
}
GetWord(ByRef TempClipboard)
{
SetBatchLines, -1
SetKeyDelay, 0
TempClipboard := ClipboardAll
Clipboard =
SendInput {LCtrl Down}{vk43}{LCtrl Up} ; "C"
Sleep, 100
if (Clipboard != "")
Return Clipboard
While A_Index < 20
{
SendInput, {LCtrl Down}{LShift Down}{Left}{LCtrl Up}{LShift Up}{LCtrl Down}{vk43}{LCtrl Up} ; "C"
ClipWait, 1
if ErrorLevel
Return
if RegExMatch(Clipboard, "P)([ \t])", Found) && A_Index != 1
{
SendInput {LCtrl Down}{LShift Down}{Right}{LCtrl Up}{LShift Up}
Return SubStr(Clipboard, FoundPos1 + 1)
}
PrevClipboard := Clipboard
Clipboard =
SendInput, {LShift Down}{Left}{LShift Up}{LCtrl Down}{vk43}{LCtrl Up} ; "C"
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
{
Clipboard =
SendInput, {LShift Down}{Left}{LShift Up}{LCtrl Down}{vk43}{LCtrl Up} ; "C"
ClipWait, 1
if ErrorLevel
Return
if (StrLen(Clipboard) = StrLen(PrevClipboard))
Return Clipboard
Else
{
SendInput {LShift Down}{Right 2}{LShift Up}
Return PrevClipboard
}
}
SendInput {LShift Down}{Right}{LShift Up}
s := SubStr(Clipboard, 1, 1)
if s in %A_Space%,%A_Tab%,`n,`r
{
Clipboard =
SendInput, {LShift Down}{Left}{LShift Up}{LCtrl Down}{vk43}{LCtrl Up} ; "C"
ClipWait, 1
if ErrorLevel
Return
Return Clipboard
}
Clipboard =
}
}
ConvertText(string, ByRef OppositeLayout)
{
L1 := L2 := 0
Loop, Parse, string
{
_ord := Ord(A_LoopField)
If oSymbols[oSymbols.Langs[1]].charischar[_ord]
++L1
Else If oSymbols[oSymbols.Langs[2]].charischar[_ord]
++L2
}
if (L1 != L2) {
CurrentLayout := L1 > L2 ? oSymbols.Langs[1] : oSymbols.Langs[2]
OppositeLayout := L1 > L2 ? oSymbols.Langs[2] : oSymbols.Langs[1]
}
else
{
threadId := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
landId := DllCall("GetKeyboardLayout", Ptr, threadId, Ptr) & 0xFFFF
if (oSymbols.Langs[1] = landId)
CurrentLayout := oSymbols.Langs[1], OppositeLayout := oSymbols.Langs[2]
else
CurrentLayout := oSymbols.Langs[2], OppositeLayout := oSymbols.Langs[1]
}
Return ConvertLayout(string, CurrentLayout, OppositeLayout)
}
SwitchLocale(Layout)
{
ControlGetFocus, CtrlFocus, A
PostMessage, 0x50,, Layout, %CtrlFocus%, A ; WM_INPUTLANGCHANGEREQUEST
}
ConvertRegistr(string) {
Loop, Parse, string
{
r := oSymbols.Registr[Ord(A_LoopField)]
newstring .= (r = "") ? A_LoopField : r
}
Return newstring
}
ConvertLayout(string, inhkl, outhkl) {
Loop, Parse, string
{
If !sc := oSymbols[inhkl].chartocode[Ord(A_LoopField)]
newstring .= A_LoopField
Else
newstring .= oSymbols[outhkl].sctochar[sc]
}
Return newstring
}
SymbolsListCreate(L1 = "", L2 = "") {
; ENU = 1033, RUS = 1049, DEU = 1031
Static MAPVK_VK_TO_VSC := 0
If (L1 = "")
{
for hkl, LayoutName in GetKeyboardLayoutList()
LangsStr .= LayoutName "`t" hkl "`n"
MsgBox % Clipboard := LangsStr
Return
}
oSymbols := {}
oSymbols.Langs := []
oSymbols.Registr := {}
for hkl, LayoutName in GetKeyboardLayoutList()
{
If (LayoutName != L1 && LayoutName != L2)
Continue
oSymbols.Langs[2 - (LayoutName = L1)] := hkl
oSymbols[hkl] := {}, oSymbols[hkl].sctochar := {}
oSymbols[hkl].chartocode := {}, oSymbols[LayoutName] := hkl
oSymbols[hkl].charischar := {}
for min, max in {0x30:0x5A,0xBA:0xE2}
{
loop % max - min + 1
{
vk := min + A_Index - 1
If !sc := DllCall("MapVirtualKeyEx", "Uint", vk, "Uint", MAPVK_VK_TO_VSC, "Ptr", hkl, "Uint")
Continue
Char := GetKeyChar(vk, sc, hkl, 0), _Char := GetKeyChar(vk, sc, hkl, 1)
If (Char != "")
{
_ord := Ord(Char)
oSymbols[hkl].sctochar[sc] := Char
oSymbols[hkl].chartocode[_ord] := sc
If (RegExMatch(Char, "(*UCP)[^\W\d_]"))
{
oSymbols[hkl].charischar[_ord] := 1
If (_Char != "")
oSymbols.Registr[_ord] := _Char
}
}
If (_Char != "")
{
_ord := Ord(_Char)
oSymbols[hkl].sctochar[-sc] := _Char
oSymbols[hkl].chartocode[_ord] := -sc
If (RegExMatch(_Char, "(*UCP)[^\W\d_]"))
{
oSymbols[hkl].charischar[_ord] := 1
If (Char != "")
oSymbols.Registr[_ord] := Char
}
}
}
}
}
If oSymbols.Langs.Count() != 2
Throw Exception("Не найдена указанная раскладка!")
}
GetKeyChar(vk, sc, HKL, Shift = 0) {
Static state, _ := VarSetCapacity(state, 256, 0)
, char, __ := VarSetCapacity(char, 4, 0)
If Shift
NumPut(-128, state, 0x10 , "Char")
Else
NumPut(0, state, 0x10 , "Char")
n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
, "ptr", &state, "ptr", &char, "int", 1, "uint", 0, "ptr", HKL)
Return StrGet(&char, n, "utf-16")
}
GetKeyboardLayoutList() {
VarSetCapacity(List, A_PtrSize*5)
Size := DllCall("GetKeyboardLayoutList", Int, 5, Str, List)
Locales := []
Loop % Size
Locales[Locale := NumGet(List, A_PtrSize*(A_Index - 1)) & 0xFFFF] := GetLangName(Locale)
Return Locales
}
GetLangName(Locale, LCType := 3) {
Size := DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, UInt, 0, UInt, 0) * 2
VarSetCapacity(lpLCData, Size, 0)
DllCall("GetLocaleInfo", UInt, Locale, UInt, LCType, Str, lpLCData, UInt, Size)
Return lpLCData
}
RegEx, работать должно без него, само собой.
SymbolsListCreate без параметров выводит все установленные раскладки в буфер обмена.
Нужные раскладки можно менять не перезапуская скрипт, запустив SymbolsListCreate с нужными.
На это я и расчитывал вначале, иначе нет преимущества по сравнению со старой версией в коллекции, если нужно раскладки вручную переделывать.
Работает, спасибо!
На это я и расчитывал вначале
Да, тогда мне интересно было, потом забылось, а тут слово за слово и допилилось.
Но посмотрим, может рано радоваться, не тестировалось же толком.
Кстати если кто языки будет менять, напишите на каких нормально работает.