1

Тема: AHK: Смена раскладки написанного текста

Работает под AHK_L.
Скрипт меняет раскладку выделенного текста или последнего слова слева от каретки по Shift + Break, как программа Punto Switcher.

+Break::SwitchKeysLocale()

SwitchKeysLocale()
{
   Critical
   SetBatchLines, -1
   SetKeyDelay, 0

   TempClipboard := ClipboardAll
   Clipboard =
   SendInput, ^{vk43}   ; Ctrl + C
   ClipWait, 0
; если буфер обмена пуст (ничего не выделено), определяем и выделяем
; с помощью ф-ции GetWord() последнее слово слева от курсора
   SelText := ErrorLevel ? GetWord() : Clipboard
   pResult := ConvertText(SelText)   ; получаем конвертированный текст и раскладку последней найденной буквы

   Clipboard := StrGet(pResult + A_PtrSize)
   SendInput, ^{vk56}   ; Ctrl + V
; переключаем раскладку клавиатуры в зависимости от раскладки последней найденной буквы
   Sleep, 200
   SwitchLocale(NumGet(pResult+0, "UInt"))
   Sleep, 200
   Clipboard := TempClipboard
}

GetWord()
{
   While A_Index < 10
   {
      Clipboard =
      SendInput, ^+{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if RegExMatch(Clipboard, "P).*([ \t])", Found)
      {
         SendInput, ^+{Right}
         Return SubStr(Clipboard, FoundPos1 + 1)
      }

      PrevClipboard := Clipboard
      Clipboard =
      SendInput, +{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if (StrLen(Clipboard) = StrLen(PrevClipboard))
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         if (StrLen(Clipboard) = StrLen(PrevClipboard))
            Return Clipboard
         Else
         {
            SendInput, +{Right 2}
            Return PrevClipboard
         }
      }

      SendInput, +{Right}

      s := SubStr(Clipboard, 1, 1)
      if s in %A_Space%,%A_Tab%,`n,`r
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         Return Clipboard
      }
   }
}

ConvertText(Text)
{
   static Result

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

   Loop, parse, Text
   {
      found =
      if found := InStr(Lat, A_LoopField, 1)
         NewText .= SubStr(Cyr, found, 1), lastfound := 2

      if !found
         if found := InStr(Cyr, A_LoopField, 1)
            NewText .= SubStr(Lat, found, 1), lastfound := 1

      if !found
         NewText .= A_LoopField
   }
   VarSetCapacity(Result, A_PtrSize + StrPut(NewText)*(A_IsUnicode ? 2 : 1))
   NumPut(lastfound, &Result), StrPut(NewText, &Result + A_PtrSize)
   Return &Result
}

SwitchLocale(lastfound)
{
   SetFormat, IntegerFast, H
   VarSetCapacity(List, A_PtrSize*2)
   DllCall("GetKeyboardLayoutList", Int, 2, Ptr, &List)
   Locale1 := NumGet(List)
   b := SubStr(Locale2 := NumGet(List, A_PtrSize), -3) = 0409
   En := b ? Locale2 : Locale1
   Ru := b ? Locale1 : Locale2
   SendMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, lastfound = 1 ? En : Ru,, A
}

Тема для обсуждения.

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

2

Re: AHK: Смена раскладки написанного текста

Новая версия. Добавлено переключение регистра выделенного текста или последнего слова слева от каретки (введённого с ошибочно включенным CapsLock).

^PGDN::SwitchKeysLocale()   ; Ctrl + Page Down
+PGDN::SwitchRegistr()      ; Shift + Page Down

SwitchKeysLocale()
{
   SelText := GetWord(TempClipboard) 
   Clipboard := ConvertText(SelText, Layout)
   SendInput, ^{vk56} 
   Sleep, 50
   SwitchLocale(Layout)
   Sleep, 50
   Clipboard := TempClipboard
}

SwitchRegistr()
{
   SelText := GetWord(TempClipboard)
   Clipboard := ConvertRegistr(SelText) 
   SendInput, ^{vk56}   ; Ctrl + V 
   Sleep, 200 
   Clipboard := TempClipboard
}

GetWord(ByRef TempClipboard)
{
   Critical
   SetBatchLines, -1
   SetKeyDelay, 0
   
   TempClipboard := ClipboardAll
   Clipboard =
   SendInput, ^{vk43}
   ClipWait, 0
   if !ErrorLevel
      Return Clipboard
   
   While A_Index < 10
   {
      Clipboard =
      SendInput, ^+{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if RegExMatch(Clipboard, "P)([ \t])", Found)
      {
         SendInput, ^+{Right}
         Return SubStr(Clipboard, FoundPos1 + 1)
      }

      PrevClipboard := Clipboard
      Clipboard =
      SendInput, +{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if (StrLen(Clipboard) = StrLen(PrevClipboard))
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         if (StrLen(Clipboard) = StrLen(PrevClipboard))
            Return Clipboard
         Else
         {
            SendInput, +{Right 2}
            Return PrevClipboard
         }
      }

      SendInput, +{Right}

      s := SubStr(Clipboard, 1, 1)
      if s in %A_Space%,%A_Tab%,`n,`r
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         Return Clipboard
      }
   }
}

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

   RegExReplace(Text, "i)[A-Z]", "", LatCount)
   RegExReplace(Text, "i)[А-ЯЁ]", "", CyrCount)
   CurrentLayout := LatCount > CyrCount ? "Lat" : "Cyr"
   OppositeLayout := LatCount > CyrCount ? "Cyr" : "Lat"

   Loop, parse, Text
      NewText .= (found := InStr(%CurrentLayout%, A_LoopField, 1)) 
         ? SubStr(%OppositeLayout%, found, 1) : A_LoopField
   Return NewText
}

SwitchLocale(Layout)
{
   ControlGetFocus, CtrlFocus, A
   PostMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, Layout = "Lat" ? 0x4090409 : 0x4190419, %CtrlFocus%, A
}

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
}

Функция ConvertRegistr(), доработка ConvertText()serzh82saratov
Функция SwitchLocale()YMP
Тема для обсуждения

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

3 (изменено: teadrinker, 2016-08-10 02:45:24)

Re: AHK: Смена раскладки написанного текста

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

Скрипт меняет раскладку выделенного текста или последнего слова слева от каретки по Ctrl + Page Down, как программа Punto Switcher, по Shift + Page Down переключает регистр (когда текст введён с ошибочно включенным CapsLock).

^PGDN::SwitchKeysLocale()   ; Ctrl + Page Down
+PGDN::SwitchRegistr()      ; Shift + Page Down

SwitchKeysLocale()
{
   SelText := GetWord(TempClipboard) 
   Clipboard := ConvertText(SelText, Layout)
   SendInput, ^{vk56}   ; Ctrl + V
   Sleep, 50
   SwitchLocale(Layout)
   Sleep, 50
   Clipboard := TempClipboard
}

SwitchRegistr()
{
   SelText := GetWord(TempClipboard)
   Clipboard := ConvertRegistr(SelText) 
   SendInput, ^{vk56}   ; Ctrl + V 
   Sleep, 200 
   Clipboard := TempClipboard
}

GetWord(ByRef TempClipboard)
{
   SetBatchLines, -1
   SetKeyDelay, 0
   
   TempClipboard := ClipboardAll
   Clipboard =
   SendInput, ^{vk43}
   Sleep, 100
   if (Clipboard != "")
      Return Clipboard
   
   While A_Index < 10
   {
      SendInput, ^+{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if RegExMatch(Clipboard, "P)([ \t])", Found) && A_Index != 1
      {
         SendInput, ^+{Right}
         Return SubStr(Clipboard, FoundPos1 + 1)
      }

      PrevClipboard := Clipboard
      Clipboard =
      SendInput, +{Left}^{vk43}
      ClipWait, 1
      if ErrorLevel
         Return

      if (StrLen(Clipboard) = StrLen(PrevClipboard))
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         if (StrLen(Clipboard) = StrLen(PrevClipboard))
            Return Clipboard
         Else
         {
            SendInput, +{Right 2}
            Return PrevClipboard
         }
      }

      SendInput, +{Right}

      s := SubStr(Clipboard, 1, 1)
      if s in %A_Space%,%A_Tab%,`n,`r
      {
         Clipboard =
         SendInput, +{Left}^{vk43}
         ClipWait, 1
         if ErrorLevel
            Return

         Return Clipboard
      }
      Clipboard =
   }
}

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

   RegExReplace(Text, "i)[A-Z@#\$\^&\[\]'`\{}]", "", LatCount)
   RegExReplace(Text, "i)[А-ЯЁ№]", "", CyrCount)
   
   if (LatCount != CyrCount)  {
      CurrentLayout := LatCount > CyrCount ? "Lat" : "Cyr"
      OppositeLayout := LatCount > CyrCount ? "Cyr" : "Lat"
   }
   else  {
      threadId := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
      landId := DllCall("GetKeyboardLayout", Ptr, threadId, Ptr) & 0xFFFF
      if (landId = 0x409)
         CurrentLayout := "Lat", OppositeLayout := "Cyr"
      else
         CurrentLayout := "Cyr", OppositeLayout := "Lat"
   }
   Loop, parse, Text
      NewText .= (found := InStr(%CurrentLayout%, A_LoopField, 1)) 
         ? SubStr(%OppositeLayout%, found, 1) : A_LoopField
   Return NewText
}

SwitchLocale(Layout)
{
   ControlGetFocus, CtrlFocus, A
   PostMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, Layout = "Lat" ? 0x4090409 : 0x4190419, %CtrlFocus%, A
}

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
}

Функция ConvertRegistr(), доработка ConvertText()serzh82saratov
Функция SwitchLocale()YMP
Тема для обсуждения

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