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
Спасибо, попробую разобраться.
Чтобы отправить ответ, вы должны войти или зарегистрироваться