1

Тема: AHK: Break и Shift+Break как в пунто свитчере

Пытаюсь создать скрипт выполняющий функции как в PuntoSwitcher'е конвертирующие раскладку по клавише Break и Shift+Break(конвертировать раскладку напечатанного ранее или выделенного текста соответственно).

Вот что у меня получилось:

#NoEnv
#SingleInstance,Force
SendMode,Input
SetBatchLines,-1
SetKeyDelay,10


EN=0x4090409 ;Английский
RU=0x4190419 ;Русский


+break::
break::
{
keywait,break

; Узнаем текущую раскладку в активном окне
WinGet,ID,id,A
ThreadID:=DllCall("GetWindowThreadProcessId",UInt,ID,UInt,0)
LO:=DllCall("GetKeyboardLayout",UInt,ThreadID,UInt)
if % lo=EN
  Lang=EN
else if % lo=RU
  Lang=RU

if a_thishotkey=break ; Если клавиша Break
{
clipboard:= ; Очистка буфера
Loop ; Выделение и копирование текста в буфер
{
  send,{CTRL DOWN}
  Send,{SHIFT DOWN}
  Send,{left}
  Send,{SHIFT UP}
  Send,{vk43}
  Send,{CTRL UP}
  ClipWait,1
  if ErrorLevel=0
    break
}
}
else if a_thishotkey=+break ; Если клавиша Shift+Break
{
clipboard:= ; Очистка буфера
; Копирование предварительно выделенного текста в буфер
Send,{CTRL DOWN}
Send,{vk43}
Send,{CTRL UP}
sleep,300
}

clip=%clipboard% ; Перенос текста из буфера в переменную

if lang=RU ; Обработка текста если раскладка была русская (а текс печатался английский например: РУДДЩ (HELLO))
{
SendMessage,0x50,,%EN%,,ahk_id %ID% ; Переключение на английскую раскладку для продолжения набора текста уже на английском

StringReplace,clip,clip, а , f , All
StringReplace,clip,clip, б , `, , All
StringReplace,clip,clip, в , d , All
StringReplace,clip,clip, г , u , All
StringReplace,clip,clip, д , l , All
StringReplace,clip,clip, е , t , All
StringReplace,clip,clip, ё , `` , All
StringReplace,clip,clip, ж , `; , All
StringReplace,clip,clip, з , p , All
StringReplace,clip,clip, и , b , All
StringReplace,clip,clip, й , q , All
StringReplace,clip,clip, к , r , All
StringReplace,clip,clip, л , k , All
StringReplace,clip,clip, м , v , All
StringReplace,clip,clip, н , y , All
StringReplace,clip,clip, о , j , All
StringReplace,clip,clip, п , g , All
StringReplace,clip,clip, р , h , All
StringReplace,clip,clip, с , c , All
StringReplace,clip,clip, т , n , All
StringReplace,clip,clip, у , e , All
StringReplace,clip,clip, ф , a , All
StringReplace,clip,clip, х , [ , All
StringReplace,clip,clip, ц , w , All
StringReplace,clip,clip, ч , x , All
StringReplace,clip,clip, ш , i , All
StringReplace,clip,clip, щ , o , All
StringReplace,clip,clip, ъ , ] , All
StringReplace,clip,clip, ы , s , All
StringReplace,clip,clip, ь , m , All
StringReplace,clip,clip, э , ' , All
StringReplace,clip,clip, ю , . , All
StringReplace,clip,clip, я , z , All

StringReplace,clip,clip, А , F , All ; *Проблема* Верхний регистр необрабатывается
StringReplace,clip,clip, Б , < , All
StringReplace,clip,clip, В , D , All
StringReplace,clip,clip, Г , U , All
StringReplace,clip,clip, Д , L , All
StringReplace,clip,clip, Е , T , All
StringReplace,clip,clip, Ё , ~ , All
StringReplace,clip,clip, Ж , : , All
StringReplace,clip,clip, З , P , All
StringReplace,clip,clip, И , B , All
StringReplace,clip,clip, Й , Q , All
StringReplace,clip,clip, К , R , All
StringReplace,clip,clip, Л , K , All
StringReplace,clip,clip, М , V , All
StringReplace,clip,clip, Н , Y , All
StringReplace,clip,clip, О , J , All
StringReplace,clip,clip, П , G , All
StringReplace,clip,clip, Р , H , All
StringReplace,clip,clip, С , C , All
StringReplace,clip,clip, Т , N , All
StringReplace,clip,clip, У , E , All
StringReplace,clip,clip, Ф , A , All
StringReplace,clip,clip, Х , { , All
StringReplace,clip,clip, Ц , W , All
StringReplace,clip,clip, Ч , X , All
StringReplace,clip,clip, Ш , I , All
StringReplace,clip,clip, Щ , O , All
StringReplace,clip,clip, Ъ , } , All
StringReplace,clip,clip, Ы , S , All
StringReplace,clip,clip, Ь , M , All
StringReplace,clip,clip, Э , `" , All
StringReplace,clip,clip, Ю , > , All
StringReplace,clip,clip, Я , Z , All

StringReplace,clip,clip, . , / , All
StringReplace,clip,clip, `" , @ , All
StringReplace,clip,clip, № , # , All
StringReplace,clip,clip, `; , $ , All
StringReplace,clip,clip, : , ^ , All
StringReplace,clip,clip, ? , & , All
StringReplace,clip,clip, / , | , All
}
else if lang=EN ; Обработка текста если раскладка была английская (а текс печатался русский например: YF:FNBT (НАЖАТИЕ))
{                     ; *Проблема* Слово обрабатывается только до двоеточия тоесть на выходе получается YF:АТИЕ
SendMessage,0x50,,%RU%,,ahk_id %ID%

StringReplace,clip,clip, q , й , All
StringReplace,clip,clip, w , ц , All
StringReplace,clip,clip, e , у , All
StringReplace,clip,clip, r , к , All
StringReplace,clip,clip, t , е , All
StringReplace,clip,clip, y , н , All
StringReplace,clip,clip, u , г , All
StringReplace,clip,clip, i , ш , All
StringReplace,clip,clip, o , щ , All
StringReplace,clip,clip, p , з , All
StringReplace,clip,clip, a , ф , All
StringReplace,clip,clip, s , ы , All
StringReplace,clip,clip, d , в , All
StringReplace,clip,clip, f , а , All
StringReplace,clip,clip, g , п , All
StringReplace,clip,clip, h , р , All
StringReplace,clip,clip, j , о , All
StringReplace,clip,clip, k , л , All
StringReplace,clip,clip, l , д , All
StringReplace,clip,clip, z , я , All
StringReplace,clip,clip, x , ч , All
StringReplace,clip,clip, c , с , All
StringReplace,clip,clip, v , м , All
StringReplace,clip,clip, b , и , All
StringReplace,clip,clip, n , т , All
StringReplace,clip,clip, m , ь , All

StringReplace,clip,clip, Q , Й , All ; Верхний регистр необрабатывается
StringReplace,clip,clip, W , Ц , All
StringReplace,clip,clip, E , У , All
StringReplace,clip,clip, R , К , All
StringReplace,clip,clip, T , Е , All
StringReplace,clip,clip, Y , Н , All
StringReplace,clip,clip, U , Г , All
StringReplace,clip,clip, I , Ш , All
StringReplace,clip,clip, O , Щ , All
StringReplace,clip,clip, P , З , All
StringReplace,clip,clip, A , Ф , All
StringReplace,clip,clip, S , Ы , All
StringReplace,clip,clip, D , В , All
StringReplace,clip,clip, F , А , All
StringReplace,clip,clip, G , П , All
StringReplace,clip,clip, H , Р , All
StringReplace,clip,clip, J , О , All
StringReplace,clip,clip, K , Л , All
StringReplace,clip,clip, L , Д , All
StringReplace,clip,clip, Z , Я , All
StringReplace,clip,clip, X , Ч , All
StringReplace,clip,clip, C , С , All
StringReplace,clip,clip, V , М , All
StringReplace,clip,clip, B , И , All
StringReplace,clip,clip, N , Т , All
StringReplace,clip,clip, M , Ь , All

StringReplace,clip,clip, / , . , All
StringReplace,clip,clip, `@ , `" , All
StringReplace,clip,clip, # , № , All
StringReplace,clip,clip, `$ , `; , All
StringReplace,clip,clip, ^ , : , All
StringReplace,clip,clip, & , ? , All
StringReplace,clip,clip, | , / , All
StringReplace,clip,clip, `` , ё , All
StringReplace,clip,clip, ~ , Ё , All
StringReplace,clip,clip, < , Б , All
StringReplace,clip,clip, > , Ю , All
StringReplace,clip,clip, : , Ж , All
StringReplace,clip,clip, `" , Э , All
StringReplace,clip,clip, { , Х , All
StringReplace,clip,clip, } , Ъ , All
StringReplace,clip,clip, `, , б , All
StringReplace,clip,clip, . , ю , All
StringReplace,clip,clip, ? , `, , All
StringReplace,clip,clip, `; , ж , All
StringReplace,clip,clip, ' , э , All
StringReplace,clip,clip, [ , х , All
StringReplace,clip,clip, ] , ъ , All
}

send,%clip% ; Выделенный текст заменяется обработанным
}
return

Проблемы:
1) Необрабатываются буквы в верхнем регистре, весь текст преобразуется в нижний.
2) При нажатии Break я использовал посылку Ctrl+Shift+Left чтобы выделить слово перед курсором. Но если слово содержит русские буквы: х, ъ, ж, э, б, ю; напечатанные в английской раскладке слово выделаяется только до них а не целиком.(отмечено в коментах)

Наверняка эти проблемы решаются с комощью скан кодов и DLLCALL, к сожалению я незнаю как.

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

2

Re: AHK: Break и Shift+Break как в пунто свитчере

Alectric пишет:

1) Необрабатываются буквы в верхнем регистре, весь текст преобразуется в нижний.
2) При нажатии Break я использовал посылку Ctrl+Shift+Left чтобы выделить слово перед курсором. Но если слово содержит русские буквы: х, ъ, ж, э, б, ю; напечатанные в английской раскладке слово выделаяется только до них а не целиком.(отмечено в коментах)

Наверняка эти проблемы решаются с комощью скан кодов и DLLCALL, к сожалению я незнаю как.

1) В описании же на это указано. Нужно в начале скрипта написать:

StringCaseSense On

2) посылать shift+left пока не наткнёмся на неалфавитный символ или не закончится текст.
А DllCall тут навряд ли поможет, скорее уж SendMessage smile .

3 (изменено: Alectric, 2011-11-01 20:23:24)

Re: AHK: Break и Shift+Break как в пунто свитчере

StringCaseSense On

Пробовал. Работает через раз и иногда наоборот маленькие буквы делает заглавными. Наверно есть зависимость от последовательности обработки символов StringReplace'ом
А с определением символа(пробела) попробую... но сомневаюсь. Подскажите пожалуйста как определить когда слово кончится
Да и SendMessage посылать в Edit текстового редактора с 1000ми строками текста страшновато както... Или я чето нето говорю?...

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

4

Re: AHK: Break и Shift+Break как в пунто свитчере

Alectric пишет:

Пробовал. Работает через раз и иногда наоборот маленькие буквы делает заглавными. Наверно есть зависимость от последовательности обработки символов StringReplace'ом

Ну вообще не очень рационально его тут использовать. Я бы предложил массивы(только в AutoHotkey_L) или их самопальные аналоги smile. Приведённый код у меня очень некорректно работает, но регистры не путает smile.

Alectric пишет:

А с определением символа(пробела) попробую... но сомневаюсь. Подскажите пожалуйста как определить когда слово кончится

Когда длина строки не изменится после копирования.

Alectric пишет:

Да и SendMessage посылать в Edit текстового редактора с 1000ми строками текста страшновато както... Или я чето нето говорю?...

Ну точно не страшнее чем имитировать ввод с клавиатуры и использовать буфер обмена для анализа и редактирования введённого текста smile . Список команд для edit'ов можно посмотреть здесь. Часть функционала предоставляет ControlGet.

5

Re: AHK: Break и Shift+Break как в пунто свитчере

Когда длина строки не изменится после копирования.

Исключено. Строка продолжит увеличиватся если слово находится в предложении.

Спасибо за ссылки буду искать варианты...

Или просто подскажите в виде кода как мне взять в переменную последнее слово в Editе и после обработки заменить его с помощью SendMessage и ControlGet.

winget,id,id,A
MouseGetPos,,,,focus
ControlGetText,text,%focus%,ahk_id %id%
; Что дальше?!?

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

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

6

Re: AHK: Break и Shift+Break как в пунто свитчере

Как-то всё сложно у вас. smile Вот для выделенного слова в блокноте по F11:

Cyr = ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю
Lat = QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>qwertyuiop[]asdfghjkl;'zxcvbnm,.

CyrArray := [], LatArray := []

Loop, parse, Cyr
   CyrArray[A_Index] := A_LoopField
   
Loop, parse, Lat
   LatArray[A_Index] := A_LoopField
   
#IfWinActive, ahk_class Notepad
F11::
   WinWait, ahk_class Notepad
   
   VarSetCapacity(buf1, 4), VarSetCapacity(buf2, 4)
   SendMessage, EM_GETSEL := 0xB0, &buf1, &buf2, Edit1
   StartPos := NumGet(buf1) + 1
   EndPos := NumGet(buf2) + 1
   
   ControlGetText, Text, Edit1
   SelText := SubStr(Text, StartPos, EndPos - StartPos)
   
   Loop, parse, SelText
   {
      for k, v in CyrArray
         if (A_LoopField == v)
            NewText .= LatArray[k], found := 1
      
      if !found
         for k, v in LatArray
            if (A_LoopField == v)
               NewText .= CyrArray[k], found := 1
      
      if !found
         NewText .= A_LoopField
         
      found =
   }
   SendMessage, EM_REPLACESEL := 0xC2, 0, &NewText, Edit1
   NewText =
   Return

Подумаю, как конвертировать последнее написанное слово.

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

7

Re: AHK: Break и Shift+Break как в пунто свитчере

Alectric пишет:

Исключено. Строка продолжит увеличиватся если слово находится в предложении.

Я думал имеется ввиду достижение первого символа контрола. Иначе очевидно- нужно составить алфавит из допустимых символов.

Alectric пишет:

Или просто подскажите в виде кода как мне взять в переменную последнее слово в Editе и после обработки заменить его с помощью SendMessage и ControlGet.

winget,id,id,A
MouseGetPos,,,,focus
ControlGetText,text,%focus%,ahk_id %id%
; Что дальше?!?

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

Ну буфер универсальнее, ведь сообщения EM_* обрабатываются только edit'ом и richedit'ом. А выделить последнее слово очень просто при помощи регулярных выражений(код лучше оптимизировать smile):

f10::
   winget id,id,A
   ControlGetFocus cont, ahk_id %id%
   if(!RegExMatch(cont, "i)edit\d+")) ; тут проверяем класс
   {
      msgbox не тот контрол
	  return
   }
   ControlGet strnum, CurrentLine, , %cont%, ahk_id %id% ; получили номер выбранной строки
   ControlGet str, Line, %strnum%, %cont%, ahk_id %id% ; получили саму строку
   ControlGet colnum, CurrentCol , , %cont%, ahk_id %id% ; получаем расположение курсора
   if(!RegExMatch(SubStr(str, colnum-1, 1), "[`~a-zA-Z\[\]{};:'\x22<>,\.]+"))
   {
      msgbox слева от курсора недопустимый символ
	  return
   }
   i:=1
   loop
   {
      FoundPos := RegExMatch(str, "[`~a-zA-Z\[\]{};:'\x22<>,\.]+", res, i) ;
      if(!FoundPos || FoundPos+StrLen(res)>=colnum)
         break
      i:=FoundPos+StrLen(res)
   }
   msgbox %res%
return

В этом примере по нажатию F10 выводится сообщение с последним словом, которое было набрано русскими буквами, но на английской раскладке. "Последним словом" здесь является слово, которому принадлежит буква слева от курсора.

teadrinker пишет:

Как-то всё сложно у вас.

Ну вообще-то примерно это я и предлагал. Только я не был уверен, что используется именно AutoHotkey_L и алгоритм я бы иной выбрал smile.

8

Re: AHK: Break и Shift+Break как в пунто свитчере

Если есть выделенный текст, то по F11 меняет раскладку выделенного текста, если нет — слова слева от каретки до пробела. Меняет локаль на основе последнего найденного символа — если латиница — на русскую, кириллица — на английскую. Работает с любыми edit-контролами, принимающими сообщения для стандартного Edit-контрола. Работа с браузером немного сложнее, но теоретически тоже возможна через javascript или посылы клавиш.

Cyr = ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю
Lat = QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>qwertyuiop[]asdfghjkl;'zxcvbnm,.

CyrArray := [], LatArray := []

Loop, parse, Cyr
   CyrArray[A_Index] := A_LoopField
   
Loop, parse, Lat
   LatArray[A_Index] := A_LoopField
   
#If EditControl := EditControlFocused()
F11::
   VarSetCapacity(buf1, 4), VarSetCapacity(buf2, 4)
   SendMessage, EM_GETSEL := 0xB0, &buf1, &buf2, % EditControl, A
   StartPos := NumGet(buf1)
   EndPos := NumGet(buf2)
   
   ControlGetText, Text, % EditControl, A
   if (StartPos = EndPos)
   {
      SubText := SubStr(Text, 1, EndPos)
      if RegExMatch(SubText, "[ \t]$")
         Return
      SelText := RegExReplace(SubText, "s).*\s(\S+).*", "$1")
      Start := EndPos - StrLen(SelText)
   }
   else
      SelText := SubStr(Text, StartPos + 1, EndPos - StartPos)
   
   Loop, parse, SelText
   {
      for k, v in CyrArray
         if (A_LoopField == v)
            NewText .= LatArray[k], lastfound := found := 1
      
      if !found
         for k, v in LatArray
            if (A_LoopField == v)
               NewText .= CyrArray[k], lastfound := found := 2
      
      if !found
         NewText .= A_LoopField
         
      found =
   }
   
   if (StartPos = EndPos)
   {
      SendMessage, EM_SETSEL := 0xB1, Start, EndPos, % EditControl, A
      WordLen1 := WordPos1 := ""
   }
   
   SendMessage, EM_REPLACESEL := 0xC2, 1, &NewText, % EditControl, A
   NewText =
   
;переключаем раскладку   
   VarSetCapacity(List, 8)
   DllCall("GetKeyboardLayoutList", Int, 2, UInt, &List)
   Locale1 := NumGet(List)
   If SubStr(Locale2 := NumGet(List, 4), -3) = 0409
      En := Locale2, Ru := Locale1
   Else
      En := Locale1, Ru := Locale2

   WinGet, WinID,, A
   ThreadID := DllCall("GetWindowThreadProcessId", UInt, WinID, UInt, 0)
   InputLocaleID := DllCall("GetKeyboardLayout", UInt, ThreadID, UInt)

   SendMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, lastfound = 2 ? Ru : En,, A
   Return
   
EditControlFocused()
{
   ControlGetFocus, Control, A
   StringCaseSense, Off
   if InStr(Control, "Edit")
      Return Control
}
Александр_ пишет:

и алгоритм я бы иной выбрал

Хотелось сделать без использования буфера обмена и посылов клавиш, ибо ненадёжно.

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

9

Re: AHK: Break и Shift+Break как в пунто свитчере

teadrinker пишет:

Хотелость сделать без использования буфера обмена и посылов клавиш, ибо ненадёжно.

Я про алгоритм парсинга говорил.

teadrinker пишет:

Работает с любыми edit-контролами, принимающими сообщения для стандартного Edit-контрола.
...

if InStr(Control, "Edit")

smile

teadrinker пишет:

Работа с браузером немного сложнее, но теоретически тоже возможна через javascript или посылы клавиш.

А у тебя не возникло желание punto switcher или аналоги поковырять? Лично у меня- нет big_smile.

10

Re: AHK: Break и Shift+Break как в пунто свитчере

Александр_ пишет:
teadrinker пишет:

Работает с любыми edit-контролами, принимающими сообщения для стандартного Edit-контрола.
...

if InStr(Control, "Edit")

smile

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

Александр_ пишет:

А у тебя не возникло желание punto switcher или аналоги поковырять? Лично у меня- нет big_smile.

Да нет, я так, ради интереса попробовал. smile

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

11

Re: AHK: Break и Shift+Break как в пунто свитчере

teadrinker пишет:

Хотелось сделать без использования буфера обмена и посылов клавиш, ибо ненадёжно.

Хотя, присмотревшись к работе punto switcher'а, кажется, он работает именно методом посыла клавиш.

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

12

Re: AHK: Break и Shift+Break как в пунто свитчере

teadrinker пишет:

Хотя, присмотревшись к работе punto switcher'а, кажется, он работает именно методом посыла клавиш.

Ага- [link]. Цитата:

http://punto.yandex.ru/faq пишет:

Почему конвертация выделенного текста не работает в некоторых программах?
    Некоторые программы не поддерживают копирование в буфер обмена по команде Ctrl+C и вставку — по Ctrl+V. Если это возможно, настройте программу, которую вы используете, для работы с данными комбинациями.

Но всех вопросов это не снимает smile

13

Re: AHK: Break и Shift+Break как в пунто свитчере

Важная тема, интересный вопрос.
В ANSI версии ahk с функцией исправления неверной раскладки при вводе качественно справлялся этот скрипт.
Аналогов в коллекции скриптов не нашел в своё время, да и сейчас использую его в скомпилированном виде.
Из явных недостатков — не обрабатывает «ё» и соответственно «`».

14

Re: AHK: Break и Shift+Break как в пунто свитчере

Попозже исправлю.

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

15

Re: AHK: Break и Shift+Break как в пунто свитчере

teadrinker пишет:

Хотя, присмотревшись к работе punto switcher'а, кажется, он работает именно методом посыла клавиш.

Сие хорошо видно при попытке конвертации с помощью PS текста в окне консоли: в окно приходит «^V» («Ctlr-V»).

16

Re: AHK: Break и Shift+Break как в пунто свитчере

Спасибо за ответы!

Off:
Какбудто в густой лес зашел... Такие сложные коды... Мне еще далеко до Вас...

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

17 (изменено: Alectric, 2011-11-02 19:24:54)

Re: AHK: Break и Shift+Break как в пунто свитчере

Вот в таком "страшном" виде все работает как положенно, но немного дольше чем надо:

#NoEnv
#SingleInstance,Force
SetBatchLines,-1
SetKeyDelay,100
process,priority,,realtime

EN=0x4090409
RU=0x4190419
Cyr = ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю.,
Lat = QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>qwertyuiop[]asdfghjkl;'zxcvbnm,./?
; "
CyrArray := [], LatArray := []
Loop, parse, Cyr
   CyrArray[A_Index] := A_LoopField
Loop, parse, Lat
   LatArray[A_Index] := A_LoopField

+break::
break::
{
keywait,break
ClipSaved:=ClipboardAll
WinGet,ID,id,A
ThreadID:=DllCall("GetWindowThreadProcessId",UInt,ID,UInt,0)
LO:=DllCall("GetKeyboardLayout",UInt,ThreadID,UInt)
if % lo=EN
  Lang=EN
else if % lo=RU
  Lang=RU
if lang=RU
{
  SendMessage,0x50,,%EN%,,ahk_id %ID%
  tooltip,Английский,x+10,y-20,3
}
else if lang=EN
{
  SendMessage,0x50,,%RU%,,ahk_id %ID%
  tooltip,Русский,x+10,y-20,3
}
SetTimer,REMOVE_TOOLTIP,1000

if a-thishotkey=break
{
  clipboard:=
  gosub,copy
  StringReplace,clipboard,clipboard,`n,,All
}
else if a_thishotkey=+break
{
  clipboard:=
  Loop
  {
    Send,{CTRL DOWN}
    Send,{vk43}
    Send,{CTRL UP}
    ClipWait,1
    if ErrorLevel=0
      break
  }
}

Seltext=%clipboard%

   Loop, parse, SelText
   {
      for k, v in CyrArray
         if (A_LoopField == v)
            NewText .= LatArray[k], lastfound := found := 1

      if !found
         for k, v in LatArray
            if (A_LoopField == v)
               NewText .= CyrArray[k], lastfound := found := 2

      if !found
         NewText .= A_LoopField

      found =
   }

   send,%NewText%
   NewText=
   Clipboard:=ClipSaved
   ClipSaved=
}
return


REMOVE_TOOLTIP:
   SetTimer,REMOVE_TOOLTIP,off
   tooltip,,,,3
   return


copy:
{
loop
{
  StringLen,cliplen,clipboard
  if % old_cliplen=cliplen
    return
  old_cliplen:=cliplen

  if clipboard not contains %a_space%,`n
  {
    Loop
    {
      send,{CTRL DOWN}
      sleep,10
      Send,{SHIFT DOWN}
      sleep,10
      Send,{left}
      sleep,10
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      sleep,10
      ClipWait,1
      if ErrorLevel=0
        break
    }
  }
  else
  {
    Loop
    {
      send,{CTRL DOWN}
      sleep,10
      Send,{SHIFT DOWN}
      sleep,10
      Send,{right}
      sleep,10
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      sleep,10
      ClipWait,1
      if ErrorLevel=0
        return
    }
  }
}
}
return

А можно ли както вытащить последнее набранное слово с помощью этого?:

#persistent
;#notrayicon
SetBatchLines, -1

logpath=c:\log.log

hHookKeybd:=DllCall("SetWindowsHookEx",Int,WH_KEYBOARD_LL:=13,UInt,RegisterCallback("LowLevelKeyboardProc","Fast"),UInt,DllCall("GetModuleHandle",Int,0),UInt,0)
OnExit,Exit

Exit:
DllCall("UnhookWindowsHookEx",UInt,hHookKeybd)
ExitApp

LowLevelKeyboardProc(nCode,wParam,lParam)
{
global
;Critical

if (wParam=0x100)
{
  vk:=NumGet(lParam+0)
  sc:=NumGet(lParam+0,4)
WinGetTitle,titl,A
Char:=GetCharOfKey(vk,sc)
fileappend,%Char%,%logpath%
}
Return DllCall("CallNextHookEx",UInt,0,Int,nCode,UInt,wParam,UInt,lParam)
}


GetCharOfKey(vk,sc)
{
ThreadID := DllCall("GetWindowThreadProcessId",UInt,WinExist("A"),UInt,0)
InputLocaleID := DllCall("GetKeyboardLayout",UInt,ThreadID)
VarSetCapacity(KeyState, 256)
DllCall("AttachThreadInput",UInt,ThreadID,UInt,DllCall("GetCurrentThreadId"),UInt,1)
DllCall("GetKeyboardState",UInt,&KeyState)
VarSetCapacity(Buffer,2)
A_IsUnicode ? DllCall("ToUnicodeEx",UInt,vk,UInt,sc,UInt,&KeyState,Str,Buffer,Int,1,UInt,0,UInt,InputLocaleID) : DllCall("ToAsciiEx",UInt,vk,UInt,sc,UInt,&KeyState,Str,Buffer,UInt,0,UInt,InputLocaleID)
Return Buffer
}

PS: Разумеется без использования fileappend.

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

18

Re: AHK: Break и Shift+Break как в пунто свитчере

Alectric пишет:

А можно ли както вытащить последнее набранное слово с помощью этого?:

Можно с помощью этого.

Вариант с посылом клавиш, по F11 меняет раскладку выделенного, если есть, если нет — последнего слова слева от каретки до пробела, таба, переноса строки или начала текста. Также меняет раскладку клавиатуры на основе последнего найденного символа. Обрабатывает "Ё" smile

SetBatchLines, -1
SetKeyDelay, 0

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

CyrArray := [], LatArray := []

Loop, parse, Cyr
   CyrArray[A_Index] := A_LoopField

Loop, parse, Lat
   LatArray[A_Index] := A_LoopField

F11::
   TempClipboard := ClipboardAll
   Clipboard =
   SendInput, ^{vk43}
   ClipWait, 0
   SelText := ErrorLevel ? GetWord() : Clipboard
   
   Loop, parse, SelText
   {
      found =
      for k, v in CyrArray
         if (A_LoopField == v)
            NewText .= LatArray[k], lastfound := found := 1

      if !found
         for k, v in LatArray
            if (A_LoopField == v)
               NewText .= CyrArray[k], lastfound := found := 2

      if !found
         NewText .= A_LoopField
   }
   Clipboard := NewText
   SendInput, ^{vk56}
   Clipboard := TempClipboard
   NewText =
   
;переключаем раскладку
   VarSetCapacity(List, 8)
   DllCall("GetKeyboardLayoutList", Int, 2, UInt, &List)
   Locale1 := NumGet(List)
   If SubStr(Locale2 := NumGet(List, 4), -3) = 0409
      En := Locale2, Ru := Locale1
   Else
      En := Locale1, Ru := Locale2

   WinGet, WinID,, A
   ThreadID := DllCall("GetWindowThreadProcessId", UInt, WinID, UInt, 0)
   InputLocaleID := DllCall("GetKeyboardLayout", UInt, ThreadID, UInt)

   SendMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, lastfound = 2 ? Ru : En,, A
   Return
   
   
GetWord()
{
   While A_Index < 100
   {
      Clipboard =
      SendInput, +{Left}
      SendInput, ^{vk43}
      ClipWait, 500
      if ErrorLevel
         Return
      
      Len := StrLen(Clipboard)
      if (Len = PrevLen)
         Return Clipboard
      PrevLen := Len
      s := SubStr(Clipboard, 1, 1)
      if (s = A_Space || s = A_Tab || s = "`n" || s = "`r")
      {
         SendInput, +{Right}
         s := SubStr(Clipboard, 1, 2)
         Return SubStr(ClipBoard, RegExMatch(s, "[\n\r]{2}") ? 3 : 2)
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

19

Re: AHK: Break и Shift+Break как в пунто свитчере

Работае, но с глюками.

Поставил вместо:   

SendInput, ^{vk56}

Вот это
 

 send,%NewText%

А иначе периодически вставляется старый буфер.

Спасибо за помощь.

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

20

Re: AHK: Break и Shift+Break как в пунто свитчере

Немного глючно, потом отредактирую smile

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

21 (изменено: Alectric, 2011-11-02 20:20:18)

Re: AHK: Break и Shift+Break как в пунто свитчере

В какойто момент перестает работать. Застрявает на

ClipWait,500

Сделал

ClipWait,1

Попробовал сделать выделение не по символу а по слову... неработает. Мой вариант в этом плане быстрее отрабатывает.

      SendInput, ^+{Left}

Off: Всеравно красивее чем мои скрипты. smile

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

22 (изменено: Alectric, 2011-11-02 20:34:56)

Re: AHK: Break и Shift+Break как в пунто свитчере

Немного подправил свой код. Впринципе это готовый рабочий вариант:

#NoEnv
#SingleInstance,Force
SetBatchLines,-1
SetKeyDelay,100
process,priority,,realtime

EN=0x4090409
RU=0x4190419
Cyr = ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю.,
Lat = QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>qwertyuiop[]asdfghjkl;'zxcvbnm,./?
; "
CyrArray := [], LatArray := []
Loop, parse, Cyr
   CyrArray[A_Index] := A_LoopField
Loop, parse, Lat
   LatArray[A_Index] := A_LoopField

+break::
break::
{
keywait,break
ClipSaved:=ClipboardAll
WinGet,ID,id,A
ThreadID:=DllCall("GetWindowThreadProcessId",UInt,ID,UInt,0)
LO:=DllCall("GetKeyboardLayout",UInt,ThreadID,UInt)
if % lo=EN
  Lang=EN
else if % lo=RU
  Lang=RU
if lang=RU
{
  SendMessage,0x50,,%EN%,,ahk_id %ID%
  tooltip,Английский,x+10,y-20,3
}
else if lang=EN
{
  SendMessage,0x50,,%RU%,,ahk_id %ID%
  tooltip,Русский,x+10,y-20,3
}
SetTimer,REMOVE_TOOLTIP,1000

if a-thishotkey=break
{
  clipboard:=
  gosub,copy
  StringReplace,clipboard,clipboard,`n,,All
}
else if a_thishotkey=+break
{
  clipboard:=
  Loop
  {
    Send,{CTRL DOWN}
    Send,{vk43}
    Send,{CTRL UP}
    ClipWait,1
    if ErrorLevel=0
      break
  }
}

Seltext=%clipboard%

   Loop, parse, SelText
   {
      for k, v in CyrArray
         if (A_LoopField == v)
            NewText .= LatArray[k], lastfound := found := 1

      if !found
         for k, v in LatArray
            if (A_LoopField == v)
               NewText .= CyrArray[k], lastfound := found := 2

      if !found
         NewText .= A_LoopField

      found =
   }

   send,%NewText%
   NewText=
   Clipboard:=ClipSaved
   ClipSaved=
}
return


REMOVE_TOOLTIP:
   SetTimer,REMOVE_TOOLTIP,off
   tooltip,,,,3
   return


copy:
{
loop
{
  StringLen,cliplen,clipboard
  if % old_cliplen=cliplen
    return
  old_cliplen:=cliplen

  if clipboard not contains %a_space%,`n
  {
    Loop
    {
      send,{CTRL DOWN}
      Send,{SHIFT DOWN}
      Send,{left}
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        break
    }
  }
  else
  {
    Loop
    {
      send,{CTRL DOWN}
      Send,{SHIFT DOWN}
      Send,{right}
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        return
    }
  }
}
}
return

Результат:
При нажатии Break конвертируется слово перед текстовым курсором. (Хотя в PuntoSwitcherе конвертируется последний набранный текст а не слово)
При выделении текста и нажатии Shift+Break конвертируется выделенный текст.

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

23 (изменено: creature.ws, 2011-11-02 21:17:46)

Re: AHK: Break и Shift+Break как в пунто свитчере

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

24 (изменено: Alectric, 2011-11-02 21:44:21)

Re: AHK: Break и Shift+Break как в пунто свитчере

У меня нормально все работает...
Возможно у Вас конфликтует с другим скриптом или с оригинальным PuntoSwitcherом.

Хотя наверно проблема сдесь:

if clipboard not contains %a_space%,`n
  {
    Loop
    {
      send,{CTRL DOWN}
      Send,{SHIFT DOWN}
      Send,{left}
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        break
    }
  }
  else
  {
    Loop
    {
      send,{CTRL DOWN}
      Send,{SHIFT DOWN}
      Send,{right}
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        return
    }
  }

Надо так:

if clipboard not contains %a_space%,`n
  {
    Loop
    {
      send,{CTRL DOWN}
      sleep,10
      Send,{SHIFT DOWN}
      sleep,10
      Send,{left}
      sleep,10
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        break
    }
  }
  else
  {
    Loop
    {
      send,{CTRL DOWN}
      sleep,10
      Send,{SHIFT DOWN}
      sleep,10
      Send,{right}
      sleep,10
      Send,{SHIFT UP}
      sleep,10
      Send,{vk43}
      sleep,10
      Send,{CTRL UP}
      ClipWait,1
      if ErrorLevel=0
        return
    }
  }

Более стабильно работает.

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

25

Re: AHK: Break и Shift+Break как в пунто свитчере

С внесёнными исправлениями работает как и прежде (за исключением скорости ввода текста smile)
Нет, иных скриптов на момент тестирования запущено небыло, как и PuntoSwitcherа.