1 (изменено: Krot66, 2013-10-06 22:06:07)

Тема: AHK: Еще один заменитель Punto Switcher'a

Основан на скрипте cargo отсюда: http://www.autohotkey.com/board/topic/2 … -switcher/ .
Принципиальное отличие - обработка текста осуществляется с помощью команды Input, а не выделения по горячим клавишам. Благодаря этому отпадают проблемы с символами, интерпретируемыми как разделители слов и становится возможно быстрое изменения раскладки текста, набранного посередине предложения или даже слова.
Поскольку ничего кроме Backspace не требуется, гораздо более совместим с программами, не являющихся редакторами.
Работает с Far.
Добавлен настраиваемый дневник.
Добавлена транслитерация буфера и выделенного текста.

#NoEnv 
SetWorkingDir %A_ScriptDir%
SendMode Input 
#SingleInstance, force
#MaxHotkeysPerInterval 500
SetKeyDelay 50, 50
Menu, Tray, Icon, shell32.dll, 134

;----------------------------------------------------------
; Pause - конвертация последнего слова или выделенного текста
; RCtrl+T - транслитерация выделенного текста
; RCtrl+B - транслитерация буфера обмена 
;----------------------------------------------------------
log:=1 ; - вести дневник
logfile:="Logs\Keys\" A_MM "." A_YYYY ".txt" ; - файл дневника
block:="Far 3,SciTE,AlReader,GoldenDict,PotPlayer,MPC-BE" ; - фрагменты заголовков окон программ-исключений дневника
cliplog:=1 ; - сохранять текстовый буфер обмена
cliplength:=1000 ; - обрезать до ... символов
ignor:="</h,</p>" ; - комбинации символов, при наличии которых буфер игнорируется
fkey:="Tab,Backspace,Enter,NumpadEnter,Escape" ; - завершающие клавиши, отображаемые в дневнике (см. переменную endkey)
;----------------------------------------------------------
endkey:="{Pause}{Space}{Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}"
Eng=qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>
Rus=йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ

if log
{
    SplitPath logfile, , dir
    FileCreateDir % dir
}
clip_old:=Clipboard

Loop
{
    WinGetTitle t, A
    Input text, i v, % endkey
    StringLen count, text
    e:=ErrorLevel
    if e=Endkey:Pause
        Translate()
    Log()
}

~LButton::
~RButton::
~MButton::
Input
return

Translate()
{    
    global
    clip:=Clipboard
    if (count>0)
        Send {BS %count%}
    else
    {
        Send ^{Ins}
        ClipWait 0.3
        if ! Errorlevel
        {
            Send {Del}
            text:=Clipboard
        }
        else
        {
            Tooltip Отмена невозможна, % A_CaretX,% A_CaretY
            Sleep 500
            ToolTip
            goto end
        }
    }
    r:="" 
    Loop, parse,text
    { 
       SendMessage, 0x50,, 0x4090409,, A ; Eng 
       p := InStr(Eng, A_LoopField, true) 
       if p > 0 
          r := r . SubStr(Rus, p, 1) 
       else 
       { 
          SendMessage, 0x50,, 0x4190419,, A ; Rus 
          p := InStr(Rus, A_LoopField, true) 
          if p > 0 
             r := r . SubStr(Eng, p, 1) 
          else 
             r := r . A_LoopField 
       } 
    } 
    PostMessage, 0x50, 2, 0,, A
    Send % r
    end:
    text:=r
    Clipboard:=clip
    return 
}

Log()
{
    global
    if ! log
        return
    if t contains % block
        return
    if (count>0)
    {
        if (t<>tlast)
        {
            FileAppend % "`n`n" A_DD "." A_MM "." A_YYYY "  " A_Hour ":" A_Min "  (" t ")`n", % logfile
            tlast:=t
        }
        if e contains EndKey
            StringTrimLeft e, e, 7
        k:=" "
        if e contains % fkey
            k:=" {" e "} "
        if e contains Enter
            k:=k "`n"
        if e=NewInput
            k:=" {Click} "
        FileAppend % text . k , % logfile
    }
    cl:=Clipboard
    if ((cl<>clip_old) && (cl<>""))
    {
        if cl contains % ignor
            return
        StringLen  l, cl
        end:=""
        if (l>cliplength)
            end:=" {...}"
        StringLeft cl, cl, % cliplength
        FileAppend % "`n`n### Clipboard  (" t ")`n" cl . end "`n###`n", % logfile
        
    }
    clip_old:=cl
    return
}

;------ Translit ------
>^vk42::
Translit()
MsgBox, 64, Translit, Текст в буфере!, 1
return

>^vk54::
Translit()
Send {Del}
Sleep 200
Send ^{vk56}
return

Translit()
{
    KeyWait RCtrl
    ClipBoard := "" 
    Send ^{Ins}
    ClipWait 2
    x:=ClipBoard

    StringReplace, x, x, а , a , All
    StringReplace, x, x, б , b , All
    StringReplace, x, x, в , v , All
    StringReplace, x, x, г , g , All
    StringReplace, x, x, д , d , All
    StringReplace, x, x, е , e , All
    StringReplace, x, x, ё , yo , All
    StringReplace, x, x, ж , zh , All
    StringReplace, x, x, з , z , All
    StringReplace, x, x, и , i , All
    StringReplace, x, x, й , j , All
    StringReplace, x, x, к , k , All
    StringReplace, x, x, л , l , All
    StringReplace, x, x, м , m , All
    StringReplace, x, x, н , n , All
    StringReplace, x, x, о , o , All
    StringReplace, x, x, п , p , All
    StringReplace, x, x, р , r , All
    StringReplace, x, x, с , s , All
    StringReplace, x, x, т , t , All
    StringReplace, x, x, у , u , All
    StringReplace, x, x, ф , f , All
    StringReplace, x, x, х , kh , All
    StringReplace, x, x, ц , ts , All
    StringReplace, x, x, ч , ch , All
    StringReplace, x, x, ш , sh , All
    StringReplace, x, x, щ , shh , All
    StringReplace, x, x, ъ , " , All
    StringReplace, x, x, ы , y , All
    StringReplace, x, x, ь , ' , All
    StringReplace, x, x, э , eh , All
    StringReplace, x, x, ю , yu , All
    StringReplace, x, x, я , ya , All

    StringReplace, x, x, А , A , All
    StringReplace, x, x, Б , B , All
    StringReplace, x, x, В , V , All
    StringReplace, x, x, Г , G , All
    StringReplace, x, x, Д , D , All
    StringReplace, x, x, Е , E , All
    StringReplace, x, x, Ё , Yo , All
    StringReplace, x, x, Ж , Zh , All
    StringReplace, x, x, З , Z , All
    StringReplace, x, x, И , I , All
    StringReplace, x, x, Й , J , All
    StringReplace, x, x, К , K , All
    StringReplace, x, x, Л , L , All
    StringReplace, x, x, М , M , All
    StringReplace, x, x, Н , N , All
    StringReplace, x, x, О , O , All
    StringReplace, x, x, П , P , All
    StringReplace, x, x, Р , R , All
    StringReplace, x, x, С , S , All
    StringReplace, x, x, Т , T , All
    StringReplace, x, x, У , U , All
    StringReplace, x, x, Ф , F , All
    StringReplace, x, x, Х , Kh , All
    StringReplace, x, x, Ц , Ts , All
    StringReplace, x, x, Ч , Ch , All
    StringReplace, x, x, Ш , Sh , All
    StringReplace, x, x, Щ , Shh , All
    StringReplace, x, x, Ъ , " , All
    StringReplace, x, x, Ы , Y , All
    StringReplace, x, x, Ь , ' , All
    StringReplace, x, x, Э , Eh , All
    StringReplace, x, x, Ю , Yu , All
    StringReplace, x, x, Я , Ya , All

    return Clipboard:=x
}

2

Re: AHK: Еще один заменитель Punto Switcher'a

А где сейчас используется транслит?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: Еще один заменитель Punto Switcher'a

В каком смысле? Я делал для себя и как в оригинале. Могу убрать

4

Re: AHK: Еще один заменитель Punto Switcher'a

Нет, я просто хотел узнать, для чего это нужно, я не в курсе.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5 (изменено: stealzy, 2014-11-10 17:38:08)

Re: AHK: Еще один заменитель Punto Switcher'a

Чуток улучшил.
• перевесил исправление на Hotkey(теперь можно выбрать любое сочетание клавиш),
• убрал пробел из EndKey(можно успеть набрать несколько слов прежде чем заметишь неправильный раскладку),
• вместо ClipWait используется сравнение буфера до и после
(как вариант можно очищать буфер и смотреть не появилось ли чего),
из-за низкой надежности срабатывания ClipWait и кракозябр при повторном нажатии(у меня во всяком случае)

#NoEnv 
SendMode Input 
#SingleInstance, force
#MaxHotkeysPerInterval 500
SetKeyDelay 50, 50
Menu, Tray, Icon, shell32.dll, 134

;----------------------------------------------------------
; Shift+Pause - конвертация последнего текста(слова) или выделенного текста
;----------------------------------------------------------
endkey:="{Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}"
Lat:="~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,.?&@#"
Cyr:="ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю,?""№"

clip_old:=Clipboard

Loop
{
    WinGetTitle t, A
    Input text, i v, % endkey
    StringLen count, text
    if fTranslateAfter
        Translate()
}

~LButton::
~RButton::
~MButton::
Input
return

+Pause::
Input
fTranslateAfter:=1
return

Translate()
{    
    global
    clip:=Clipboard
    if (count>0)
        Send {BS %count%}
    else
    {
        Send ^{Ins}
        Sleep 20
        clipAfter:=Clipboard
        if (clip != clipAfter) ; ! Errorlevel
        {
            Send {Del}
            text:=Clipboard
        }
        else
        {
            Tooltip Отмена невозможна, % A_CaretX,% A_CaretY
            Sleep 500
            ToolTip
            goto end
        }
    }
    r:="" 
    Loop, parse,text
    { 
       SendMessage, 0x50,, 0x4090409,, A ; Eng 
       p := InStr(Lat, A_LoopField, true) 
       if p > 0 
          r := r . SubStr(Cyr, p, 1) 
       else 
       { 
          SendMessage, 0x50,, 0x4190419,, A ; Rus 
          p := InStr(Cyr, A_LoopField, true) 
          if p > 0 
             r := r . SubStr(Lat, p, 1) 
          else 
             r := r . A_LoopField 
       } 
    } 
    PostMessage, 0x50, 2, 0,, A
    Send % r
    end:
    text:=r
    Clipboard:=clip
    fTranslateAfter:=0
    return 
}

Баг — при пропускании текста через

Loop, parse

перевод строки — CR;LF(Windows формат) удваивается.
Если просто CR или LF (Mac или Unix формат) все ок.
Кто-нибудь знает как побороть?

Win7x64, AutoHotkey 1.1.30.00

6 (изменено: stealzy, 2014-11-24 11:55:51)

Re: AHK: Еще один заменитель Punto Switcher'a

Окончательный вариант, одна функция - один хоткей.
Отличие от других вариантов — исправление текста, набранного посередине другого текста или слова.

; Shift+Pause — конвертация  последнего текста  или  выделенного текста
; Зажмите Shift+Pause на 2с — в трее появится иконка, 
; откуда можно добавить скомпилированый скрипт в автозагрузку, или закрыть скрипт.
;----------------------------------------------------------
#NoEnv
#SingleInstance, force
#MaxHotkeysPerInterval 500
SetKeyDelay 50, 50
{ ; отключаемая иконка в трее
Menu, Tray, NoIcon
Menu, tray, NoStandard
NewName:="Добавить в автозагрузку"
Menu, tray, add, %NewName%, AutorunSwitch
Menu, tray, add, Выход, _Exit
}
endkey:="{Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}"
Global Lat, Cyr
Lat:="~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,./|?@#$^&"
Cyr:="ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю./,""№;:?"

Loop
{
    Input text, i v, % endkey
    if fReplaceAfter {
        ReplaceText(text)
        fReplaceAfter:=0
    }
}

~LButton::
~RButton::
~MButton::
Input
return

+Pause::
Input
KeyWait, vk10, T2
if ErrorLevel
{
    checkIcon()
} else {
    fReplaceAfter:=1
}
return

ReplaceText(text) {
    ; take text & clear failure
    StringLen count, text
    clip:=Clipboard
    if (count>0)
        SendInput {BS %count%}
    else
    {
        SendPlay ^{Ins}
        Sleep 20 ; без задержки не всегда успевает попасть в буфер
        clipAfter:=Clipboard
        if (clip != clipAfter) ; ! Errorlevel
        {
            SendInput {Del}
            text:=Clipboard
        }
        else
        {
            Tooltip Отмена невозможна, % A_CaretX,% A_CaretY
            Sleep 500
            ToolTip
            goto end
        }
    }
    
    ; determine lang
    ;    lang    ID        code        layoute
    ;    En        1033    0x4090409    Lat
    ;    Ru        1049    0x4190419    Cyr
    EnID := 1033
    EnCode:=0x4090409
    RuCode:=0x4190419
    
    failureLangID := GetInputLangID("A")
    correctLangCode := (failureLangID=EnID) ? RuCode : EnCode
    failureLayoute := (failureLangID = EnID) ? Lat : Cyr
    correctLayoute := (failureLangID = EnID) ? Cyr : Lat
    
    ; replace text
    substituteText:="" 
    Loop, parse,text,`r
    {
        symbol := InStr(failureLayoute, A_LoopField, true)
        if symbol > 0
            substituteText .= SubStr(correctLayoute, symbol, 1)
        else
            substituteText .= A_LoopField
    }
    
    ; change language & send text
    changeLang(correctLangCode)
    Sleep 50 ; без задержки появляются баги со знаками пунктуации
    SendInput {Raw}%substituteText% ; режим Raw позволяет посылать фигурные скобки [{], [}] вместо [Х], [Ъ]. Без Raw скобку { придется оборачивать так: {{}
    end:
    Clipboard:=clip
    return
}
changeLang(lcode=0) {
    WinGetClass, Class, % "ahk_id" hwnd := WinExist("A")
    if (Class = "#32770")
        hwnd := DllCall("GetWindow", Ptr, hwnd, UInt, GW_OWNER := 4, Ptr)
    if lcode
        PostMessage, 0x50,,%lcode%,, ahk_id %hwnd%
    else
        PostMessage, 0x50, 2,,, ahk_id %hwnd%
}
GetInputLangID(window) {
    If !(hWnd := WinExist(window))
        return
 
    WinGetClass, Class
 
    if (Class == "ConsoleWindowClass")
    {
        WinGet, consolePID, PID
        DllCall("AttachConsole", Ptr, consolePID)
        VarSetCapacity(buff, 16)
        DllCall("GetConsoleKeyboardLayoutName", Str, buff)
        DllCall("FreeConsole")
        langID := "0x" . SubStr(buff, -3)
    }
    Else
        langID := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr) & 0xFFFF
 
    return langID
}

; дальнейший код нужен только для версии с иконкой
checkIcon() {
Static fIconShow:=0
if fIconShow
    Menu, Tray, NoIcon
Else {
    Menu, Tray, Icon
    TrayTip, ShiftPause, I here
}
fIconShow:=!fIconShow
}
AutorunSwitch:
{
    if (NewName != "Убрать из автозагрузки")
    {
        OldName := "Добавить в автозагрузку"
        NewName := "Убрать из автозагрузки"
        FileCreateShortcut, %A_ScriptFullPath%, %A_Startup%\ShiftPause.lnk
    } else {
        OldName := "Убрать из автозагрузки"
        NewName := "Добавить в автозагрузку"
        FileDelete, %A_Startup%\ShiftPause.lnk
    }
    menu, tray, rename, %OldName%, %NewName%
}
Return
_Exit:
ExitApp
; Основан на коде Krot66, использована ф-я для определения языка от teadrinker

Можно сделать .ехе с помощью ahk2exe.

Win7x64, AutoHotkey 1.1.30.00

7

Re: AHK: Еще один заменитель Punto Switcher'a

Ошибка на 69 строке - A Goto/Gosub must not jump into a block that doesn't enclose it.

Как сказал мой дед - Я твой дед

8 (изменено: stealzy, 2014-11-20 16:43:58)

Re: AHK: Еще один заменитель Punto Switcher'a

Поправил, спасибо. Ошибка была из-за добавленых под конец фиг. скобок для красивого фолдинга. Не проверил.

Win7x64, AutoHotkey 1.1.30.00

9

Re: AHK: Еще один заменитель Punto Switcher'a

А если у меня своя раскладка типа

q::a
w::s

и т.д., и я использую SendMode Input, то строчка Input text, i v, % endkey не срабатывает для этих букв, даже если убрать опцию i, т.к. в справке по команде Input написано

I: Ignore input generated by any AutoHotkey script, such as the SendEvent command. However, the SendInput and SendPlay methods are always ignored, regardless of this setting.

Получается, единственный выход - использовать для скрипта вместо одного? Можно ли в один скрипт всё уместить?

Ещё в последнем варианте у меня цикл Loop, parse, text,`r не работает, нужно удалить ", `r".

10

Re: AHK: Еще один заменитель Punto Switcher'a

Скорее всего, надо просто видоизменить переменные Lat и Cyr ( в моей версии Rus и Eng), по которым производится замена символов.

11 (изменено: softrunner, 2015-08-15 13:47:26)

Re: AHK: Еще один заменитель Punto Switcher'a

Скорее всего, надо просто видоизменить переменные Lat и Cyr ( в моей версии Rus и Eng), по которым производится замена символов.

Не понял. Если используется SendMode Input, то в цикле получения строк зарегистрированные клавиши вообще не появляются. Похоже, остаётся лишь либо использовать SendMode Event, либо два отдельных скрипта.

12

Re: AHK: Еще один заменитель Punto Switcher'a

Ответ касался вашей нестандартной (бельгийской или какой еще) клавиатуры. Переменные, о которых писал - это ряды знаков, по которым производится замена символов при нажатии кнопки Pause. Если у вас перетасовано размещение руских и английских символов, нужно поправить эти ряды так, чтобы эти соответствия были верными. Это просто: заменяются знаки в одной и той же позиции в переменных Cyr и Lat.
Режим посылки клавиш SendEvent медленнее, но много более надежен, так что лучше убрать всю мешанину в скрипте и всюду использовать просто Send, как было у меня. Хотя это вопрос приложений, с которыми вы работаете - для большинства текстовых редакторов и офисных пакетов это не имеет значения.

13

Re: AHK: Еще один заменитель Punto Switcher'a

Krot66, клавиатура стандартная, просто раскладка не qwerty. Константы Lat и Cyr я, естественно, поменял. Сейчас перешёл на режим Send, хотя в справке написано

SendInput and SendPlay ... are generally faster and more reliable.

поэтому я и спрашиваю, можно ли обойти ограничение команды Input.

14

Re: AHK: Еще один заменитель Punto Switcher'a

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

15

Re: AHK: Еще один заменитель Punto Switcher'a

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

P.S.: Punto уже несколько раз сбрасывал собственные настройки, да и функция автопереключения мне ни к чему.

16

Re: AHK: Еще один заменитель Punto Switcher'a

Думаю, проблема в Win 10.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

17 (изменено: Alectric, 2015-11-07 22:13:05)

Re: AHK: Еще один заменитель Punto Switcher'a

becauseim пишет:

Есть ли альтернативные сценарии?

Пользуюсь таким кодом:



Cyr:="ЙЦУКЕНГШЩЗФЫВАПРОЛДЯЧСМИТЬйцукенгшщзфывапролдячсмитьбюБЮхъХЪЖжэёЁЭ"""",.№;:?/"
Lat:="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm,.<>{}[]:;'``~""""@?/#$^&|"
RegUp:=  "ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮQWERTYUIOPASDFGHJKLZXCVBNM"
RegDown:="йцукенгшщзхъфывапролджэячсмитьбюqwertyuiopasdfghjklzxcvbnm"



loop
{
  sleep,100
  ; //////////////// фикс контрола \\\\\\\\\\\\\\\\\\\
  if GetKeyState("ctrl","P")
  {
    keywait,ctrl,T0.2
    if errorlevel
      ctrltimeout=1
  }
  else
    ctrltimeout=0
}

; ////////// переключение языка ____________________________HOTKEYS_________________________
Ctrl::
if !ctrltimeout
  InputLayout("T")
return

; ////////// переключение раскладки выделенного слова или слова перед кареткой, конвертация регистра_________HOTKEYS___________
+Break::
!Break::
Break::
Critical
keywait,Break,L
;if A_TimeSinceThisHotkey>200
;  return
TempClipboard:=ClipboardAll
;Clipboard=
PrevLen=
if a_thishotkey=break
{
  tmpc:=Copy(1)
  if (tmpc and !instr(tmpc,"`n,`r"))
    SelText:=tmpc
  else
  {
    loop,33
    {
;      Clipboard=
      SendInput,{shift down}
      tooltip
      SendInput,{Left}
      tooltip
      SendInput,{shift up}
      tooltip
      if !Clipboardd:=Copy(1)
        break
      Len:=StrLen(Clipboardd)
      if (Len=PrevLen)
      {
        SelText:=Clipboardd
        break
      }
      PrevLen:=Len
      swd:=SubStr(Clipboardd,1,1)
      if A_Index>32
        swd=`n
      if swd in %A_Space%,%A_Tab%,`n,`r
      {
        SendInput,{shift down}
        SendInput,{right}
        SendInput,{shift up}
        swd:=SubStr(Clipboardd,1,2)
        SelText:=SubStr(Clipboardd,RegExMatch(swd,"[\n\r]{2}") ? 3 : 2)
        break
      }
    }
  }
}
else
  SelText:=Copy(1)
NewText=
Loop,parse,SelText
{
  if (a_thishotkey="!break")
  {
    if found:=InStr(RegUp, A_LoopField, 1)
      NewText.=SubStr(RegDown, found, 1)
    else
      if found:=InStr(RegDown, A_LoopField, 1)
        NewText.=SubStr(RegUp, found, 1)
    if !found
      NewText.=A_LoopField
  }
  else
  {
    if found:=InStr(Lat, A_LoopField, 1)
    {
      Lang=Rus
      NewText.=SubStr(Cyr, found, 1)
    }
    else
      if found:=InStr(Cyr, A_LoopField, 1)
      {
        Lang=Eng
        NewText.=SubStr(Lat, found, 1)
      }
    if !found
      NewText.=A_LoopField
  }
}
Clipboard:=NewText
loop,30
{
  sleep,10
} until Clipboard
SendInput,^{vk56}
Sleep,300
Clipboard:=TempClipboard
TempClipboard:=SelText:=
if (a_thishotkey!="!break")
  InputLayout(Lang)
Return



RemoveToolTip:
tooltip
return



InputLayout(switch="T")
{
  mousegetpos,x,y
  WinGetClass,Class,% "ahk_id" hID:=WinExist("A")
  if !id:=DllCall("GetWindow",Ptr,hid,UInt,GW_OWNER:=4,Ptr)
    id:=hID
  ThreadID:=DllCall("GetWindowThreadProcessId",Ptr,id,Int,0)
  sKbd:=GetLayot(ThreadID)
  if (switch="T")
  {
    SendMessage,0x50,0,% sKbd="English" ? 0x4190419 : 0x4090409,,ahk_id %ID%
    ToolTip,% sKbd="English" ? "Русский" : "Английский",% A_CaretX=0 ? X : A_CaretX+10,% A_CaretY=0 Y ? : A_CaretY-20
    if (sKbd=GetLayot(ThreadID))
      send,{alt down}{shift down}{shift up}{alt up}
    SetTimer,RemoveToolTip,-1000
    Return 1
  }
  else if (switch="Eng")
  {
    SendMessage,0x50,0,0x4090409,,ahk_id %ID%
    ToolTip,Английский,% A_CaretX=0 ? X : A_CaretX+10,% A_CaretY=0 Y ? : A_CaretY-20
    sKbd=English
    if (sKbd!=GetLayot(ThreadID))
      send,{alt down}{shift down}{shift up}{alt up}
    SetTimer,RemoveToolTip,-1000
    Return 1
  }
  else if (switch="Rus")
  {
    SendMessage,0x50,0,0x4190419,,ahk_id %ID%
    ToolTip,Русский,% A_CaretX=0 ? X : A_CaretX+10,% A_CaretY=0 Y ? : A_CaretY-20
    sKbd=English ;
    if (sKbd=GetLayot(ThreadID))
      send,{alt down}{shift down}{shift up}{alt up}
    SetTimer,RemoveToolTip,-1000
    Return 1
  }
  Return sKbd
}
GetLayot(ThreadID)
{
    HKL:=DllCall("GetKeyboardLayout",uint,ThreadID,UShort)
    VarSetCapacity(sKbd,260,0)
    DllCall("GetLocaleInfo",uint,HKL
                           ,uint,0x1001
                           ,str,sKbd
                           ,uint,260)
  return sKbd
}

Copy(c="")
{
  if c
  {
    Clipboard=
    loop,30
    {
      sleep,10
    } until !Clipboard
    SendInput,^{vk43}
  }
  loop,30
  {
    sleep,10
  } until Clipboard
  return % Clipboard
}

ЗЫ Могут быть ошибки т.к. выдернул код из своего большого скрипта.

Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

18 (изменено: becauseim, 2015-11-07 23:16:36)

Re: AHK: Еще один заменитель Punto Switcher'a

Alectric, работает! Но как и прежние сценарии, роняет Скайп.
Скажите, пожалуйста, за что отвечает "фикс контрола"? В каких случаях или в каких целях он используется?

loop
{
  sleep,100
  ; //////////////// фикс контрола \\\\\\\\\\\\\\\\\\\
  if GetKeyState("ctrl","P")
  {
    keywait,ctrl,T0.2
    if errorlevel
      ctrltimeout=1
  }
  else
    ctrltimeout=0
}

19

Re: AHK: Еще один заменитель Punto Switcher'a

По ctrl - простое переключение раскладки, фикс - чтобы переключение не срабатывало, если ctrl зажат дольше 200 ms.

becauseim пишет:

роняет Скайп

Что значит "роняет" скайп?

Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

20

Re: AHK: Еще один заменитель Punto Switcher'a

Alectric, окно перестает отвечать.

21 (изменено: Alectric, 2015-11-15 11:06:14)

Re: AHK: Еще один заменитель Punto Switcher'a

Попробуй заменить функцию GetLayot(ThreadID) на пустышку:

GetLayot(ThreadID)
{
  return "English"
}

если перестанет зависать, то нужно подумать чем ее заменить. Если все равно зависает то нужно убирать все DLLCall.

Закоментируй строки:

;  if !id:=DllCall("GetWindow",Ptr,hid,UInt,GW_OWNER:=4,Ptr)
;    id:=hID
;  ThreadID:=DllCall("GetWindowThreadProcessId",Ptr,id,Int,0)
Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

22

Re: AHK: Еще один заменитель Punto Switcher'a

Alectric, сконвертировал дважды одно и то же слово, т.е. сначала в другую раскладку, потом опять в прежнюю, на третий раз "не отвечает". Да и работает с задержкой.

23

Re: AHK: Еще один заменитель Punto Switcher'a

Другие скрипты запущены?

Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

24 (изменено: becauseim, 2015-11-15 11:16:18)

Re: AHK: Еще один заменитель Punto Switcher'a

Alectric пишет:

Закоментируй строки:

;  if !id:=DllCall("GetWindow",Ptr,hid,UInt,GW_OWNER:=4,Ptr)
;    id:=hID
;  ThreadID:=DllCall("GetWindowThreadProcessId",Ptr,id,Int,0)

https://i.gyazo.com/70805c75b61116a2c0e93ef6e2cee789.gif
То же и с выключенными другими скриптами.

25

Re: AHK: Еще один заменитель Punto Switcher'a

Попробуй сохранить сам скрипт в юникоде.

Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

26 (изменено: stealzy, 2017-05-03 22:09:09)

Re: AHK: Еще один заменитель Punto Switcher'a

Почти полностью переписал скрипт.

По заданной ГК исправляется последний набранный текст, таковым считается любой текст,
не прерывающийся нажатием клавиш:
мыши, навигации (←↑↓→Pg*, Home, End), модификаторов (Alt Ctrl Win), Enter, Esc, F[1-12].
Полный список прерывающих клавиш содержится в методе _GetInputText().
Можно добавить туда пробел - тогда будет исправлятся только последнее слово.
Можно исключить Enter - тогда можно исправлять абзацами .
После исправления текста переключается раскладка.
Если выделен текст, то исправлен будет он.
(Большинством символов в выделенном будет определена раскладка, символы из которой необходимо исправить.)

+ Тех. особенности:

• Использует команду Input для взятия последнего введенного текста,
если переменная последнего введенного текста пуста, то ^{Ins} и взятие из буфера обмена (выделенный текст)
(если использована одна из EndKeys клавиш, описанных в методе _GetInputText() или клик мышью, переменная последнего введенного текста обнуляется).
• Текст исправляется с помощью захардкоженного соответствия латинских и кириллических символов в стандартных раскладках (строки Lat:="~QWER... и Cyr:="ЁЙЦУК..., описанные в методе _GetTextInOppositeLayout()).
Направление исправления выбирается на основе тек.раскладки, для выделенного текста - на основе большинства символов в тексте.
• Использует BackSpace для стирания последнего введенного текста, и SendInput для ввода исправленного.

Ограничения: в одном скрипте с переключалкой нежелательно использовать горячие клавиши на клики мышью или клавиши модификаторы (переключалка устанавливает свои прозрачные ГК на мышь для запрета исправления введенного текста после клика мышью).

#SingleInstance, force
#NoEnv
; #NoTrayIcon
P := new Punto
corr := ObjBindMethod(P, "CorrectionEnteredText")
Hotkey % "Pause", % corr
; togg := ObjBindMethod(P, "ToggleLayout")
; Hotkey % "!" Format("vk{:02x}", GetKeyVK("R")), % corr
Return

Class Punto {
	__New() {
		; Workaround for include mouse button in Input EndKeys
			_InputFn := ObjBindMethod(this, "_Input")
			_InputModFn := ObjBindMethod(this, "_Input", keyModifier := true)
			Hotkey ~*LButton, % _InputFn
			Hotkey ~*RButton, % _InputFn
			Hotkey ~*MButton, % _InputFn
		; Workaround for run CorrectionEnteredText() from hotkey including modifier keys:
		; you can't put LAlt in EndKeys if you run correction method by hotkey contain Alt (!R).
			Hotkey ~*LControl, % _InputModFn
			Hotkey ~*RControl, % _InputModFn
			Hotkey ~*LAlt, % _InputModFn
			Hotkey ~*RAlt, % _InputModFn
			Hotkey ~*LWin, % _InputModFn
			Hotkey ~*RWin, % _InputModFn
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer % timer, -1
	}
	_Input(keyModifier:=false) {
		If keyModifier ; Workaround because bug with using Hotkey ~*LAlt Up,
			KeyWait, % LTrim(A_ThisHotkey, "~*")
		Input
	}
	_GetInputText() {
		Input text, i v, {Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}
		this.ReplaceAfter := this.ReplaceAfter ? this._ReplaceText(text) :
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer % timer, -1
	}

	CorrectionEnteredText() {
		this.ReplaceAfter:=true
		Input
	}

	_ReplaceText(text) {
		StringLen count, text
		if (count>0)	; если вводился текст
			SendInput {BS %count%}
		else { 				; если выделен текст (при выделении используются кнопки мыши или шифт с навигационными кл. => text="" => count=0)
			cliptmp:=Clipboard
			Clipboard =
			SendPlay ^{Ins}
			Send ^{vk43}
			ClipWait .7, 1
			clipNew:=Clipboard
			if (clipNew != "") {
				text:=Clipboard
				fromClip:=true
			} else {
				Tooltip Выделите текст для исправления, A_CaretX+20, A_CaretY-3
				SetTimer TToff, -1000
				Return

				TToff:
					ToolTip
					Return
			}
			Clipboard:=cliptmp
		}

		substituteText := this._GetTextInOppositeLayout(text, fromClip, LayoutNeedToggle)
		(!fromClip || LayoutNeedToggle)  ?  this.ToggleLayout()
		Sleep 50 ; без задержки появляются баги со знаками пунктуации
		SetKeyDelay 50, 50
		SendInput {Raw}%substituteText%
		Return
	}
	_GetTextInOppositeLayout(text, fromClip, ByRef LayoutNeedToggle) {
		static Lat:="~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,./|?@#$^&"
		, Cyr:="ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю./,""№;:?"

		En := (this.GetInputHKL() = 0x04090409)
		If fromClip {
			; для выделенного текста определяем принадлежность большинства символов к той или иной раскладке
			u := 0
			Loop, parse, text
			{
				OutputDebug % (A_LoopField = "`n") " " (A_LoopField = "`r")
				LatSym := InStr(Lat, A_LoopField), CyrSym := InStr(Cyr, A_LoopField)
				if (LatSym && !CyrSym)
					++u
				else if (CyrSym && !LatSym)
					--u
			}

			failureLayout:= (u>0) ? Lat : Cyr
			correctLayout := (u>0) ? Cyr : Lat
			LayoutNeedToggle := En ^ (u<=0)
		}
		Else {
			; для простого переключения основываемся на тек. раскладке
			failureLayout:= En ? Lat : Cyr
			correctLayout := En ? Cyr : Lat
		}

		Loop, parse, text,, `r ; `r — hack for Send command, because it regards `r`n as separate \n
		{
			if (symbolNum := InStr(failureLayout, A_LoopField, CaseSensitive:=true))
				substituteText .= SubStr(correctLayout, symbolNum, 1)
			else
				substituteText .= A_LoopField
		}
		Return substituteText
	}
	ToggleLayout() {
		PostMessage, 0x50, 2,,, % (hWndOwn := DllCall("GetWindow", Ptr, hWnd:=WinActive("A"), UInt, GW_OWNER := 4, Ptr)) ? "ahk_id" hWndOwn : "ahk_id" hWnd
	}
	GetInputHKL() {
		hWnd := WinExist("A")
		WinGetClass, Class
		if (Class == "ConsoleWindowClass") {
				WinGet, consolePID, PID
				DllCall("AttachConsole", Ptr, consolePID)
				VarSetCapacity(buff, 16)
				DllCall("GetConsoleKeyboardLayoutName", Str, buff)
				DllCall("FreeConsole")
				HKL := "0x" . SubStr(buff, -3)
		} else
			HKL := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr)
		return HKL
	}
}
Win7x64, AutoHotkey 1.1.30.00

27

Re: AHK: Еще один заменитель Punto Switcher'a

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

28

Re: AHK: Еще один заменитель Punto Switcher'a

Попробуйте, у меня не вышло.

Win7x64, AutoHotkey 1.1.30.00

29

Re: AHK: Еще один заменитель Punto Switcher'a

В старом скрипте если дописать в endkey {LButton}{RButton}{MButton} и удалить горячие клавиши все работает как надо. Т.е. Input отрабатывает нажатия клавиш мыши.

30 (изменено: stealzy, 2017-03-24 19:55:57)

Re: AHK: Еще один заменитель Punto Switcher'a

Я пробовал именно так. Попробуйте простой Input и MsgBox за ним чтобы убедиться.

Input text,, {LButton}{End}
MsgBox % text
ExitApp
Win7x64, AutoHotkey 1.1.30.00

31

Re: AHK: Еще один заменитель Punto Switcher'a

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

32 (изменено: stealzy, 2017-03-25 00:10:05)

Re: AHK: Еще один заменитель Punto Switcher'a

Krot66, так это я намеренно сделал )). После клика курсор может оказаться в другом поле, и туда будут посланы нажатия BackSpace и введен тест из предыдущего поля. Можно конечно проверять совпадене контрола по таймеру, но ведь можно кликнуть в тот же самый контрол в середину текста, результат можете себе представить.
У меня юзкейс такой: неправильно начал набирать → увидел → нажал ГК для исправления.
Мне просто ни разу не понадобилось кликать мышкой м/у начальным и конечными пунктами, а вы зачем кликаете?

В методе __New() уберите хоткеи если так угодно.

Win7x64, AutoHotkey 1.1.30.00

33

Re: AHK: Еще один заменитель Punto Switcher'a

В скрипте из первого поста при нажатии на горячую клавишу отправляется последнее сконвертированное слово. В скрипте из 26-го поста даже при выделении слова пишет "Выделите текст для исправления". Это только у меня так?

34

Re: AHK: Еще один заменитель Punto Switcher'a

Дальнейшая разработка вопроса.

35 (изменено: becauseim, 2017-05-03 20:07:23)

Re: AHK: Еще один заменитель Punto Switcher'a

stealzy, реагирует на выделенные слова по-прежнему. При конвертировании набранного слова на англ., конвертирует слово дважды, сначала на рус., затем собратно. Подумал, что запущен Punto Switcher, но нет. Другие скрипты тоже закрыл для чистоты теста.

36 (изменено: stealzy, 2017-05-03 20:52:48)

Re: AHK: Еще один заменитель Punto Switcher'a

becauseim, покажите содержимое файла log.txt после воспроизведения проблемы.

#SingleInstance, force
#NoEnv
; #NoTrayIcon
P := new Punto
corr := ObjBindMethod(P, "CorrectionEnteredText")
Hotkey % "Pause", % corr
Return

Class Punto {
	__New() {
		Log("__New")
		; Workaround for include mouse button in Input EndKeys
			_InputFn := ObjBindMethod(this, "_Input")
			_InputModFn := ObjBindMethod(this, "_Input", keyModifier := true)
			Hotkey ~*LButton, % _InputFn
			Hotkey ~*RButton, % _InputFn
			Hotkey ~*MButton, % _InputFn
		; Workaround for run CorrectionEnteredText() from hotkey including modifier keys:
		; you can't put LAlt in EndKeys if you run correction method by hotkey contain Alt (!R).
			Hotkey ~*LControl, % _InputModFn
			Hotkey ~*RControl, % _InputModFn
			Hotkey ~*LAlt, % _InputModFn
			Hotkey ~*RAlt, % _InputModFn
			Hotkey ~*LWin, % _InputModFn
			Hotkey ~*RWin, % _InputModFn
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer % timer, -1
	}
	_Input(keyModifier:=false) {
		Log("_Input")
		If keyModifier ; Workaround because bug with using Hotkey ~*LAlt Up,
			KeyWait, % LTrim(A_ThisHotkey, "~*")
		Input
	}
	_GetInputText() {
		Log("_GetInputText")
		Input text, i v, {Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}
		this.ReplaceAfter := this.ReplaceAfter ? this._ReplaceText(text) :
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer % timer, -1
	}

	CorrectionEnteredText() {
		Log("`nCorrectionEnteredText")
		this.ReplaceAfter:=true
		Input
	}

	_ReplaceText(text) {
		Log("_ReplaceText(" text ")")
		StringLen count, text
		if (count>0)	; если вводился текст
			SendInput {BS %count%}
		else { 				; если выделен текст (при выделении используются кнопки мыши или шифт с навигационными кл. => text="" => count=0)
			cliptmp:=Clipboard
			Clipboard =
			SendPlay ^{Ins}
			ClipWait .2, 1
			clipNew:=Clipboard
			if (clipNew != "") {
				text:=Clipboard
				Log("_ReplaceText: clipBoard = " text)
				fromClip:=true
			} else {
				Tooltip Выделите текст для исправления, A_CaretX+20, A_CaretY-3
				SetTimer TToff, -1000
				Return

				TToff:
					ToolTip
					Return
			}
			Clipboard:=cliptmp
		}

		substituteText := this._GetTextInOppositeLayout(text, fromClip, LayoutNeedToggle)
		(!fromClip || LayoutNeedToggle)  ?  this.ToggleLayout()
		Sleep 50 ; без задержки появляются баги со знаками пунктуации
		SetKeyDelay 50, 50
		SendInput {Raw}%substituteText%
		Return
	}
	_GetTextInOppositeLayout(text, fromClip, ByRef LayoutNeedToggle) {
		static Lat:="~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,./|?@#$^&"
		, Cyr:="ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю./,""№;:?"

		En := (this.GetInputHKL() = 0x04090409)
		If fromClip {
			; для выделенного текста определяем принадлежность большинства символов к той или иной раскладке
			u := 0
			Loop, parse, text
			{
				OutputDebug % (A_LoopField = "`n") " " (A_LoopField = "`r")
				LatSym := InStr(Lat, A_LoopField), CyrSym := InStr(Cyr, A_LoopField)
				if (LatSym && !CyrSym)
					++u
				else if (CyrSym && !LatSym)
					--u
			}

			failureLayout:= (u>0) ? Lat : Cyr
			correctLayout := (u>0) ? Cyr : Lat
			LayoutNeedToggle := En ^ (u<=0)
		}
		Else {
			; для простого переключения основываемся на тек. раскладке
			failureLayout:= En ? Lat : Cyr
			correctLayout := En ? Cyr : Lat
		}

		Loop, parse, text,, `r ; `r — hack for Send command, because it regards `r`n as separate \n
		{
			if (symbolNum := InStr(failureLayout, A_LoopField, CaseSensitive:=true))
				substituteText .= SubStr(correctLayout, symbolNum, 1)
			else
				substituteText .= A_LoopField
		}
		Return substituteText
	}
	ToggleLayout() {
		Log("ToggleLayout")
		PostMessage, 0x50, 2,,, % (hWndOwn := DllCall("GetWindow", Ptr, hWnd:=WinActive("A"), UInt, GW_OWNER := 4, Ptr)) ? "ahk_id" hWndOwn : "ahk_id" hWnd
	}
	GetInputHKL() {
		hWnd := WinExist("A")
		WinGetClass, Class
		if (Class == "ConsoleWindowClass") {
				WinGet, consolePID, PID
				DllCall("AttachConsole", Ptr, consolePID)
				VarSetCapacity(buff, 16)
				DllCall("GetConsoleKeyboardLayoutName", Str, buff)
				DllCall("FreeConsole")
				HKL := "0x" . SubStr(buff, -3)
		} else
			HKL := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr)
		return HKL
	}
}

Log(str) {
	FileAppend % str "`n", %A_ScriptDir%\log.txt
}

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

реагирует на выделенные слова по-прежнему

Это как? Совсем не конвертирует выделенное или все-таки дважды?

Win7x64, AutoHotkey 1.1.30.00
+ ww2

37 (изменено: becauseim, 2017-05-03 20:59:20)

Re: AHK: Еще один заменитель Punto Switcher'a

stealzy, сейчас вроде все работает кроме конвертирования выделенных слов. Т.е. выдает сообщение о том, что ничего не выделено. Наверное, в Win 10 что-то работает иначе.

Забегая вперед, если я выделю слова, набранные и на латинице и на кириллице, весь текст будет сконвертирован на противоположный или же приравняется к раскладке, в которой введено последнее или первое выделенное слово?

По какому принципу скрипт берет под конвертацию сразу несколько последних введенных слов?

Post's attachments

log.txt 4.79 kb, 2 downloads since 2017-05-03 

You don't have the permssions to download the attachments of this post.

38 (изменено: stealzy, 2017-05-03 22:05:57)

Re: AHK: Еще один заменитель Punto Switcher'a

becauseim, тогда и лог не нужен. Видимо просто в буфер обмена при копировании ничего ни попадает.
Судя по логу, единственная строка, которую вы пытались исправить выделением, была "привет воарплор", так?
Я использовал SendPlay ^{Ins}, сейчас добавил Send ^{vk43}, так работает?
Что касается логики исправления выделенного, я пробовал следующие варианты:
1) определяется текущая раскладка, все символы из нее в выделенном конвертируются.
2) каждый символ из одной раскладки переходил в другую.
Проблема в том, что делать с символами, присутствующими в обеих раскладках и находящимися на разных клавишах (,.;" etc).
3) определяем к какой раскладке однозначно относиться большинство символов, и исправляем только в этом направлении.
Сейчас использую последний.
Вообще выделением пользуюсь редко, хватает обычного режима.

Win7x64, AutoHotkey 1.1.30.00

39 (изменено: becauseim, 2017-05-03 21:47:39)

Re: AHK: Еще один заменитель Punto Switcher'a

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

И мне все-таки интересно, по какому принципу скрипт берет под конвертацию сразу несколько последних введенных слов? Потому что я привык к тому, как работает обычный Punto Switcher, который конвертирует всегда только одно последнее набранное слово. А сам Punto Switcher использовать не могу, т.к. из-за него некорректно срабатывают некоторые скрипты на AHK.

40

Re: AHK: Еще один заменитель Punto Switcher'a

Ранние версии скриптов просто брали и перелопачивали с одной раскладки на противоположную. Но в этом есть изъян: может выйти так, что в итоговой строке будут соседствовать русские и латинские символы. Этот способ позволяет избегать подобного. Можно, конечно, сделать "голосование", но это муторно да и нет смысла.

41 (изменено: stealzy, 2017-05-03 22:03:13)

Re: AHK: Еще один заменитель Punto Switcher'a

По выделенному тексту, что предлагаете делать с проблемой по пункту 2?
";" - оставить как есть или это буква "ж"?

по какому принципу скрипт берет под конвертацию сразу несколько последних введенных слов

Описания из 26 поста недостаточно?

только одно последнее набранное слово

См. там же. Дело вкуса, конечно. Судя по тому, что вы меняете раскладку и продолжаете набор текста, не глядя на экран, вам этого будет мало.

Win7x64, AutoHotkey 1.1.30.00

42

Re: AHK: Еще один заменитель Punto Switcher'a

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

Win 10 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

43

Re: AHK: Еще один заменитель Punto Switcher'a

stealzy пишет:

";" - оставить как есть или это буква "ж"?

Думаю, стоит конвертировать. Например, я хочу напечатать слово "жизнь", после которого поставить точку с запятой. Но если я не переключил раскладку, то у меня невольно выйдет следующее: ;bpym$
Если же вместо знака $ там находится ;, значит, я был намерен написать слово "жизньж".

Возможно, я не учел всех возможных моментов, поэтому, поправьте, если не прав.

44 (изменено: toxicdream, 2019-12-16 05:09:10)

Re: AHK: Еще один заменитель Punto Switcher'a

Спасибо большое.
На основе ваших скриптов наваял свое поделие.
Тестировал на двух языках в Windows 10.
Из особенностей:
+ работает в Edge
+ работает в консольных окнах CMD
+ перекодировывает смешанные строки

Для "железобетонного" переключения желательно назначить на каждый язык сочетание клавиш для переключения.
Или вручную, или с помощью файла реестра. В скрипте для английской раскладки ожидается Ctrl+Shist+1, для русской - Ctrl+Shift+2.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000100]
"Virtual Key"=hex:31,00,00,00
"Key Modifiers"=hex:06,c0,00,00
"Target IME"=hex:09,04,09,04

[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000101]
"Virtual Key"=hex:32,00,00,00
"Key Modifiers"=hex:06,c0,00,00
"Target IME"=hex:19,04,19,04

Собственно моё изделие:

#InstallKeybdHook
#SingleInstance, force
#NoEnv
;#NoTrayIcon

SetNumLockState,    On
SetScrollLockState, AlwaysOff
SetCapsLockState,   AlwaysOff

MyPunto := new Punto

corr := ObjBindMethod(MyPunto, "CorrectionEnteredText")
togg := ObjBindMethod(MyPunto, "ToggleLayout")
tgEN := ObjBindMethod(MyPunto, "ToggleLayout", "ENG")
tgRU := ObjBindMethod(MyPunto, "ToggleLayout", "RUS")
;chck := ObjBindMethod(MyPunto, "_check_lang")

Hotkey Pause,      %corr%
Hotkey ScrollLock, %togg%
Hotkey CapsLock,   %tgEN%
Hotkey +CapsLock,  %tgRU%
Hotkey ^CapsLock,  %tgRU%
Hotkey #n,         AkelPad
Hotkey #c,         Command
;Hotkey F12,        %chck%
Return

AkelPad:
Run c:\totalcmd\PROGRAMS\AkelPad.exe
Return

Command:
Run cmd.exe
Return

Class Punto {
	__New()
	{
		; Workaround for include mouse button in Input EndKeys
		_InputFn    := ObjBindMethod(this, "_Input")
		_InputModFn := ObjBindMethod(this, "_Input", keyModifier := true)
		Hotkey ~*LButton,  %_InputFn%
		Hotkey ~*RButton,  %_InputFn%
		Hotkey ~*MButton,  %_InputFn%
		; Workaround for run CorrectionEnteredText() from hotkey including modifier keys:
		; you can't put LAlt in EndKeys if you run correction method by hotkey contain Alt (!R).
		Hotkey ~*LControl, %_InputModFn%
		Hotkey ~*RControl, %_InputModFn%
		Hotkey ~*LAlt,     %_InputModFn%
		Hotkey ~*RAlt,     %_InputModFn%
		Hotkey ~*LWin,     %_InputModFn%
		Hotkey ~*RWin,     %_InputModFn%
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer %timer%, -1
	}

	_Input(keyModifier:=false)
	{
		If keyModifier ; Workaround because bug with using Hotkey ~*LAlt Up,
			KeyWait, %LTrim%(A_ThisHotkey, "~*")
		Input
	}

	_GetInputText()
	{						
		Input text, i v, {Enter}{NumpadEnter}{Tab}{Backspace}{Escape}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}
		this.ReplaceAfter := this.ReplaceAfter ? this._ReplaceText(text) :
		timer := ObjBindMethod(this, "_GetInputText")
		SetTimer %timer%, -1
	}

	CorrectionEnteredText()
	{
		this.ReplaceAfter := true
		Input
	}

	_ReplaceText(text)
	{
		StringLen count, text
		if (count>0)	; если вводился текст
			SendInput {BS %count%}
		else 				; если выделен текст (при выделении используются кнопки мыши или шифт с навигационными кл. => text="" => count=0)
		{
			cliptmp := Clipboard
			Clipboard := ""
			Sleep 50
			SendEvent ^{Ins}
			ClipWait 1, 1
			clipNew := Clipboard
			Clipboard := cliptmp
			if StrLen(clipNew) != 0
				text := clipNew
			else
			{
				Tooltip Выделите текст для исправления, A_CaretX+20, A_CaretY-3
				SetTimer TToff, -2000
				Return
				TToff:
					ToolTip
					Return
			}
		}
		substituteText := this._GetTextInOppositeLayout(text)
		if this._check_lang() == "ENG"
			this.ToggleLayout("RUS")
		else
			this.ToggleLayout("ENG")
		Sleep 50 ; без задержки появляются баги со знаками пунктуации
		SetKeyDelay 50, 50
		SendInput {Raw}%substituteText%
		Return
	}

	_GetTextInOppositeLayout(text)
	{
		static str1 := "~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,./|?@#$^&ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю./,""№;:?",
		       str2 := "ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёйцукенгшщзхъфывапролджэячсмитьбю./,""№;:?~QWERTYUIOP{}ASDFGHJKL:""ZXCVBNM<>``qwertyuiop[]asdfghjkl;'zxcvbnm,./|?@#$^&"
		Loop, parse, text,, `r ; `r — hack for Send command, because it regards `r`n as separate \n
		{
			if (symbolNum := InStr(str1, A_LoopField, CaseSensitive:=true))
				outputText .= SubStr(str2, symbolNum, 1)
			else
				outputText .= A_LoopField
		}
		Return outputText
	}

	ToggleLayout(Layout := "")
	{
		WinGetClass, winClass, A
		SetKeyDelay -1, -1
		if (StrLen(Layout) == 0)  or (winClass == "ConsoleWindowClass") 
			SendEvent {Blind}{LAlt down}{LShift down}{LShift up}{LAlt up}
		else
		{
			CurrLang := this._check_lang()
			if (Layout == "ENG") and (CurrLang != "ENG")
			{
				SendEvent ^+1
				SendMessage, 0x50, 0, 0x04090409,, A
			}
			if (Layout == "RUS") and (CurrLang != "RUS")
			{
				SendEvent ^+2
				SendMessage, 0x50, 0, 0x04190419,, A
			}
		}
		Return
	}

	_check_lang_by_window_id(hWnd)
	{
		if !hWnd
			Return
		WinGetClass, winClass, A
		if (winClass != "ConsoleWindowClass") || (b := SubStr(A_OSVersion, 1, 2) = "10")
		{
			if b
			{
				WinGet, consolePID, PID
				childConhostPID := this._GetCmdChildConhostPID(consolePID)
				dhw_prev := A_DetectHiddenWindows
				DetectHiddenWindows, On
				hWnd := WinExist("ahk_pid " . childConhostPID)
				DetectHiddenWindows, %dhw_prev%
			}
			threadId := DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0)
			lyt := DllCall("GetKeyboardLayout", Ptr, threadId, UInt)
			langID := Format("{:#x}", lyt)
		}
		else ; окно консольное в вин7
		{
			WinGet, dwProcessId, PID, A
			bResult := DllCall("AttachConsole", "uint", dwProcessId, "int")
			if(!bResult)
				langID := 
			else
			{
				VarSetCapacity(lyt, 16)
				DllCall("GetConsoleKeyboardLayoutName", Str, lyt)
				DllCall("FreeConsole")
				langID := "0x" . lyt
			}
		}
		if     (langID = 0x04090409) or (langID = 0x00000409) ; для английского
			Return "ENG"
		else if(langID = 0x04190419) or (langID = 0x00000419) ; для русского
			Return "RUS"
		else if(langID = 0xF0080419) or (langID = 0x00010419) ; русская машинопись
			Return "RUQ"
		else if(langID = 0xF0A80422) or (langID = 0x00020422) ; для украинского
			Return "UKR"
		else if(langID = 0x04230423) or (langID = 0x00000423) ; для белорусского
			Return "BEL"
		else if(langID = 0x043F043F) or (langID = 0x0000043F) ; для казахского
			Return "KAZ"
		else
			Return %langID%
	}

	_GetCmdChildConhostPID(CmdPID)
	{
		static TH32CS_SNAPPROCESS := 0x2, MAX_PATH := 260
		h := DllCall("CreateToolhelp32Snapshot", UInt, TH32CS_SNAPPROCESS, UInt, 0, Ptr)
		VarSetCapacity(PROCESSENTRY32, size := 4*7 + A_PtrSize*2 + (MAX_PATH << !!A_IsUnicode), 0)
		NumPut(size, PROCESSENTRY32, "UInt")
		res := DllCall("Process32First", Ptr, h, Ptr, &PROCESSENTRY32)
		while res
		{
			parentPid := NumGet(PROCESSENTRY32, 4*4 + A_PtrSize*2, "UInt")
			if (parentPid = CmdPID)
			{
				exeName := StrGet(&PROCESSENTRY32 + 4*7 + A_PtrSize*2, "CP0")
				if (exeName = "conhost.exe" && PID := NumGet(PROCESSENTRY32, 4*2, "UInt"))
					break
			}
			res := DllCall("Process32Next", Ptr, h, Ptr, &PROCESSENTRY32)
		}
		DllCall("CloseHandle", Ptr, h)
		Return PID
	}

	_check_lang()
	{
		SetFormat, Integer, H
		WinGet, WinID,, A
		CurLang := this._check_lang_by_window_id(WinID)
		;MsgBox, %CurLang%
		Return %CurLang%
	}

}
Post's attachments

Punto.ahk 7.01 kb, 7 downloads since 2019-12-16 

You don't have the permssions to download the attachments of this post.

45

Re: AHK: Еще один заменитель Punto Switcher'a

ButtonSwitchLocale:
StringCaseSense On
ControlFocus, Edit1, ahk_exe AutoHotkey.exe
Send ^{vk41}  ; "Ctrl+A"

   ;clipSave:=clipAnsi()
   send ^{Insert}
   sleep,50
StringReplace, Clipboard, Clipboard, zh , ж , All
StringReplace, Clipboard, Clipboard, kh , х , All
StringReplace, Clipboard, Clipboard, shh , щ , All
StringReplace, Clipboard, Clipboard, sch , щ , All
StringReplace, Clipboard, Clipboard, sh , ш , All
StringReplace, Clipboard, Clipboard, ju , ю , All
StringReplace, Clipboard, Clipboard, yu , ю , All
StringReplace, Clipboard, Clipboard, ja , я , All
StringReplace, Clipboard, Clipboard, ya , я , All
StringReplace, Clipboard, Clipboard, ts , ц , All
StringReplace, Clipboard, Clipboard, ch , ч , All
StringReplace, Clipboard, Clipboard, c , ц , All
StringReplace, Clipboard, Clipboard, h , х , All
StringReplace, Clipboard, Clipboard, j , й , All
StringReplace, Clipboard, Clipboard, Zh , Ж , All
StringReplace, Clipboard, Clipboard, Kh , Х , All
StringReplace, Clipboard, Clipboard, Shh , Щ , All
StringReplace, Clipboard, Clipboard, Ju , Ю , All
StringReplace, Clipboard, Clipboard, Yu , Ю , All
StringReplace, Clipboard, Clipboard, Ja , Я , All
StringReplace, Clipboard, Clipboard, Ya , Я , All
StringReplace, Clipboard, Clipboard, Ts , Ц , All
StringReplace, Clipboard, Clipboard, Ch , Ч , All
StringReplace, Clipboard, Clipboard, Sch , Щ , All
StringReplace, Clipboard, Clipboard, Sh , Ш , All
StringReplace, Clipboard, Clipboard, C , Ц , All
StringReplace, Clipboard, Clipboard, H , Х , All
StringReplace, Clipboard, Clipboard, a , а , All
StringReplace, Clipboard, Clipboard, b , б , All
StringReplace, Clipboard, Clipboard, v , в , All
StringReplace, Clipboard, Clipboard, w , в , All
StringReplace, Clipboard, Clipboard, g , г , All
StringReplace, Clipboard, Clipboard, d , д , All
StringReplace, Clipboard, Clipboard, e , е , All
StringReplace, Clipboard, Clipboard, z , з , All
StringReplace, Clipboard, Clipboard, i , и , All
StringReplace, Clipboard, Clipboard, k , к , All
StringReplace, Clipboard, Clipboard, l , л , All
StringReplace, Clipboard, Clipboard, m , м , All
StringReplace, Clipboard, Clipboard, n , н , All
StringReplace, Clipboard, Clipboard, o , о , All
StringReplace, Clipboard, Clipboard, p , п , All
StringReplace, Clipboard, Clipboard, r , р , All
StringReplace, Clipboard, Clipboard, s , с , All
StringReplace, Clipboard, Clipboard, t , т , All
StringReplace, Clipboard, Clipboard, u , у , All
StringReplace, Clipboard, Clipboard, f , ф , All
StringReplace, Clipboard, Clipboard, y , ы , All
StringReplace, Clipboard, Clipboard, ' , ь , All
StringReplace, Clipboard, Clipboard, A , А , All
StringReplace, Clipboard, Clipboard, B , Б , All
StringReplace, Clipboard, Clipboard, V , В , All
StringReplace, Clipboard, Clipboard, W , В , All
StringReplace, Clipboard, Clipboard, G , Г , All
StringReplace, Clipboard, Clipboard, D , Д , All
StringReplace, Clipboard, Clipboard, E , Е , All
StringReplace, Clipboard, Clipboard, Z , З , All
StringReplace, Clipboard, Clipboard, I , И , All
StringReplace, Clipboard, Clipboard, K , К , All
StringReplace, Clipboard, Clipboard, L , Л , All
StringReplace, Clipboard, Clipboard, M , М , All
StringReplace, Clipboard, Clipboard, N , Н , All
StringReplace, Clipboard, Clipboard, O , О , All
StringReplace, Clipboard, Clipboard, P , П , All
StringReplace, Clipboard, Clipboard, R , Р , All
StringReplace, Clipboard, Clipboard, S , С , All
StringReplace, Clipboard, Clipboard, T , Т , All
StringReplace, Clipboard, Clipboard, U , У , All
StringReplace, Clipboard, Clipboard, F , Ф , All
StringReplace, Clipboard, Clipboard, Y , Ы , All
   send +{Insert}

Return

46 (изменено: ww2, 2020-07-01 23:14:23)

Re: AHK: Еще один заменитель Punto Switcher'a

Выбирал скрипты для замены Пунто. Самые стабильные оказались  от stealzy (в 36 сообщении)
Была проблема с конвертацией выделения, но после того, как поменял SendPlay ^{Ins} на Send ^{vk43} по подсказке Автора, стало вообще все корректно.
Единственная проблема. У меня 3 установленных языка в системе (РУС,ENG,УКР). Так вот, если текст ошибочно набираю на английском, то исправление на русский влечет за собой и переключение языка на РУС.
Если ошибочно набираю на русском, то текст переводит на английский без проблем, но вот раскладку переключает на УКР. Изменение последовательности раскладок не помогает. Похоже, что переключение происходит не на конкретный язык, а на "следующий". При 2-х языках такой проблемы, естественно, не будет. Смотрел скрипты и у других Авторов, но там проблем больше. У скрипта Krot66 в какой-то момент переключение вообще перестает работать, а у toxicdream иногда "глотает" переводы строк.
Сам с AHK последний раз работал лет 12-15 назад, да и то писал простенькие скрипты, поэтому сейчас "с налету" не смогу разобраться с текстом и исправить самостоятельно.
Логику работы, на мой взгляд, следует оставить существующую (определение раскладки выделенного текста "голосованием"). Так как 95% букв в кириллических языках совпадает, то выбор раскладки выделенного текста делать между русским и английским (кириллицей-латиницей). И при конвертации с латиницы на кириллицу переключать на РУС, а при конвертации кириллицы в латиницу - принудительно в ENG вне зависимости от того какая раскладка была текущей и сколько вообще языков и раскладок в системе установлено.
На случай, если текст будет набран в украинской раскладке вместо английской, добавлю в строки Cyr и Lat 3 украинские буквы и их соответствия в латинице, чтобы предусмотреть такой вариант. Уж с этим я разберусь самостоятельно
Вариант циклического переключения языков не очень удобен (такой подход реализован в CarambaSwitcher Сергея Москалева - родоначальника PuntoSwitcher). Так как при каждой последующей конвертации текста из-за возможных знаков пунктуации текст может приобрести такой вид, что легче его перепечатать заново.
И, кстати, CarambaSwitcher тоже иногда вешает Скайп