101 (изменено: DaVinchi, 2013-05-20 20:24:39)

Re: AHK: Переводчик онлайн

teadrinker пишет:

Хм, тогда ты единственный, у кого такая проблема. В строке никакой ошибки нет, возможно, версия AHK старая?

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

upd. Действительно, скачал новее версию, все работает супер.

Сейчас попробовал изменить код как я думал, но ничего не вышло. Может быть вы подскажете, как сделать, что бы окно не появлялось и продолжало висеть только в трее?

102

Re: AHK: Переводчик онлайн

А что значит «продолжало висеть в трее»?

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

103

Re: AHK: Переводчик онлайн

teadrinker пишет:

А что значит «продолжало висеть в трее»?

Это значит, что о работе скрипта должен говорить только значок возле часов и переведенный текст, который будет вставлен при помощи ctrl+alt+v.
Т.е. само ГУИ не появится, пока не будет вызвано кликом по значку.

104

Re: AHK: Переводчик онлайн

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


Menu, Tray, Add, Всегда спрятано, AlwaysHidden
if AlwaysHidden

Но на этом мои идеи закончились. И как дальше реализовать это, я не могу придумать.

105

Re: AHK: Переводчик онлайн

Делаешь поиск по скрипту на фразу "Gui, Show". Их там 3 таких.  - Коментируешь.

в теле процедуры "ShowTranslation(SourceText, TransText, from, to)" вставляешь строку "Clipboard:=TransText" в самом начале. Все.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

106

Re: AHK: Переводчик онлайн

Mikki пишет:

Делаешь поиск по скрипту на фразу "Gui, Show". Их там 3 таких.  - Коментируешь.

в теле процедуры "ShowTranslation(SourceText, TransText, from, to)" вставляешь строку "Clipboard:=TransText" в самом начале. Все.

Кхм... Срабатывает только 1 раз, после нужно перезапускать скрипт.
Я так понимаю нужно как то сделать, что бы после вставки с буфера обмена скрипт перезапускался?

107

Re: AHK: Переводчик онлайн

Такс. Странно. Но вот пол часа прошло, я пробую скрипт и все прекрасно работает и без каких либо шаманств с бубном..

108 (изменено: serzh82saratov, 2013-05-22 22:49:07)

Re: AHK: Переводчик онлайн

DaVinchi
Может проще выделить для себя только функции перевода:

+ открыть спойлер


#NoEnv
#SingleInstance, force
SetBatchLines, -1

global  MAX_URL_LENGTH := 2076

SourseText =
(
Такс. Странно. 
Но вот пол часа прошло, я пробую скрипт и все прекрасно работает и без каких либо шаманств с бубном..
)

msgbox % Translate(RegExReplace(SourseText, "\R", "`r`n"), "ru", "en")

Translate(Sourse, _from, _to)
{
    if !Ping("translate.google.com")
    {
        MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
        Return
    } 
    
    if (_from = "" && _to = "")
    {
        cyr := RegExMatch(Sourse, "[А-Яа-я]")
        from := cyr ? "ru" : "auto", to := cyr ? "en" : "ru"
    }
    else
        from := _from, to := _to

    PreUrl := "http://translate.google.com/translate_a/t?client=x&sl=" from "&tl=" to "&text="
    Url := PreUrl . URIEncode(Sourse) 
    if StrLen(Url) > MAX_URL_LENGTH
    {
        if RegExMatch(Sourse, "[\.\?!\n]")
        {
            StartPos := 1
            While StartPos := RegExMatch(Sourse, ".+?([\.\?!\r\n]+([ \t\r\n]*)|$)", Found, StartPos) + StrLen(Found)
            {
                Delimiter := Found2 ? Found2 : RegExReplace(Found, ".*(\s*)", "$1")
                Text := RegExReplace(Found, "(.*)\s*", "$1")
                Url := PreUrl . URIEncode(Text)
                if StrLen(Url) > MAX_URL_LENGTH
                {
                    If RegExMatch(Text, "[,;:—\r\n]")
                    {
                        PrevText := "", StartPos_ := 1

                        While StartPos_ := RegExMatch(Text, "(.+?)(([,;:—\.]+\s*)|$)", Found_, StartPos_) + StrLen(Found_)
                        {
                            txt := Found_1, dlmtr := Found_2

                            If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
                                TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from) . RegExReplace(PrevText, ".*(\s+)$", "$1")
                                    . BreakdownByGaps(txt, PreUrl, from) . dlmtr, PrevText := ""

                            else If StrLen(PreUrl . URIEncode(txt . dlmtr . PrevText)) > MAX_URL_LENGTH
                                TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
                                    . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

                            else
                                PrevText .= txt . dlmtr
                        }
                        TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
                    }
                    else
                        TransText .= BreakdownByGaps(Text, PreUrl, ByRef from)
                    TransText .= Delimiter
                }
                else
                    TransText .= GetTranslate(Url, from) . Delimiter
            }
        }
        else
            TransText := BreakdownByGaps(Sourse, PreUrl, ByRef from)
    }
    else
        TransText := GetTranslate(Url, from)

    TransText := RegExReplace(TransText, " ``(.)", "$1" Chr(0x301))   ; обработка знака ударения
       
    Return TransText 
}

URIEncode(Str)
{
    b_Format:=A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, % StrPutVar(Str, Var, "UTF-8")
    {
        Ch:=NumGet(Var, A_Index-1, "UChar")
        If Ch=0
            Break
        If (Ch>0x7f Or Ch<0x30 Or Ch=0x3d)
            s.="%"((StrLen(c:=SubStr(Ch, 3))<2) ? "0"c:c)
        else
            s.=Chr(Ch)
    }
    SetFormat, IntegerFast, % b_Format
    Return, s
}

Ping(strHost)
{
   Loop 4
      bRet := ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
   until bRet
   return bRet
}
 
GetTranslate(Url, byref from)
{
    if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
    {
        MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
        Return
    } 
    oJSON := GetObjectFromJSON(JsonTrans)
    
    Loop % oJSON.sentences.MaxIndex()
        trans .= oJSON.sentences[A_Index].trans
    
    MainTransText := FinishingText(trans)

    if oJSON.HasKey("dict")
        for k,v in oJSON.dict
            for ky,val in v
            {
                if !(ky = "terms")
                    continue
                
                dict .= "`n`n", i := 1
                for key,value in val
                {
                    if value ~= "i)(*UCP)^" trans "$"
                        continue
                    dict .= (i++ = 1 ? "" : "; ") . value
                }
            }
    
    from := oJSON.src, oJSON := "", dict := Trim(dict, "`n")
    Return FinishingText(trans . (dict ? "`n+`n" . dict : ""))
}

BreakdownByGaps(Text, PreUrl, ByRef from)
{
    StartPos := 1
    While StartPos := RegExMatch(Text, "(.+?)([ \t]+|$)", Found, StartPos) + StrLen(Found)
    {
        txt := Found1, dlmtr := Found2
        If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
            TransText .= txt . dlmtr, PrevText := ""

        else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > MAX_URL_LENGTH
            TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
                . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr 
        else
            PrevText .= txt . dlmtr
    }
    Return TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
}
 
StrPutVar(string, ByRef var, encoding = "CP0")
{
     ; Ensure capacity.
     VarSetCapacity( var, StrPut(string, encoding)
          ; StrPut returns char count, but VarSetCapacity needs bytes.
          * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
     ; Copy or convert the string.
     return StrPut(string, &var, encoding)
}

UrlDownloadToVar(URL, UserAgent = "", ProxyServer = "", UserName = "", Password = "")
{
    WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ProxyServer ? WebRequest.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY := 2, ProxyServer)
   WebRequest.Open("GET", Url)
   ProxyServer ? WebRequest.SetCredentials(UserName, Password, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY := 1)
    UserAgent ? WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
    Text := WebRequest.ResponseText
    WebRequest := ""
    return Text
}
 
GetObjectFromJSON(string)
{
   FirstSim := SubStr(string, 1, 1)
   mode := FirstSim = "{" ? "collection" : FirstSim = "[" ? "array" : FirstSim = """" ? ""
      . "str" : RegExMatch(FirstSim, "[\d]") ? "num" : "Error"
   if (mode = "collection")
   {
      Obj := {}, StartPos := 2
      While StartPos := RegExMatch(string, """(.*?)"":\s*", Found, StartPos)
      {
         RegExMatch(string, "P)([\[\{""\d])", Found_, StartPos += StrLen(Found))
         Content := GetContent(SubStr(string, StartPos))
         Obj[Found1] := GetObjectFromJSON(Content)
         StartPos := Found_Pos1 + StrLen(Content)
      }
   }
   else if (mode = "array")
   {
      Obj := [], StartPos := 2
      While RegExMatch(string, "P)([\[\{""\d])", Found_, StartPos)
      {
         Content := GetContent(SubStr(string, Found_Pos1))
         Obj.Insert(GetObjectFromJSON(Content))
         StartPos := Found_Pos1 + StrLen(Content)
      }
   }
   else if (mode = "str")
        Obj := SubStr(string, 2, -1)
   else if (mode = "num")
      Obj := string
   else
      MsgBox, Ошибка! Первый символ входящего объекта не может быть "%FirstSim%"!
   Return Obj
}

FinishingText(text)
{
    if RegExMatch(text, "\\u\d\d\d\d")
    {
        StartPos := 1
        While StartPos := RegExMatch(text, "\\u(\d\d\d\d)", Found, StartPos)
            text := RegExReplace(text, "\Q" Found "\E", Chr("0x" Found1)), StartPos++
    }
    text := RegExReplace(text, "\\r\\n", "`r`n")
 , text := RegExReplace(text, "\\(.)", "$1")
    Return text
} 
 
GetContent(string)
{
   FirstSim := SubStr(string, 1, 1)
   inverse := FirstSim = "{" ? "}" : FirstSim = "[" ? "]" : FirstSim = """" ? """" : ""
   if (inverse = "")
      Content := RegExReplace(string, "([\de.-]+).*", "$1")
   else if (inverse = """")
      Content := RegExReplace(string, "(.*?[^\\]"").*", "$1")
   else
   {
      i := 0
      Loop, parse, string
      {
         Content .= A_LoopField
         i += ((A_LoopField = FirstSim && PrevSim != "\") ? 1 : (A_LoopField = inverse && PrevSim != "\") ? -1 : 0)
         if i = 0
            break
         PrevSim := A_LoopField
      }
   }
   Return Content
} 
Return

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

109 (изменено: serzh82saratov, 2013-05-22 22:22:46)

Re: AHK: Переводчик онлайн

Хотя нет, ещё проще добавить хоткей в оригинальный код, ничего не трогать, и всем пользоватся:


1:: msgbox % Clipboard := Translate(RegExReplace(Clipboard, "\R", "`r`n"), "", "", 0) 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

110

Re: AHK: Переводчик онлайн

Ну пока что не стал заморачиваться и сделал как написал Mikki. Сначала код тупил и переводил только первую попытку, но сейчас вот работает все на 5+!
Возможно это великий и могучий Маздай Биловский, приставкой 7...

111

Re: AHK: Переводчик онлайн

Если проверить/использовать готовый код, это - заморачиваться, то прошу прощения.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

112

Re: AHK: Переводчик онлайн

OwnCorporation пишет:

Отлично сделал !Приятного дня, если ты в США.Доброй ночи, если ты не в США. :))

113

Re: AHK: Переводчик онлайн

Приветствую народ, у меня на Win7 64 не корректно работает скрипт из коллекции - иконки он скачал, а дальше - окно не показывается. Даже не понимаю какие еще симптомы или данные сообщить, потому, что вообще ни чего не происходит на экране после Ctrl+C+C, разве что - фокус разочек прыгает на текущее активное окно.

Спасибо.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

114

Re: AHK: Переводчик онлайн

У меня на Win7 64 всё работает корректно. Может, горячая клавиша Ctrl+C+C с чем-то пересекается. Попробуй в трей-меню включить Ctrl+Ins+Ins. Ну или код неверно скопирован. Также версию AHK не помешает проверить. Кроме того, если буфер обмена пуст, окно не появится, поэтому перед нажатием Ctrl+C+C нужно какой-либо текст выделить.

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

115 (изменено: Mikki, 2013-07-16 20:43:03)

Re: AHK: Переводчик онлайн

наверное скрипт был старый....другого не дано - скачал из коллекции и он работает. Спасибо за скрипт!

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

116 (изменено: Mikki, 2013-12-25 14:57:58)

Re: AHK: Переводчик онлайн

Всем привет.
При запуске перевода на одном сайте начало выдавать ошибку:

"Ошибка! Первый символ входящего объекта не может быть 't'"

, и входит в бесконечный цикл выдавания этого окна пока не снимешь задачу.... Проблема проявляется при попытке перевода в поле редактирования на сайте использующем движок bugzilla (отслеживание багов в проекте и отчетность).

После короткого расследования выяснилось, что в функцию GetObjectFromJSON(string) приходит значение "true", первый символ которого и есть "t"....

Если сделать Ctrl+C потом Ctrl+V из этого поля редактирования то вставляется то что скопировано. Есть ли у кого идеи в чем причина такого поведения скрипта на окне Багзиллы и предположения как исправить это?


added:

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

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

117

Re: AHK: Переводчик онлайн

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

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

118

Re: AHK: Переводчик онлайн

Исправил функцию GetObjectFromJSON():

GetObjectFromJSON(string)
{
   FirstSim := SubStr(string, 1, 1)
   mode := FirstSim = "{" ? "collection" : FirstSim = "[" ? "array" : FirstSim = """" ? ""
      . "str" : (RegExMatch(FirstSim, "[\d]") || string = "true" || string = "false") ? "num" : "Error"
    
   if (mode = "collection")
   {
      Obj := {}, StartPos := 2
      While StartPos := RegExMatch(string, """(.*?)"":\s*", Found, StartPos)
      {
         RegExMatch(string, "P)([\[\{""\dtf])", Found_, StartPos += StrLen(Found))
         Content := GetContent(SubStr(string, StartPos))
         Obj[Found1] := GetObjectFromJSON(Content)
         StartPos := Found_Pos1 + StrLen(Content)
      }
   }
   else if (mode = "array")
   {
      Obj := [], StartPos := 2
      While RegExMatch(string, "P)([\[\{""\dtf])", Found_, StartPos)
      {
         Content := GetContent(SubStr(string, Found_Pos1))
         Obj.Insert(GetObjectFromJSON(Content))
         StartPos := Found_Pos1 + StrLen(Content)
      }
   }
   else if (mode = "str")
        Obj := SubStr(string, 2, -1)
   else if (mode = "num")
      Obj := string
   else
      MsgBox, Ошибка! Первый символ входящего объекта не может быть "%FirstSim%"!
   Return Obj
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

119

Re: AHK: Переводчик онлайн

Огромное спасибо!

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

120

Re: AHK: Переводчик онлайн

Также и случай "false" не помешает учесть, подредактировал.

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

121

Re: AHK: Переводчик онлайн

только что попытался перевести текст функции которую ты привел 3-мя постами выше (браузер - Chrome) - выдало про "Первый символ "t""..Дважды выдает, потом переводит.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

122

Re: AHK: Переводчик онлайн

Да, есть какой-то затык, надо подумать.

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

123

Re: AHK: Переводчик онлайн

Новый вариант. Изменён принцип получения объекта из JSON-строки.

#NoEnv
#SingleInstance, force
SetBatchLines, -1

if !A_IsCompiled
{
   if !FileExist(A_ScriptDir . "\Icons")
   {
      MsgBox, 4,, В директории скрипта отсутствует папка с иконками.`nЗагрузить с сервера?
      IfMsgBox, Yes
      {
         FileCreateDir, % A_ScriptDir "\Icons"
         TrayTip,, Идёт загрузка файлов с сервера`, подождите...
         if !Ping("content.screencast.com")
         {
            MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
            ExitApp
         }
         PreUrl := "http://content.screencast.com/users/teadrinker/folders/icons/media/"
         URLDownloadToFile, % PreUrl . "83188ad1-4a8a-491f-bf70-fb292e73c98c/Change.ico?downloadOnly=true"    , Icons\Change.ico
         URLDownloadToFile, % PreUrl . "57ced9ad-3ccc-4019-a9bd-6f86218f3dd9/Google.ico?downloadOnly=true"    , Icons\Google.ico
         URLDownloadToFile, % PreUrl . "4ed2cdc9-556f-4266-9b23-d8ec665c9b84/PlayPause.ico?downloadOnly=true", Icons\PlayPause.ico
         URLDownloadToFile, % PreUrl . "869c4c44-5e3a-470c-bed4-c8d2bcee621d/Stop.ico?downloadOnly=true"       , Icons\Stop.ico
         URLDownloadToFile, % PreUrl . "0ac5a584-d28c-4ca7-aac8-a45631a2e3c3/Translate.ico?downloadOnly=true", Icons\Translate.ico
         
         if !(FileExist("Icons\Change.ico") && FileExist("Icons\Google.ico") && FileExist("Icons\PlayPause.ico")
            && FileExist("Icons\Stop.ico") && FileExist("Icons\Translate.ico"))
         {
            TrayTip
            MsgBox, Не удалось завершить загрузку.`nЗагрузите папку вручную из аттача к теме на форуме
               ,`nпоместите её в директорию скрипта и запустите скрипт снова.
            ExitApp
         }
         else
         {
            Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
            TrayTip,, Загрузка успешно завершена!
            Sleep, 1500
            TrayTip
         }
      }
      else
      {
         MsgBox, Загрузите папку вручную из аттача к теме на форуме
            ,`nпоместите её в директорию скрипта и запустите скрипт снова.
         ExitApp
      }
   }
   Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
}

global  MAX_URL_LENGTH := 2076, IMAGE_ICON := 1, WM_INPUTLANGCHANGEREQUEST := 0x50
      , EVENT_SYSTEM_MOVESIZESTART := 0xA, EVENT_SYSTEM_MOVESIZEEND := 0xB
      , GUIs := [], LangArray := {}, Player, Voice := [], ColorGui := "Default", MainTransText
      , SIZING, Edit1HPos, Edit2HPos, Edit2YPos, Button2YPos, Button6YPos, Edit1FontSize, Edit2FontSize
      , IsControlPos, GetControlPos, ScriptPID, GuiActive, SaveSize, AllowMultiWindow
      , IniName := RegExReplace(A_ScriptName, "(.*\.).*", "$1ini")
   
Process, Exist
ScriptPID := ErrorLevel
InitLangArray()

Hotkey, IfWinActive
Hotkey, ~^vk43, HotkeyRun, Off
Hotkey, ~^Ins , HotkeyRun, Off

IniRead, Hotkey            , % IniName, Hotkey   , Hotkey               , C
IniRead, ShowWindowOnStart   , % IniName, Settings, ShowWindowOnStart   , 0
IniRead, SaveSize            , % IniName, Settings, SaveSize            , 0
IniRead, AllowMultiWindow   , % IniName, Settings, AllowMultiWindow   , 0
IniRead, Edit1FontSize      , % IniName, Location, Edit1FontSize      , 8
IniRead, Edit2FontSize      , % IniName, Location, Edit2FontSize      , 8

if InStr(Hotkey, "C")
   Hotkey, ~^vk43, On
if InStr(Hotkey, "Ins")
   Hotkey, ~^Ins, On

Menu, Tray, NoStandard

Menu, Tray, Add, Открыть, Open
Menu, Tray, Default, Открыть
Menu, Tray, Add

Menu, Tray, Add, Показывать окно при запуске, ShowWindowOnStart
if ShowWindowOnStart
   Menu, Tray, Check, Показывать окно при запуске

Menu, Tray, Add, Сохранять размеры окна, SaveSize
if SaveSize
   Menu, Tray, Check, Сохранять размеры окна

Menu, Tray, Add, Разрешить много окон, AllowMultiWindow
if AllowMultiWindow
   Menu, Tray, Check, Разрешить много окон

Menu, Tray, Add
Menu, Tray, Add, Использовать Ctrl+C+C, Hotkey
Menu, Tray, Add, Использовать Ctrl+Ins+Ins, Hotkey
if InStr(Hotkey, "C")
   Menu, Tray, Check, Использовать Ctrl+C+C
if InStr(Hotkey, "Ins")
   Menu, Tray, Check, Использовать Ctrl+Ins+Ins
Menu, Tray, Add

if !A_IsCompiled
{
   Menu, Tray, Add, Edit, Edit
   Menu, Tray, Add, Reload, Reload
   Menu, Tray, Add
}
Menu, Tray, Add, Выход, ExitApp

HWINEVENTHOOK := SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, 0
                                          , RegisterCallback("WinGetControlPos", "F"), 0, 0, 0)
OnExit, Exit

OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x111, "WM_COMMAND")
OnMessage(0x214, "WM_SIZING")

ShowWindowOnStart ? ShowTranslation("", "", "en", "ru")
Return

Open:
   if !WinExist("Google Translate ahk_pid" ScriptPID) || AllowMultiWindow
   ShowTranslation("", "", "en", "ru")
   return
   
ShowWindowOnStart:
AllowMultiWindow:
SaveSize:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   %A_ThisLabel% := !%A_ThisLabel%
   IniWrite, % %A_ThisLabel%, % IniName, Settings, %A_ThisLabel%
   return

Edit:
   Edit
   return
   
Reload:
   Reload
   return

Hotkey:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   
   if InStr(A_ThisMenuItem, "Ins")
      Hotkey := InStr(Hotkey, "Ins") ? RegExReplace(Hotkey, "Ins") : Hotkey . "Ins"
   if InStr(A_ThisMenuItem, "C+C")
      Hotkey := InStr(Hotkey, "C") ? RegExReplace(Hotkey, "C") : Hotkey . "C"
   
   Hotkey, ~^Ins, % InStr(Hotkey, "Ins") ? "On" : "Off"
   Hotkey, ~^vk43, % InStr(Hotkey, "C") ? "On" : "Off"
   
   IniWrite, % Hotkey, % IniName, Hotkey, Hotkey
   return

HotkeyRun:
   DoublePress()
   return
   
Exit:
   WinGet, List, List, % "Google Translate ahk_pid" ScriptPID
   Loop % List
   {
      if (List%A_Index% = GUIs.1)
      {
         IniWriteSizeGui(GUIs.1), SaveSize ? IniWriteSizeEdit(GUIs.1)
         break
      }
   }
   DllCall("UnhookWinEvent", Ptr, HWINEVENTHOOK)
   GUIs := LangArray := Voice := ""
ExitApp:
   ExitApp
   
^!vk56::SendInput, {Raw}%MainTransText%

#If WinActive("Google Translate ahk_pid" ScriptPID)
Esc::WinClose, A
Enter::ControlClick, Button4, % "Google Translate ahk_pid" ScriptPID

#If WinActive("Google Translate ahk_pid" ScriptPID) && NN := GetEditFocus()
^WheelUp::
^WheelDown::
   InStr(A_ThisHotkey, "Up") ? ++Edit%NN%FontSize : --Edit%NN%FontSize
   Edit%NN%FontSize < 6 ? Edit%NN%FontSize := 6
   Edit%NN%FontSize > 25 ? Edit%NN%FontSize := 25
   ToolTip % "FontSize = " . Edit%NN%FontSize
   
   Gui, % WinExist("A") . ":Default"
   Gui, Font, % "q5 s" . Edit%NN%FontSize, Verdana
   GuiControl, Font, Edit%NN%
   SetTimer, IniWriteFontSize, -500
   return
   
IniWriteFontSize:
   ToolTip
   IniWrite, %Edit1FontSize%, % IniName, Location, Edit1FontSize
   IniWrite, %Edit2FontSize%, % IniName, Location, Edit2FontSize
   return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400 And Clipboard
   {
      pressed1 := 0
      if (!(hwnd := WinExist("Google Translate ahk_pid" ScriptPID)) || AllowMultiWindow)
         GuiActive := GetActiveWindow(), Translate(RegExReplace(Clipboard, "\R", "`r`n"))
      else
         TranslateInTheSameWindow(hwnd, Clipboard)
   }   
   else
      pressed1 := 1
}

Translate(Sourse, ByRef _from="", ByRef _to="", NewWindow = 1)
{
   if !Ping("translate.google.com")
   {
      MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Sourse, "[А-Яа-я]")
      from := cyr ? "ru" : "auto", to := cyr ? "en" : "ru"
   }
   else
      from := _from, to := _to

   PreUrl := "http://translate.google.com/translate_a/t?client=x&sl=" . from . "&tl=" . to . "&text="
   Url := PreUrl . URIEncode(Sourse)

   if StrLen(Url) > MAX_URL_LENGTH
   {
      if RegExMatch(Sourse, "[\.\?!\n]")
      {
         StartPos := 1
         While StartPos := RegExMatch(Sourse, ".+?([\.\?!\r\n]+([ \t\r\n]*)|$)", Found, StartPos) + StrLen(Found)
         {
            Delimiter := Found2 ? Found2 : RegExReplace(Found, ".*(\s*)", "$1")
            Text := RegExReplace(Found, "(.*)\s*", "$1")
            Url := PreUrl . URIEncode(Text)
            if StrLen(Url) > MAX_URL_LENGTH
            {
               If RegExMatch(Text, "[,;:—\r\n]")
               {
                  PrevText := "", StartPos_ := 1

                  While StartPos_ := RegExMatch(Text, "(.+?)(([,;:—\.]+\s*)|$)", Found_, StartPos_) + StrLen(Found_)
                  {
                     txt := Found_1, dlmtr := Found_2

                     If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
                        TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from) . RegExReplace(PrevText, ".*(\s+)$", "$1")
                           . BreakdownByGaps(txt, PreUrl, from) . dlmtr, PrevText := ""

                     else If StrLen(PreUrl . URIEncode(txt . dlmtr . PrevText)) > MAX_URL_LENGTH
                        TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
                           . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

                     else
                        PrevText .= txt . dlmtr
                  }
                  TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
               }
               else
                  TransText .= BreakdownByGaps(Text, PreUrl, ByRef from)
               TransText .= Delimiter
            }
            else
               TransText .= GetTranslate(Url, from) . Delimiter
         }
      }
      else
         TransText := BreakdownByGaps(Sourse, PreUrl, ByRef from)
   }
   else
      TransText := GetTranslate(Url, from)

   TransText := RegExReplace(TransText, " ``(.)", "$1" Chr(0x301))   ; обработка знака ударения
   
   If NewWindow
      ShowTranslation(Clipboard, TransText, from, to)
   else
   {
      _from := from, _to := to
      Return TransText
   }
}

BreakdownByGaps(Text, PreUrl, ByRef from)
{
   StartPos := 1
   While StartPos := RegExMatch(Text, "(.+?)([ \t]+|$)", Found, StartPos) + StrLen(Found)
   {
      txt := Found1, dlmtr := Found2
      If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= txt . dlmtr, PrevText := ""

      else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
            . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

      else
         PrevText .= txt . dlmtr
   }
   Return TransText .= GetTranslate(PreUrl . URIEncode(PrevText), from)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, IntegerFast, H
   Loop, % StrPutVar(Str, Var, "UTF-8")
   {
      Ch:=NumGet(Var, A_Index-1, "UChar")
      If Ch=0
         Break
      If (Ch>0x7f Or Ch<0x30 Or Ch=0x3d)
         s.="%"((StrLen(c:=SubStr(Ch, 3))<2) ? "0"c:c)
      else
         s.=Chr(Ch)
   }
   SetFormat, IntegerFast, % b_Format
   Return, s
}

GetTranslate(Url, byref from)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      MsgBox, 16, Ошибка, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }
   if !RegExMatch(JsonTrans, "^\{""sentences.*trans.*\}$")
   {
      MsgBox, 16, Ошибка, Неверный формат ответа от сервера.
      return
   }
   
   htmldoc := ComObjCreate("htmlfile")
   Script := htmldoc.Script   ; или htmldoc.parentWindow
   Script.execScript(GetJScript())
   oJSON := Script.eval("(" . JsonTrans . ")")
   
   Loop % oJSON.sentences.GetKeys().length
      trans .= (oJSON.sentences)[A_Index-1].trans
   
   MainTransText := FinishingText(trans)

   keys := oJSON.GetKeys()
   Loop % keys.length
   {
      if (keys[A_Index-1] != "dict")
         continue
      
      oDict := oJSON.dict
      Loop % oDict.GetKeys().length
      {
         dict .= "`n`n", i := 1
         oTerms := (oDict[A_Index-1]).terms
         Loop % oTerms.GetKeys().length
         {
            value := oTerms[A_Index-1]
            if value ~= "i)(*UCP)^" trans "$"
               continue
            dict .= (i++ = 1 ? "" : "; ") . value
         }
      }
   }
   
   from := oJSON.src, dict := Trim(dict, "`n")
   Return FinishingText(trans . (dict ? "`n+`n" . dict : ""))
}

GetJScript()
{
   JScript =
   (
      Object.prototype.GetKeys = function ()
      {
         var keys = []
         for (var k in this)
            if (this.hasOwnProperty(k))
               keys.push(k)
         return keys
      }
   )
   return JScript
}

FinishingText(text)
{
   if RegExMatch(text, "\\u\d\d\d\d")
   {
      StartPos := 1
      While StartPos := RegExMatch(text, "\\u(\d\d\d\d)", Found, StartPos)
         text := RegExReplace(text, "\Q" Found "\E", Chr("0x" Found1)), StartPos++
   }
   text := RegExReplace(text, "\\r\\n", "`r`n")
 , text := RegExReplace(text, "\\(.)", "$1")
   Return text
}

WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}

StrPutVar(string, ByRef var, encoding = "CP0")
{
    ; Ensure capacity.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut returns char count, but VarSetCapacity needs bytes.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; Copy or convert the string.
    return StrPut(string, &var, encoding)
}

UrlDownloadToVar(URL, UserAgent = "", ProxyServer = "", UserName = "", Password = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ProxyServer ? WebRequest.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY := 2, ProxyServer)
   WebRequest.Open("GET", Url)
   ProxyServer ? WebRequest.SetCredentials(UserName, Password, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY := 1)
   UserAgent ? WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}

ShowTranslation(SourceText, TransText, from, to)
{
   static PlayPause1, PlayPause2, Stop1, Stop2, hGui, Control, ExChange1, ExChange2, Source
        , hIconPlayPause, hIconStop, hIconTranslate, hIconGoogle, hIconChange, Icons
        , hButtPlayPause1, hButtPlayPause2, hButtStop1, hButtStop2, hButtTranslate, hButtChange1, hButtChange2
        , BS_ICON := 0x40, WM_SETICON := 0x80, BM_SETIMAGE := 0xF7, ES_NOHIDESEL := 0x100
        , WMSZ_TOP := 3, WMSZ_TOPLEFT := 4, WMSZ_TOPRIGHT := 5

   Gui, New, +AlwaysOnTop +LastFound +Resize +hwndhGui +Owner +MinSize199x220 -MaximizeBox
   Gui, Color, %ColorGui%
   
   oSize := IniReadSizeEdit()
   if (SaveSize && Edit1H := oSize.Edit1H)
      Edit1W := oSize.Edit1W, Edit2H := oSize.Edit2H
   
   Gui, Font, q5 s8, Verdana
   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y15", Исходный язык:

   SourceLangNames := TargetLangNames := ""
   For k,v In LangArray
      SourceLangNames .= (A_Index = 1 ? "" : "|") . k . (v = from ? "|" : "")
    , TargetLangNames .= (A_Index = 1 ? "" : "|") . k . (v = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % SourceLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange1 gExchangeLang vExChange1"

   Gui, Font, q5 s%Edit1FontSize%, Verdana
   if !(SaveSize && Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL% vSource, % SourceText
      GuiControlGet, Edit1, Pos
      
      Edit1H < 45 ? Edit1H := 45
      Edit1H > 250 ? Edit1H := 250
      GuiControl, Move, Edit1, h%Edit1H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit1H " vSource " ES_NOHIDESEL, % SourceText

   GuiControlGet, Edit1, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit1Y + Edit1H + 5 " w52 h23 hwndhButtPlayPause1 gPlayPause vPlayPause1 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop1 gStop vStop1" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 " BS_ICON " hwndhButtTranslate gTranslate"

   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y+20", Язык перевода:

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % TargetLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange2 gExchangeLang vExChange2"

   Gui, Font, q5 s%Edit2FontSize%, Verdana
   if !(SaveSize && Edit1H := oSize.Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL%, % TransText
      GuiControlGet, Edit2, Pos
      
      Edit2H < 45 ? Edit2H := 45
      Edit2H > 250 ? Edit2H := 250
      GuiControl, Move, Edit2, h%Edit2H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit2H " " ES_NOHIDESEL, % TransText

   GuiControlGet, Edit2, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit2Y + Edit2H + 5 " w52 h23 hwndhButtPlayPause2 gPlayPause vPlayPause2 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop2 gStop vStop2" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 gGuiClose", OK

   if !IsObject(Icons)
   {
      hIconGoogle    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 1, 24) : ExtractIcon(A_ScriptDir "\Icons\Google.ico"    , 1, 24)
      hIconChange    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 2, 16) : ExtractIcon(A_ScriptDir "\Icons\Change.ico"    , 1, 16)
      hIconPlayPause := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 3, 25) : ExtractIcon(A_ScriptDir "\Icons\PlayPause.ico", 1, 25)
      hIconStop       := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 4, 12) : ExtractIcon(A_ScriptDir "\Icons\Stop.ico"       , 1, 12)
      hIconTranslate := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 5, 16) : ExtractIcon(A_ScriptDir "\Icons\Translate.ico", 1, 16)
      Icons := [hIconGoogle, hIconChange, hIconPlayPause, hIconStop, hIconTranslate]
   }

   DetectHiddenWindows, On
   Loop 2
   {
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconChange      ,, % "ahk_id" hButtChange%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconPlayPause   ,, % "ahk_id" hButtPlayPause%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconStop         ,, % "ahk_id" hButtStop%A_Index%
   }
   PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconTranslate,, ahk_id %hButtTranslate%
   PostMessage, WM_SETICON,, hIconGoogle,, ahk_id %hGui%
   PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[from = "ru" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   DetectHiddenWindows, Off
   
   GuiControlGet, Button8, Pos
   Gui, Show, % "hide h" Button8Y + Button8H + 6, Google Translate
   GuiControl, Focus, Edit1

   if !WinExist("Google Translate ahk_pid" ScriptPID)
   {
      IniRead, xGUI, % IniName, Location, xGUI, % " "
      IniRead, yGUI, % IniName, Location, yGUI, % " "
      Gui, Show, % (xGUI = "" ? "" : "x" xGUI " y" yGUI " ") "w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   else
   {
      WinGetPos, X, Y,,, % "ahk_id " (GuiActive ? GuiActive : GUIs[GUIs.MaxIndex()])
      Gui, Show, % "x" X + 60 " y" Y + 40 " w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   GUIs.Insert(hGui), GuiActive := ""
   Return
   
GuiSize:
   if !IsControlPos
      return

   SetWinDelay, 0
   if (SIZING ~= WMSZ_TOP "|" WMSZ_TOPLEFT "|" WMSZ_TOPRIGHT)
   {
      if A_GuiHeight - Edit1HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      }
   }
   else
   {
      if A_GuiHeight - Edit2HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      }
   }
   return

PlayPause:
   if IsObject(Player)
   {
      if Playing := !Playing
         Player.Controls.pause()
      else
         Player.Controls.play()
   }
   else
   {
      hGui := A_Gui, Control := A_GuiControl
      SetTimer, PlayPauseTimer, -1
   }
   return

PlayPauseTimer:
   n := SubStr(Control, 0)
   ControlGet, Text, Selected,, Edit%n%, ahk_id %hGui%
   if (Text = "")
      ControlGetText, Text, Edit%n%, ahk_id %hGui%
   ControlGetText, lng, ComboBox%n%, ahk_id %hGui%
   Say(RegExReplace(Text, "\R+", "`n"), LangArray[lng])
   return

Stop:
   Player.close()
   Playing := Player := ""
   StopButtonEnableDisable(0)
   return

ExchangeLang:
   GuiControlGet, to,, ComboBox1
   GuiControlGet, from,, ComboBox2
   
   SourceLangNames := TargetLangNames := ""
   for k In LangArray
      SourceLangNames .= "|" . k . (k = from ? "|" : "")
    , TargetLangNames .= "|" . k . (k = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")
   
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl, Focus, Edit1
   return
   
Translate:
   GuiControlGet, from,, ComboBox1
   from := LangArray[from]
   GuiControlGet, to,, ComboBox2
   to := LangArray[to]
   GuiControlGet, SourseText,, Edit1
   TransText := Translate(RegExReplace(SourseText, "\R", "`r`n"), from, to, 0)

   GuiControl,, Edit2, % TransText
   GuiControl, Focus, Edit1
   Return

GuiClose:
   if (A_Gui = GUIs.1)
      IniWriteSizeGui(A_Gui), SaveSize ? IniWriteSizeEdit(A_Gui)
   else
   {
      for k,v in GUIs
         if (A_Gui = v)
            break
      GUIs.Remove(k)
   }
   
   Gui, %A_Gui%: Destroy
   IfWinNotExist, Google Translate ahk_pid %ScriptPID%
   {
      Player.close(), Player := "", Voice := []
      FileDelete, % A_ScriptDir "\mp3\*.mp3"
      Loop % Icons.MaxIndex()
         DllCall("DestroyIcon", Ptr, Icons[A_Index])
      Icons := "", GUIs := []
   }
   return
}

TranslateInTheSameWindow(hwnd, SourceText)
{
   Translation := Translate(RegExReplace(SourceText, "\R", "`r`n"), from, to, 0)

   For k,v In LangArray
      SourceLangNames .= "|" . k . (v = from ? "|" : "")
    , TargetLangNames .= "|" . k . (v = to   ? "|" : "")
   
   Gui, %hwnd%:Default
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl,, Edit1, % SourceText
   GuiControl,, Edit2, % Translation
}

Resizing(W, H, mode)
{
   E1H := H - Edit1HPos
   E2Y := H - Edit2YPos, E2H := H - Edit2HPos
   B2Y := H - Button2YPos, B6Y := H - Button6YPos

   if mode = 1
   {
      GuiControl, Move, Edit1, % "w" W - 20 " h" E1H
      GuiControl, Move, Edit2, % "w" W - 20 " y" E2Y
      GuiControl, MoveDraw, Button2, % "y" B2Y
      GuiControl, MoveDraw, Button3, % "y" B2Y
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120) " y" B2Y
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10) " y" B2Y + 43
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112) " y" B2Y + 39
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297) " y" B2Y + 38
   }
   else
   {
      GuiControl, Move, Edit1, % "w" W - 20
      GuiControl, Move, Edit2, % "w" W - 20 " h" (E2H > 32 ? E2H : 32)
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120)
   }
   GuiControl, Move, Static1, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
   GuiControl, Move, ComboBox1, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
   GuiControl, MoveDraw, Button1, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
   GuiControl, MoveDraw, Button6, % "y" B6Y
   GuiControl, MoveDraw, Button7, % "y" B6Y
   GuiControl, MoveDraw, Button8, % "x" (W > 200 ? W - 80 : 120) " y" B6Y
}

InitLangArray()
{
   Languages =
   (LTrim C
      Азербайджанский|az
      Албанский|sq
      Английский|en
      Арабский|ar
      Армянский|hy
      Африкаанс|af
      Баскский|eu
      Белорусский|be
      Болгарский|bg
      Венгерский|hu
      Вендский|sb
      Вьетнамский|vi
      Голландский|nl
      Греческий|el
      Грузинский|ka
      Датский|da
      Иврит|he
      Идиш|ji
      Индонезийский|id
      Исландский|is
      Испанский|es
      Итальянский|it
      Каталонский|ca
      Китайский|zh
      Китайский (Аомынь)|zh-cn
      Китайский (Тайвань)|zh-tw
      Корейский|ko
      Латынь|la
      Латышский|lv
      Литовский|lt
      Македонский|mk
      Малайский|ms
      Мальтийский|mt
      Немецкий|de
      Норвежский|no
      Польский|pl
      Португальский|pt
      Румынский|ro
      Русский|ru
      Сербский|sr
      Словацкий|sk
      Словенский|sl
      Суахили|sw
      Тайский|th
      Турецкий|tr
      Украинский|uk
      Урду|ur
      Фарси|fa
      Финский|fi
      Французский|fr
      Хинди|hi
      Хорватский|hr
      Чешский|cs
      Шведский|sv
      Эсперанто|eo
      Эстонский|et
      Японский|ja
   )

   Loop, parse, Languages, `n, `r
   {
      Key := RegExReplace(A_LoopField, "(.*)\|.*", "$1")
      Value := RegExReplace(A_LoopField, ".*\|(.*)", "$1")
      LangArray[Key] := Value
   }
}

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   if (ext = "ico")
      IconNumber := 0

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Указанный файл не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge)
         , hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall)
         , hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

Ping(strHost)
{
   Loop 4
      bRet := ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
   until bRet
   return bRet
}

Say(Text, lng)
{
   static PlaylistOpenNoMedia := 6, Stopped := 1
   
   Player := ComObjCreate("WMPlayer.OCX")
   objPlaylist := Player.currentPlaylist

   for k,v in Voice
      if (v.Text = RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1") && v.lng = lng)
      {
         var := 1
         break
      }

   if var
   {
      Loop % v.mp3.MaxIndex()
         objPlaylist.appendItem(Player.newMedia(v.mp3[A_Index]))
   }
   else
   {
      if !Ping("translate.google.com")
      {
         MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
         Return
      }

      PreUrl := "http://translate.google.com/translate_tts?ie=UTF-8&tl=" lng "&q="
      Strings := []
      If StrLen(Text) > 100
      {
         StartPos := 1
         While StartPos := RegExMatch(Text, ".+?(\.|$)", Found, StartPos) + StrLen(Found)
         {
            if StrLen(Found) > 100
            {
               StartPos_ := 1
               While StartPos_ := RegExMatch(Found, "(.{1,99}([ ,\t\n]|$))|(.{1,100})", Found_, StartPos_) + StrLen(Found_)
                  Strings.Insert(Found_)
            }
            else
               Strings.Insert(Found)
         }
      }
      else
         Strings.1 := Text

      if !FileExist(A_ScriptDir "\mp3")
         FileCreateDir, %A_ScriptDir%\mp3

      Voice.Insert(o := {Text: RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1"), lng: lng, mp3: []})
      Loop % count := Strings.MaxIndex()
      {
         URLDownloadToFile, % PreUrl . URIEncode(RegExReplace(Strings[A_Index], "^\s*([^\s]+)\s*$", "$1"))
            , % mp3file := A_ScriptDir "\mp3\" A_TickCount ".mp3"
         objPlaylist.appendItem(Player.newMedia(mp3file))
         o.mp3.Insert(mp3file)
      }
   }
   StopButtonEnableDisable(1)
   Player.Controls.play()
   While Player.PlayState != Stopped && Player.OpenState != PlaylistOpenNoMedia && IsObject(Player)
      Sleep, 100
   Player.close(), Player := objPlaylist := ""
   StopButtonEnableDisable(0)
}

StopButtonEnableDisable(key)
{
   WinGet, List, List, Google Translate ahk_pid %ScriptPID%
   Loop % List
   {
      Control , % key ? "Enable" : "Disable",, Button3, % "ahk_id" List%A_Index%
      Control , % key ? "Enable" : "Disable",, Button7, % "ahk_id" List%A_Index%
   }
}

WM_COMMAND(wp, lp)
{
   static EN_SETFOCUS := 0x100, CBN_SETFOCUS := 3
   
   if !WinActive("Google Translate") || !(wp>>16 = EN_SETFOCUS || wp>>16 = CBN_SETFOCUS)
      return
   
   Gui, %A_Gui%:Default
   DetectHiddenWindows, On
   
   if (wp>>16 = EN_SETFOCUS)
   {
      GuiControlGet, Name, Name, %lp%
      if Name != Source
         return
      
      GuiControlGet, lang,, ComboBox1
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[lang = "Русский" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   }
   
   if (wp>>16 = CBN_SETFOCUS)
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList().Ru,, ahk_id %A_ScriptHwnd%
   
   DetectHiddenWindows, Off
}

GetLayoutList()
{
   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
   SetFormat, IntegerFast, D
   Return {En: En, Ru: Ru}
}

WM_SIZING(wp)
{
   SIZING := wp
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin, UInt, eventMax
                                    , Ptr, hmodWinEventProc, Ptr, lpfnWinEventProc
                                    , UInt, idProcess, UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

WinGetControlPos(hWinEventHook, event, hwnd)
{
   if !GetActiveWindow()
      return
   
   if (event = EVENT_SYSTEM_MOVESIZEEND)
      IsControlPos := GetControlPos := "", CorrectPos(hwnd)
   else
      _WinGetControlPos(hwnd)
}

_WinGetControlPos(hwnd)
{
   Gui, %hwnd%:Default
   
   GuiControlGet, Edit1, Pos
   GuiControlGet, Edit2, Pos
   GuiControlGet, Button2, Pos
   GuiControlGet, Button6, Pos
   
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")

   Edit1HPos := ClientH - Edit1H
   Edit2HPos := ClientH - Edit2H
   Edit2YPos := ClientH - Edit2Y
   Button2YPos := ClientH - Button2Y
   Button6YPos := ClientH - Button6Y
   IsControlPos := 1
}

CorrectPos(hwnd)
{
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")
   
   Gui, %hwnd%:Default
   GuiControlGet, Edit2, Pos
   GuiControl, Move, Edit2, % "h" ClientH - Edit2Y - 34
   
   Loop 3
      GuiControl, MoveDraw, % "Button" A_Index + 5, % "y" ClientH - 29
}

GetActiveWindow()
{
   WinGetActiveTitle, Title
   WinGetClass, Class, A
   WinGet, PID, PID, A
   Return (Title = "Google Translate" && Class = "AutoHotkeyGUI" && PID = ScriptPID) ? WinExist("A") : ""
}

IniReadSizeEdit()
{
   IniRead, Edit1W, % IniName, Location, Edit1W, % " "
   IniRead, Edit1H, % IniName, Location, Edit1H, % " "
   IniRead, Edit2H, % IniName, Location, Edit2H, % " "
   Return {Edit1W: Edit1W, Edit1H: Edit1H, Edit2H: Edit2H}
}

IniWriteSizeEdit(hwnd)
{
   ControlGetPos,,, Edit1W, Edit1H, Edit1, % "ahk_id" hwnd
   ControlGetPos,,,, Edit2H, Edit2, % "ahk_id" hwnd
   
   IniWrite, % Edit1W, % IniName, Location, Edit1W
   IniWrite, % Edit1H, % IniName, Location, Edit1H
   IniWrite, % Edit2H, % IniName, Location, Edit2H
}

IniWriteSizeGui(hwnd)
{
   WinGetPos, X, Y,,, % "ahk_id" hwnd
   IniWrite, % X, % IniName, Location, xGUI
   IniWrite, % Y, % IniName, Location, yGUI
}

GetEditFocus()
{
   if !WinActive("Google Translate ahk_pid" ScriptPID)
      return
   
   ControlGetFocus, Control, A
   return InStr(Control, "Edit") ? SubStr(Control, 0) : ""
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

124 (изменено: wisgest, 2013-12-31 02:00:35)

Re: AHK: Переводчик онлайн

Как я понимаю, теперь (вероятно, с моей подачи) для разбора JSON используется JScript-функция eval() и она получается через ActiveX-объект htmlfile. Предубеждения против eval() широко известны, но не думаю, что опасность получить вредоносный код со стороны Google серьёзна. Выскажу возражения против htmlfile, к которым я пришёл за последнее время:
1) избыточность: для доступа только к возможностям языка JScript используется объект, позволяющий работать со всей объектной моделью HTML-документа;
2) зависимость от пользовательских настроек безопасности: как мне помнится, в IE6 метод window.execScript() при вызове извне работал даже при отключении клиентских сценариев, но в IE8 возникает ошибка

0x80070005 - Отказано в доступе.

Поэтому предпочтительней для получения eval() использовать способ из темы «COM-объект, умеющий исполнять JScript.».
Таким же образом (WSC) можно подключить и «настоящий» JSON-парсер: см. ответы Rumata в теме «Jscript Преобразование типов».

125

Re: AHK: Переводчик онлайн

Спасибо, сам немного сомневался в правомерности данного решения, поэтому пока в Коллекцию не заносил. Посмотрю предложенные варианты.

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

126

Re: AHK: Переводчик онлайн

wisgest пишет:

Предубеждения против eval() широко известны, но не думаю, что опасность получить вредоносный код со стороны Google серьёзна.

Чтобы получаяемая с помощью пользовательского WSC-компонента функция eval() не представляла угрозы при исполнении с её помощью стороннего кода, достаточно, на мой взгляд, удалить из её контекста потенциально опасные функции ActiveXObject() и GetObject().

delete ActiveXObject; delete GetObject;

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

127

Re: AHK: Переводчик онлайн

wisgest пишет:

Поэтому предпочтительней для получения eval() использовать способ из темы «COM-объект, умеющий исполнять JScript.».
Таким же образом (WSC) можно подключить и «настоящий» JSON-парсер: см. ответы Rumata в теме «Jscript Преобразование типов».

С этим пока не получается. В AHK нет аналога метода GetObject() из VBS. Функция ComObjGet() работает по-другому, с её помощью нельзя получить объект из файла. На оф. форуме нужной информации не нашёл.

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

128 (изменено: wisgest, 2013-12-31 04:10:01)

Re: AHK: Переводчик онлайн

teadreanker, я вчера дополнил своё сообщение в теме «COM-объект, умеющий исполнять JScript.» переводом VBS-примера на AHK. Он хоть и малосодержательный, но вполне рабочий!

129

Re: AHK: Переводчик онлайн

Ой, а у меня то же самое не вышло, почему-то . Наверно, название или путь к файлу неверно написал.

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

130

Re: AHK: Переводчик онлайн

Добавите в Коллекцию AHK?

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

131

Re: AHK: Переводчик онлайн

teadrinker пишет:

Добавите в Коллекцию AHK?

Да, я как раз сегодня думал, что этот пример можно добавить в коллекцию. Но он больше относится к зазделу WSH (ну или в меньшей мере «Прочее»), завязки на AHK тут нет, на его месте мог быть и другой язык. Хотя конечно, наряду с примером на VBScript не помешает рядом пример на AutoHotkey, но разносить их на две однотипные темы мне представляется излишним. Ну и примеры надо сделать чуть содержательнее — хотя бы добавить то же преобразование JSON-строки в объект.

132

Re: AHK: Переводчик онлайн

wisgest пишет:

разносить их на две однотипные темы мне представляется излишним.

Думаю, не страшно, многие пользователи AHK нечасто заглядывают в другие разделы, а пример действительно полезный.

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

133

Re: AHK: Переводчик онлайн

У меня так вышло:

JsonString =
(
   {
      "firstName": "Иван",
      "lastName": "Иванов",
      "address": {
          "streetAddress": "Московское ш., 101, кв.101",
          "city": "Ленинград",
          "postalCode": 101101
      },
      "phoneNumbers": [
          "812 123-1234",
          "916 123-4567"
      ]
   }
)

MethodGetKeys =
(
   Object.prototype.GetKeys = function ()
   {
      var keys = []
      for (var k in this)
         if (this.hasOwnProperty(k))
            keys.push(k)
      return keys
   }
)

if !FileExist(WscPath := A_ScriptDir . "\JS.wsc")
   FileAppend,
   (LTrim
      <component>
      <public><method name='eval'/></public>
      <script language='JScript'></script>
      </component>
   ), % WscPath

JS := ComObjGet("script:" . WscPath)

JS.eval("delete ActiveXObject; delete GetObject;")
JS.eval("(" . MethodGetKeys . ")")
oJSON := JS.eval("(" . JsonString . ")")

keys := oJSON.GetKeys()

Loop % keys.length
   MsgBox, % keys[A_Index - 1]

Это

JS.eval("delete ActiveXObject; delete GetObject;")

я верно написал?

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

134

Re: AHK: Переводчик онлайн

teadrinker пишет:

Это

JS.eval("delete ActiveXObject; delete GetObject;")

я верно написал?

Да.

135

Re: AHK: Переводчик онлайн

А как лучше, получать объект JS каждый раз заново при каждом переводе, или только один раз при загрузке скрипта? Не будут ли в последнем варианте объекты oJSON накапливаться в памяти?

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

136

Re: AHK: Переводчик онлайн

На мой взгляд, лучше один раз.
Объекты скапливаться не должны, если на них не будутоставаться ссылки.
В любом случае хуже не будет: даже если мы будем  получать объект JS каждый раз заново, но если не будут удалятся (достаточно присваивания нового значения той же переменной при новом переводе) ссылки на объекты oJSON, то они будут накапливаться в памяти.

137

Re: AHK: Переводчик онлайн

Ясно, спасибо. У меня в функциях все эти переменные локальны, они сбрасываются при завершении функции. Тогда можно JS объявить, как static.

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

138

Re: AHK: Переводчик онлайн

Все-таки терзают смутные сомнения. Почему же тогда после выполнения кода

JS.eval("(" . MethodGetKeys . ")")

соответствующий метод остается в памяти объекта JS навсегда? Ведь на него нет никаких ссылок.

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

139

Re: AHK: Переводчик онлайн

teadrinker пишет:

соответствующий метод остается в памяти объекта JS навсегда? Ведь на него нет никаких ссылок.

Внешних ссылок нет, в контексте языка JScript есть — Object.prototype.GetKeys; если это свойство удалить/изменить, при сборке мусора метод должен быть убран из памяти.

140

Re: AHK: Переводчик онлайн

Спасибо, понятно.

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

141 (изменено: wisgest, 2014-01-02 05:12:58)

Re: AHK: Переводчик онлайн

teadrinker пишет:

Добавите в Коллекцию AHK?

Добавил: AHK: Выполненние JScript-кода с помощью WSC,
кратко упомянул в разделе WSH.

Есть ли замечания  и пожелания по теоретической части (изложение, название темы)?
Что касается примера, то это, на мой взгляд, не окончательный вариант. Я, скорее, просто занял место, и не исключено, что позже отредактирую тему. Какие будут замечания и пожелания по примерам?

(Возможно, имеет смысл перенести обсуждение в тему «COM-объект, умеющий исполнять JScript.»?)

--------------------
А нельзя ли для исполнения JS-кода воспользоваться JScript.dll напрямую?

А ещё в реестре есть:

[HKEY_CLASSES_ROOT\CLSID\{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}\Implemented Categories\{F0B7A1A1-9847-11CF-8F20-00805F2CD064}]

[HKEY_CLASSES_ROOT\CLSID\{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}\Implemented Categories\{F0B7A1A2-9847-11CF-8F20-00805F2CD064}]

[HKEY_CLASSES_ROOT\CLSID\{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}\InprocServer32]
@="C:\\WINDOWS\\system32\\jscript.dll"
"ThreadingModel"="Both"

[HKEY_CLASSES_ROOT\CLSID\{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}\OLEScript]

[HKEY_CLASSES_ROOT\CLSID\{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}\ProgID]
@="JScript"

— этим воспользоваться никак нельзя?

142

Re: AHK: Переводчик онлайн

wisgest пишет:

А нельзя ли для исполнения JS-кода воспользоваться JScript.dll напрямую?

Можно, если реализовать интерфейс IActiveScriptSite и передать его движку, а от него получить IActiveScript и IActiveScriptParse.

143

Re: AHK: Переводчик онлайн

Спасибо за отличную полезную програмку. Много много спасибо.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

144

Re: AHK: Переводчик онлайн

wisgest пишет:

Какие будут замечания и пожелания по примерам?

Пример

; Определим в прототипе JScript-массивов метод, возвращающий элемент по индексу:
JS.eval("Array.prototype.item = function (i) {return this[i];};")
MsgBox % "Первый телефон: " . obj.phoneNumbers.item(0)

не очень удачный, то же самое можно сделать без определения метода:

Loop % obj.phoneNumbers.length
   MsgBox, % (obj.phoneNumbers)[A_Index - 1]   ; в jscript массивы начинаются с нулевого индекса

В целом изложено хорошо, мне всё было понятно .

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

145

Re: AHK: Переводчик онлайн

teadrinker пишет:

то же самое можно сделать без определения метода

Учёл.

146

Re: AHK: Переводчик онлайн

Исправленный вариант переводчика:

#NoEnv
#SingleInstance, force
SetBatchLines, -1

if !A_IsCompiled
{
   if !FileExist(A_ScriptDir . "\Icons")
   {
      MsgBox, 4,, В директории скрипта отсутствует папка с иконками.`nЗагрузить с сервера?
      IfMsgBox, Yes
      {
         FileCreateDir, % A_ScriptDir "\Icons"
         TrayTip,, Идёт загрузка файлов с сервера`, подождите...
         if !Ping("content.screencast.com")
         {
            MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
            ExitApp
         }
         PreUrl := "http://content.screencast.com/users/teadrinker/folders/icons/media/"
         URLDownloadToFile, % PreUrl . "83188ad1-4a8a-491f-bf70-fb292e73c98c/Change.ico?downloadOnly=true"    , Icons\Change.ico
         URLDownloadToFile, % PreUrl . "57ced9ad-3ccc-4019-a9bd-6f86218f3dd9/Google.ico?downloadOnly=true"    , Icons\Google.ico
         URLDownloadToFile, % PreUrl . "4ed2cdc9-556f-4266-9b23-d8ec665c9b84/PlayPause.ico?downloadOnly=true", Icons\PlayPause.ico
         URLDownloadToFile, % PreUrl . "869c4c44-5e3a-470c-bed4-c8d2bcee621d/Stop.ico?downloadOnly=true"       , Icons\Stop.ico
         URLDownloadToFile, % PreUrl . "0ac5a584-d28c-4ca7-aac8-a45631a2e3c3/Translate.ico?downloadOnly=true", Icons\Translate.ico
         
         if !(FileExist("Icons\Change.ico") && FileExist("Icons\Google.ico") && FileExist("Icons\PlayPause.ico")
            && FileExist("Icons\Stop.ico") && FileExist("Icons\Translate.ico"))
         {
            TrayTip
            MsgBox, Не удалось завершить загрузку.`nЗагрузите папку вручную из аттача к теме на форуме
               ,`nпоместите её в директорию скрипта и запустите скрипт снова.
            ExitApp
         }
         else
         {
            Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
            TrayTip,, Загрузка успешно завершена!
            Sleep, 1500
            TrayTip
         }
      }
      else
      {
         MsgBox, Загрузите папку вручную из аттача к теме на форуме
            ,`nпоместите её в директорию скрипта и запустите скрипт снова.
         ExitApp
      }
   }
   Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
}

global  MAX_URL_LENGTH := 2076, IMAGE_ICON := 1, WM_INPUTLANGCHANGEREQUEST := 0x50
      , EVENT_SYSTEM_MOVESIZESTART := 0xA, EVENT_SYSTEM_MOVESIZEEND := 0xB
      , GUIs := [], LangArray := {}, Player, Voice := [], ColorGui := "Default", MainTransText
      , SIZING, Edit1HPos, Edit2HPos, Edit2YPos, Button2YPos, Button6YPos, Edit1FontSize, Edit2FontSize
      , IsControlPos, GetControlPos, ScriptPID, GuiActive, SaveSize, AllowMultiWindow
      , IniName := RegExReplace(A_ScriptName, "(.*\.).*", "$1ini")
   
Process, Exist
ScriptPID := ErrorLevel
InitLangArray()

Hotkey, IfWinActive
Hotkey, ~^vk43, HotkeyRun, Off
Hotkey, ~^Ins , HotkeyRun, Off

IniRead, Hotkey            , % IniName, Hotkey   , Hotkey               , C
IniRead, ShowWindowOnStart   , % IniName, Settings, ShowWindowOnStart   , 0
IniRead, SaveSize            , % IniName, Settings, SaveSize            , 0
IniRead, AllowMultiWindow   , % IniName, Settings, AllowMultiWindow   , 0
IniRead, Edit1FontSize      , % IniName, Location, Edit1FontSize      , 8
IniRead, Edit2FontSize      , % IniName, Location, Edit2FontSize      , 8

if InStr(Hotkey, "C")
   Hotkey, ~^vk43, On
if InStr(Hotkey, "Ins")
   Hotkey, ~^Ins, On

Menu, Tray, NoStandard

Menu, Tray, Add, Открыть, Open
Menu, Tray, Default, Открыть
Menu, Tray, Add

Menu, Tray, Add, Показывать окно при запуске, ShowWindowOnStart
if ShowWindowOnStart
   Menu, Tray, Check, Показывать окно при запуске

Menu, Tray, Add, Сохранять размеры окна, SaveSize
if SaveSize
   Menu, Tray, Check, Сохранять размеры окна

Menu, Tray, Add, Разрешить много окон, AllowMultiWindow
if AllowMultiWindow
   Menu, Tray, Check, Разрешить много окон

Menu, Tray, Add
Menu, Tray, Add, Использовать Ctrl+C+C, Hotkey
Menu, Tray, Add, Использовать Ctrl+Ins+Ins, Hotkey
if InStr(Hotkey, "C")
   Menu, Tray, Check, Использовать Ctrl+C+C
if InStr(Hotkey, "Ins")
   Menu, Tray, Check, Использовать Ctrl+Ins+Ins
Menu, Tray, Add

if !A_IsCompiled
{
   Menu, Tray, Add, Edit, Edit
   Menu, Tray, Add, Reload, Reload
   Menu, Tray, Add
}
Menu, Tray, Add, Выход, ExitApp

HWINEVENTHOOK := SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, 0
                                          , RegisterCallback("WinGetControlPos", "F"), 0, 0, 0)
OnExit, Exit

OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x111, "WM_COMMAND")
OnMessage(0x214, "WM_SIZING")

ShowWindowOnStart ? ShowTranslation("", "", "en", "ru")
Return

Open:
   if !WinExist("Google Translate ahk_pid" ScriptPID) || AllowMultiWindow
   ShowTranslation("", "", "en", "ru")
   return
   
ShowWindowOnStart:
AllowMultiWindow:
SaveSize:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   %A_ThisLabel% := !%A_ThisLabel%
   IniWrite, % %A_ThisLabel%, % IniName, Settings, %A_ThisLabel%
   return

Edit:
   Edit
   return
   
Reload:
   Reload
   return

Hotkey:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   
   if InStr(A_ThisMenuItem, "Ins")
      Hotkey := InStr(Hotkey, "Ins") ? RegExReplace(Hotkey, "Ins") : Hotkey . "Ins"
   if InStr(A_ThisMenuItem, "C+C")
      Hotkey := InStr(Hotkey, "C") ? RegExReplace(Hotkey, "C") : Hotkey . "C"
   
   Hotkey, ~^Ins, % InStr(Hotkey, "Ins") ? "On" : "Off"
   Hotkey, ~^vk43, % InStr(Hotkey, "C") ? "On" : "Off"
   
   IniWrite, % Hotkey, % IniName, Hotkey, Hotkey
   return

HotkeyRun:
   DoublePress()
   return
   
Exit:
   WinGet, List, List, % "Google Translate ahk_pid" ScriptPID
   Loop % List
   {
      if (List%A_Index% = GUIs.1)
      {
         IniWriteSizeGui(GUIs.1), SaveSize ? IniWriteSizeEdit(GUIs.1)
         break
      }
   }
   DllCall("UnhookWinEvent", Ptr, HWINEVENTHOOK)
   GUIs := LangArray := Voice := ""
ExitApp:
   ExitApp

^!vk56::SendInput, {Raw}%MainTransText%

#If WinActive("Google Translate ahk_pid" ScriptPID)
Esc::WinClose, A
Enter::ControlClick, Button4, % "Google Translate ahk_pid" ScriptPID

#If WinActive("Google Translate ahk_pid" ScriptPID) && NN := GetEditFocus()
^WheelUp::
^WheelDown::
   InStr(A_ThisHotkey, "Up") ? ++Edit%NN%FontSize : --Edit%NN%FontSize
   Edit%NN%FontSize < 6 ? Edit%NN%FontSize := 6
   Edit%NN%FontSize > 25 ? Edit%NN%FontSize := 25
   ToolTip % "FontSize = " . Edit%NN%FontSize
   
   Gui, % WinExist("A") . ":Default"
   Gui, Font, % "q5 s" . Edit%NN%FontSize, Verdana
   GuiControl, Font, Edit%NN%
   SetTimer, IniWriteFontSize, -500
   return
   
IniWriteFontSize:
   ToolTip
   IniWrite, %Edit1FontSize%, % IniName, Location, Edit1FontSize
   IniWrite, %Edit2FontSize%, % IniName, Location, Edit2FontSize
   return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400 And Clipboard
   {
      pressed1 := 0
      if (!(hwnd := WinExist("Google Translate ahk_pid" ScriptPID)) || AllowMultiWindow)
         GuiActive := GetActiveWindow(), Translate(RegExReplace(Clipboard, "\R", "`r`n"))
      else
         TranslateInTheSameWindow(hwnd, Clipboard)
   }   
   else
      pressed1 := 1
}

Translate(Sourse, ByRef _from="", ByRef _to="", NewWindow = 1)
{
   if !Ping("translate.google.com")
   {
      MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Sourse, "[А-Яа-я]")
      from := cyr ? "ru" : "auto", to := cyr ? "en" : "ru"
   }
   else
      from := _from, to := _to

   PreUrl := "http://translate.google.com/translate_a/t?client=x&sl=" . from . "&tl=" . to . "&text="
   Url := PreUrl . URIEncode(Sourse)

   if StrLen(Url) > MAX_URL_LENGTH
   {
      if RegExMatch(Sourse, "[\.\?!\n]")
      {
         StartPos := 1
         While StartPos := RegExMatch(Sourse, ".+?([\.\?!\r\n]+([ \t\r\n]*)|$)", Found, StartPos) + StrLen(Found)
         {
            Delimiter := Found2 ? Found2 : RegExReplace(Found, ".*(\s*)", "$1")
            Text := RegExReplace(Found, "(.*)\s*", "$1")
            Url := PreUrl . URIEncode(Text)
            if StrLen(Url) > MAX_URL_LENGTH
            {
               If RegExMatch(Text, "[,;:—\r\n]")
               {
                  PrevText := "", StartPos_ := 1

                  While StartPos_ := RegExMatch(Text, "(.+?)(([,;:—\.]+\s*)|$)", Found_, StartPos_) + StrLen(Found_)
                  {
                     txt := Found_1, dlmtr := Found_2

                     If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
                        TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from) . RegExReplace(PrevText, ".*(\s+)$", "$1")
                           . BreakdownByGaps(txt, PreUrl, from) . dlmtr, PrevText := ""

                     else If StrLen(PreUrl . URIEncode(txt . dlmtr . PrevText)) > MAX_URL_LENGTH
                        TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
                           . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

                     else
                        PrevText .= txt . dlmtr
                  }
                  TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
               }
               else
                  TransText .= BreakdownByGaps(Text, PreUrl, ByRef from)
               TransText .= Delimiter
            }
            else
               TransText .= GetTranslation(Url, from) . Delimiter
         }
      }
      else
         TransText := BreakdownByGaps(Sourse, PreUrl, ByRef from)
   }
   else
      TransText := GetTranslation(Url, from)
   
   If NewWindow
      ShowTranslation(Clipboard, TransText, from, to)
   else
   {
      _from := from, _to := to
      Return TransText
   }
}

BreakdownByGaps(Text, PreUrl, ByRef from)
{
   StartPos := 1
   While StartPos := RegExMatch(Text, "(.+?)([ \t]+|$)", Found, StartPos) + StrLen(Found)
   {
      txt := Found1, dlmtr := Found2
      If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= txt . dlmtr, PrevText := ""

      else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
            . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

      else
         PrevText .= txt . dlmtr
   }
   Return TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, IntegerFast, H
   Loop, % StrPutVar(Str, Var, "UTF-8")
   {
      Ch:=NumGet(Var, A_Index-1, "UChar")
      If Ch=0
         Break
      If (Ch>0x7f Or Ch<0x30 Or Ch=0x3d)
         s.="%"((StrLen(c:=SubStr(Ch, 3))<2) ? "0"c:c)
      else
         s.=Chr(Ch)
   }
   SetFormat, IntegerFast, % b_Format
   Return, s
}

GetTranslation(Url, byref from)
{
   static JS := GetObjJScript()
   
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      MsgBox, 16, Ошибка, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }
   if !RegExMatch(JsonTrans, "^\{.*sentences.*trans.*\}$")
   {
      MsgBox, 16, Ошибка, Неверный формат ответа от сервера.
      Return
   }

   oJSON := JS.eval("(" . JsonTrans . ")")
   
   Loop % oJSON.sentences.length
      trans .= (oJSON.sentences)[A_Index-1].trans
   MainTransText := FinishingText(trans)

   try Loop % oJSON.dict.length
   {
      dict .= "`n`n", i := 1
      oTerms := (oJSON.dict)[A_Index-1].terms
      Loop % oTerms.length
      {
         value := oTerms[A_Index-1]
         if value ~= "i)(*UCP)^" trans "$"
            continue
         dict .= (i++ = 1 ? "" : "; ") . value
      }
   }
   
   from := oJSON.src, dict := Trim(dict, "`n")
   Return FinishingText(trans . (dict ? "`n+`n" . dict : ""))
}

GetObjJScript()
{
   if !FileExist(WscPath := A_ScriptDir . "\JS.wsc")
      FileAppend,
      (LTrim
         <component>
         <public><method name='eval'/></public>
         <script language='JScript'></script>
         </component>
      ), % WscPath

   JS := ComObjGet("script:" . WscPath)
   JS.eval("delete ActiveXObject; delete GetObject;")
   Return JS
}

FinishingText(text)
{
   if RegExMatch(text, "\\u\d\d\d\d")
   {
      StartPos := 1
      While StartPos := RegExMatch(text, "\\u(\d\d\d\d)", Found, StartPos)
         text := RegExReplace(text, "\Q" Found "\E", Chr("0x" Found1)), StartPos++
   }
   text := RegExReplace(text, "\\r\\n", "`r`n")
 , text := RegExReplace(text, "\\(.)", "$1")
 , text := RegExReplace(text, " ``(.)", "$1" Chr(0x301))   ; обработка знака ударения
   Return text
}

WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}

StrPutVar(string, ByRef var, encoding = "CP0")
{
    ; Ensure capacity.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut returns char count, but VarSetCapacity needs bytes.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; Copy or convert the string.
    return StrPut(string, &var, encoding)
}

UrlDownloadToVar(URL, UserAgent = "", ProxyServer = "", UserName = "", Password = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ProxyServer ? WebRequest.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY := 2, ProxyServer)
   WebRequest.Open("GET", Url)
   ProxyServer ? WebRequest.SetCredentials(UserName, Password, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY := 1)
   UserAgent ? WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}

ShowTranslation(SourceText, TransText, from, to)
{
   static PlayPause1, PlayPause2, Stop1, Stop2, hGui, Control, ExChange1, ExChange2, Source
        , hIconPlayPause, hIconStop, hIconTranslate, hIconGoogle, hIconChange, Icons
        , hButtPlayPause1, hButtPlayPause2, hButtStop1, hButtStop2, hButtTranslate, hButtChange1, hButtChange2
        , BS_ICON := 0x40, WM_SETICON := 0x80, BM_SETIMAGE := 0xF7, ES_NOHIDESEL := 0x100
        , WMSZ_TOP := 3, WMSZ_TOPLEFT := 4, WMSZ_TOPRIGHT := 5

   Gui, New, +AlwaysOnTop +LastFound +Resize +hwndhGui +Owner +MinSize199x220 -MaximizeBox
   Gui, Color, %ColorGui%
   
   oSize := IniReadSizeEdit()
   if (SaveSize && Edit1H := oSize.Edit1H)
      Edit1W := oSize.Edit1W, Edit2H := oSize.Edit2H
   
   Gui, Font, q5 s8, Verdana
   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y15", Исходный язык:

   SourceLangNames := TargetLangNames := ""
   For k,v In LangArray
      SourceLangNames .= (A_Index = 1 ? "" : "|") . k . (v = from ? "|" : "")
    , TargetLangNames .= (A_Index = 1 ? "" : "|") . k . (v = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % SourceLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange1 gExchangeLang vExChange1"

   Gui, Font, q5 s%Edit1FontSize%, Verdana
   if !(SaveSize && Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL% vSource, % SourceText
      GuiControlGet, Edit1, Pos
      
      Edit1H < 45 ? Edit1H := 45
      Edit1H > 250 ? Edit1H := 250
      GuiControl, Move, Edit1, h%Edit1H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit1H " vSource " ES_NOHIDESEL, % SourceText

   GuiControlGet, Edit1, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit1Y + Edit1H + 5 " w52 h23 hwndhButtPlayPause1 gPlayPause vPlayPause1 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop1 gStop vStop1" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 " BS_ICON " hwndhButtTranslate gTranslate"

   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y+20", Язык перевода:

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % TargetLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange2 gExchangeLang vExChange2"

   Gui, Font, q5 s%Edit2FontSize%, Verdana
   if !(SaveSize && Edit1H := oSize.Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL%, % TransText
      GuiControlGet, Edit2, Pos
      
      Edit2H < 45 ? Edit2H := 45
      Edit2H > 250 ? Edit2H := 250
      GuiControl, Move, Edit2, h%Edit2H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit2H " " ES_NOHIDESEL, % TransText

   GuiControlGet, Edit2, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit2Y + Edit2H + 5 " w52 h23 hwndhButtPlayPause2 gPlayPause vPlayPause2 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop2 gStop vStop2" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 gGuiClose", OK

   if !IsObject(Icons)
   {
      hIconGoogle    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 1, 24) : ExtractIcon(A_ScriptDir "\Icons\Google.ico"    , 1, 24)
      hIconChange    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 2, 16) : ExtractIcon(A_ScriptDir "\Icons\Change.ico"    , 1, 16)
      hIconPlayPause := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 3, 25) : ExtractIcon(A_ScriptDir "\Icons\PlayPause.ico", 1, 25)
      hIconStop       := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 4, 12) : ExtractIcon(A_ScriptDir "\Icons\Stop.ico"       , 1, 12)
      hIconTranslate := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 5, 16) : ExtractIcon(A_ScriptDir "\Icons\Translate.ico", 1, 16)
      Icons := [hIconGoogle, hIconChange, hIconPlayPause, hIconStop, hIconTranslate]
   }

   DetectHiddenWindows, On
   Loop 2
   {
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconChange      ,, % "ahk_id" hButtChange%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconPlayPause   ,, % "ahk_id" hButtPlayPause%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconStop         ,, % "ahk_id" hButtStop%A_Index%
   }
   PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconTranslate,, ahk_id %hButtTranslate%
   PostMessage, WM_SETICON,, hIconGoogle,, ahk_id %hGui%
   PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[from = "ru" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   DetectHiddenWindows, Off
   
   GuiControlGet, Button8, Pos
   Gui, Show, % "hide h" Button8Y + Button8H + 6, Google Translate
   GuiControl, Focus, Edit1

   if !WinExist("Google Translate ahk_pid" ScriptPID)
   {
      IniRead, xGUI, % IniName, Location, xGUI, % " "
      IniRead, yGUI, % IniName, Location, yGUI, % " "
      Gui, Show, % (xGUI = "" ? "" : "x" xGUI " y" yGUI " ") "w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   else
   {
      WinGetPos, X, Y,,, % "ahk_id " (GuiActive ? GuiActive : GUIs[GUIs.MaxIndex()])
      Gui, Show, % "x" X + 60 " y" Y + 40 " w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   GUIs.Insert(hGui), GuiActive := ""
   Return
   
GuiSize:
   if !IsControlPos
      return

   SetWinDelay, 0
   if (SIZING ~= WMSZ_TOP "|" WMSZ_TOPLEFT "|" WMSZ_TOPRIGHT)
   {
      if A_GuiHeight - Edit1HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      }
   }
   else
   {
      if A_GuiHeight - Edit2HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      }
   }
   return

PlayPause:
   if IsObject(Player)
   {
      if Playing := !Playing
         Player.Controls.pause()
      else
         Player.Controls.play()
   }
   else
   {
      hGui := A_Gui, Control := A_GuiControl
      SetTimer, PlayPauseTimer, -1
   }
   return

PlayPauseTimer:
   n := SubStr(Control, 0)
   ControlGet, Text, Selected,, Edit%n%, ahk_id %hGui%
   if (Text = "")
      ControlGetText, Text, Edit%n%, ahk_id %hGui%
   ControlGetText, lng, ComboBox%n%, ahk_id %hGui%
   Say(RegExReplace(Text, "\R+", "`n"), LangArray[lng])
   return

Stop:
   Player.close()
   Playing := Player := ""
   StopButtonEnableDisable(0)
   return

ExchangeLang:
   GuiControlGet, to,, ComboBox1
   GuiControlGet, from,, ComboBox2
   
   SourceLangNames := TargetLangNames := ""
   for k In LangArray
      SourceLangNames .= "|" . k . (k = from ? "|" : "")
    , TargetLangNames .= "|" . k . (k = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")
   
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl, Focus, Edit1
   return
   
Translate:
   GuiControlGet, from,, ComboBox1
   from := LangArray[from]
   GuiControlGet, to,, ComboBox2
   to := LangArray[to]
   GuiControlGet, SourseText,, Edit1
   TransText := Translate(RegExReplace(SourseText, "\R", "`r`n"), from, to, 0)

   GuiControl,, Edit2, % TransText
   GuiControl, Focus, Edit1
   Return

GuiClose:
   if (A_Gui = GUIs.1)
      IniWriteSizeGui(A_Gui), SaveSize ? IniWriteSizeEdit(A_Gui)
   else
   {
      for k,v in GUIs
         if (A_Gui = v)
            break
      GUIs.Remove(k)
   }
   
   Gui, %A_Gui%: Destroy
   IfWinNotExist, Google Translate ahk_pid %ScriptPID%
   {
      Player.close(), Player := "", Voice := []
      FileDelete, % A_ScriptDir "\mp3\*.mp3"
      Loop % Icons.MaxIndex()
         DllCall("DestroyIcon", Ptr, Icons[A_Index])
      Icons := "", GUIs := []
   }
   return
}

TranslateInTheSameWindow(hwnd, SourceText)
{
   Translation := Translate(RegExReplace(SourceText, "\R", "`r`n"), from, to, 0)

   For k,v In LangArray
      SourceLangNames .= "|" . k . (v = from ? "|" : "")
    , TargetLangNames .= "|" . k . (v = to   ? "|" : "")
   
   Gui, %hwnd%:Default
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl,, Edit1, % SourceText
   GuiControl,, Edit2, % Translation
}

Resizing(W, H, mode)
{
   E1H := H - Edit1HPos
   E2Y := H - Edit2YPos, E2H := H - Edit2HPos
   B2Y := H - Button2YPos, B6Y := H - Button6YPos

   if mode = 1
   {
      GuiControl, Move, Edit1, % "w" W - 20 " h" E1H
      GuiControl, Move, Edit2, % "w" W - 20 " y" E2Y
      GuiControl, MoveDraw, Button2, % "y" B2Y
      GuiControl, MoveDraw, Button3, % "y" B2Y
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120) " y" B2Y
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10) " y" B2Y + 43
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112) " y" B2Y + 39
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297) " y" B2Y + 38
   }
   else
   {
      GuiControl, Move, Edit1, % "w" W - 20
      GuiControl, Move, Edit2, % "w" W - 20 " h" (E2H > 32 ? E2H : 32)
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120)
   }
   GuiControl, Move, Static1, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
   GuiControl, Move, ComboBox1, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
   GuiControl, MoveDraw, Button1, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
   GuiControl, MoveDraw, Button6, % "y" B6Y
   GuiControl, MoveDraw, Button7, % "y" B6Y
   GuiControl, MoveDraw, Button8, % "x" (W > 200 ? W - 80 : 120) " y" B6Y
}

InitLangArray()
{
   Languages =
   (LTrim C
      Азербайджанский|az
      Албанский|sq
      Английский|en
      Арабский|ar
      Армянский|hy
      Африкаанс|af
      Баскский|eu
      Белорусский|be
      Болгарский|bg
      Венгерский|hu
      Вендский|sb
      Вьетнамский|vi
      Голландский|nl
      Греческий|el
      Грузинский|ka
      Датский|da
      Иврит|he
      Идиш|ji
      Индонезийский|id
      Исландский|is
      Испанский|es
      Итальянский|it
      Каталонский|ca
      Китайский|zh
      Китайский (Аомынь)|zh-cn
      Китайский (Тайвань)|zh-tw
      Корейский|ko
      Латынь|la
      Латышский|lv
      Литовский|lt
      Македонский|mk
      Малайский|ms
      Мальтийский|mt
      Немецкий|de
      Норвежский|no
      Польский|pl
      Португальский|pt
      Румынский|ro
      Русский|ru
      Сербский|sr
      Словацкий|sk
      Словенский|sl
      Суахили|sw
      Тайский|th
      Турецкий|tr
      Украинский|uk
      Урду|ur
      Фарси|fa
      Финский|fi
      Французский|fr
      Хинди|hi
      Хорватский|hr
      Чешский|cs
      Шведский|sv
      Эсперанто|eo
      Эстонский|et
      Японский|ja
   )

   Loop, parse, Languages, `n, `r
   {
      Key := RegExReplace(A_LoopField, "(.*)\|.*", "$1")
      Value := RegExReplace(A_LoopField, ".*\|(.*)", "$1")
      LangArray[Key] := Value
   }
}

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   if (ext = "ico")
      IconNumber := 0

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Указанный файл не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge)
         , hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall)
         , hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

Ping(strHost)
{
   Loop 4
      bRet := ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
   until bRet
   return bRet
}

Say(Text, lng)
{
   static PlaylistOpenNoMedia := 6, Stopped := 1
   
   Player := ComObjCreate("WMPlayer.OCX")
   objPlaylist := Player.currentPlaylist

   for k,v in Voice
      if (v.Text = RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1") && v.lng = lng)
      {
         var := 1
         break
      }

   if var
   {
      Loop % v.mp3.MaxIndex()
         objPlaylist.appendItem(Player.newMedia(v.mp3[A_Index]))
   }
   else
   {
      if !Ping("translate.google.com")
      {
         MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
         Return
      }

      PreUrl := "http://translate.google.com/translate_tts?ie=UTF-8&tl=" lng "&q="
      Strings := []
      If StrLen(Text) > 100
      {
         StartPos := 1
         While StartPos := RegExMatch(Text, ".+?(\.|$)", Found, StartPos) + StrLen(Found)
         {
            if StrLen(Found) > 100
            {
               StartPos_ := 1
               While StartPos_ := RegExMatch(Found, "(.{1,99}([ ,\t\n]|$))|(.{1,100})", Found_, StartPos_) + StrLen(Found_)
                  Strings.Insert(Found_)
            }
            else
               Strings.Insert(Found)
         }
      }
      else
         Strings.1 := Text

      if !FileExist(A_ScriptDir "\mp3")
         FileCreateDir, %A_ScriptDir%\mp3

      Voice.Insert(o := {Text: RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1"), lng: lng, mp3: []})
      Loop % count := Strings.MaxIndex()
      {
         URLDownloadToFile, % PreUrl . URIEncode(RegExReplace(Strings[A_Index], "^\s*([^\s]+)\s*$", "$1"))
            , % mp3file := A_ScriptDir "\mp3\" A_TickCount ".mp3"
         objPlaylist.appendItem(Player.newMedia(mp3file))
         o.mp3.Insert(mp3file)
      }
   }
   StopButtonEnableDisable(1)
   Player.Controls.play()
   While Player.PlayState != Stopped && Player.OpenState != PlaylistOpenNoMedia && IsObject(Player)
      Sleep, 100
   Player.close(), Player := objPlaylist := ""
   StopButtonEnableDisable(0)
}

StopButtonEnableDisable(key)
{
   WinGet, List, List, Google Translate ahk_pid %ScriptPID%
   Loop % List
   {
      Control , % key ? "Enable" : "Disable",, Button3, % "ahk_id" List%A_Index%
      Control , % key ? "Enable" : "Disable",, Button7, % "ahk_id" List%A_Index%
   }
}

WM_COMMAND(wp, lp)
{
   static EN_SETFOCUS := 0x100, CBN_SETFOCUS := 3
   
   if !WinActive("Google Translate") || !(wp>>16 = EN_SETFOCUS || wp>>16 = CBN_SETFOCUS)
      return
   
   Gui, %A_Gui%:Default
   DetectHiddenWindows, On
   
   if (wp>>16 = EN_SETFOCUS)
   {
      GuiControlGet, Name, Name, %lp%
      if Name != Source
         return
      
      GuiControlGet, lang,, ComboBox1
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[lang = "Русский" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   }
   
   if (wp>>16 = CBN_SETFOCUS)
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList().Ru,, ahk_id %A_ScriptHwnd%
   
   DetectHiddenWindows, Off
}

GetLayoutList()
{
   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
   SetFormat, IntegerFast, D
   Return {En: En, Ru: Ru}
}

WM_SIZING(wp)
{
   SIZING := wp
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin, UInt, eventMax
                                    , Ptr, hmodWinEventProc, Ptr, lpfnWinEventProc
                                    , UInt, idProcess, UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

WinGetControlPos(hWinEventHook, event, hwnd)
{
   if !GetActiveWindow()
      return
   
   if (event = EVENT_SYSTEM_MOVESIZEEND)
      IsControlPos := GetControlPos := "", CorrectPos(hwnd)
   else
      _WinGetControlPos(hwnd)
}

_WinGetControlPos(hwnd)
{
   Gui, %hwnd%:Default
   
   GuiControlGet, Edit1, Pos
   GuiControlGet, Edit2, Pos
   GuiControlGet, Button2, Pos
   GuiControlGet, Button6, Pos
   
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")

   Edit1HPos := ClientH - Edit1H
   Edit2HPos := ClientH - Edit2H
   Edit2YPos := ClientH - Edit2Y
   Button2YPos := ClientH - Button2Y
   Button6YPos := ClientH - Button6Y
   IsControlPos := 1
}

CorrectPos(hwnd)
{
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")
   
   Gui, %hwnd%:Default
   GuiControlGet, Edit2, Pos
   GuiControl, Move, Edit2, % "h" ClientH - Edit2Y - 34
   
   Loop 3
      GuiControl, MoveDraw, % "Button" A_Index + 5, % "y" ClientH - 29
}

GetActiveWindow()
{
   WinGetActiveTitle, Title
   WinGetClass, Class, A
   WinGet, PID, PID, A
   Return (Title = "Google Translate" && Class = "AutoHotkeyGUI" && PID = ScriptPID) ? WinExist("A") : ""
}

IniReadSizeEdit()
{
   IniRead, Edit1W, % IniName, Location, Edit1W, % " "
   IniRead, Edit1H, % IniName, Location, Edit1H, % " "
   IniRead, Edit2H, % IniName, Location, Edit2H, % " "
   Return {Edit1W: Edit1W, Edit1H: Edit1H, Edit2H: Edit2H}
}

IniWriteSizeEdit(hwnd)
{
   ControlGetPos,,, Edit1W, Edit1H, Edit1, % "ahk_id" hwnd
   ControlGetPos,,,, Edit2H, Edit2, % "ahk_id" hwnd
   
   IniWrite, % Edit1W, % IniName, Location, Edit1W
   IniWrite, % Edit1H, % IniName, Location, Edit1H
   IniWrite, % Edit2H, % IniName, Location, Edit2H
}

IniWriteSizeGui(hwnd)
{
   WinGetPos, X, Y,,, % "ahk_id" hwnd
   IniWrite, % X, % IniName, Location, xGUI
   IniWrite, % Y, % IniName, Location, yGUI
}

GetEditFocus()
{
   if !WinActive("Google Translate ahk_pid" ScriptPID)
      return
   
   ControlGetFocus, Control, A
   return InStr(Control, "Edit") ? SubStr(Control, 0) : ""
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

147

Re: AHK: Переводчик онлайн

не работает (

148

Re: AHK: Переводчик онлайн

global  MAX_URL_LENGTH := 2076, IMAGE_ICON := 1, WM_INPUTLANGCHANGEREQUEST := 0x50
      , EVENT_SYSTEM_MOVESIZESTART := 0xA, EVENT_SYSTEM_MOVESIZEEND := 0xB
      , GUIs := [], LangArray := {}, Player, Voice := [], ColorGui := "Default", MainTransText
      , SIZING, Edit1HPos, Edit2HPos, Edit2YPos, Button2YPos, Button6YPos, Edit1FontSize, Edit2FontSize
      , IsControlPos, GetControlPos, ScriptPID, GuiActive, SaveSize, AllowMultiWindow
      , IniName := RegExReplace(A_ScriptName, "(.*\.).*", "$1ini")

This line does not contain a recocnized action.

149

Re: AHK: Переводчик онлайн

niceice, ознакомьтесь с этой темой, отредактируйте свои посты. Заодно, если будете внимательно читать, и решение своей проблемы найдёте.

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

150

Re: AHK: Переводчик онлайн

Спасибо за очень полезный скрипт.
А может кто-то помочь чуть-чуть его изменить.
Интересует запрос не в гугл а в установленный на компе Abby Lingvo.

P.S. Сам пока только-только начал разбираться с написанием скриптов...

151

Re: AHK: Переводчик онлайн

А что вы хотите получить в ответ? Чтобы посылать какие-либо запросы в базу данных Lingvo, нужно знать, как она устроена, боюсь, что это никак не документировано.

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

152 (изменено: stp, 2015-02-23 11:52:56)

Re: AHK: Переводчик онлайн

teadrinker пишет:

А что вы хотите получить в ответ? Чтобы посылать какие-либо запросы в базу данных Lingvo, нужно знать, как она устроена, боюсь, что это никак не документировано.

Ну если грубо - то это же обыкновенное окно.
В него можно положить текст, нажать кнопку и получить ответ.

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

153

Re: AHK: Переводчик онлайн

stp, не нужно бессмысленно цитировать предыдущий пост.
Честно говоря, не совсем вас понял. О каком окне сейчас идёт речь? Вы хотите получить текст из окна Lingvo с переводом слова?

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

154

Re: AHK: Переводчик онлайн

2stp: Для Lingvo я использую скрипт, который копирует выделенное слово(если есть), кликает по иконке в трее и вставляет в появившееся окно.
Если надо, выложу.

Для разных вариантов перевода онлайн
использую програмку QTranslate, попробуйте, там кликом по вкладке можно выбрать сервис перевода - google, microsoft, yandex, etc?

155

Re: AHK: Переводчик онлайн

stealzy пишет:

Если надо, выложу.

Буду очень благодарен!

156

Re: AHK: Переводчик онлайн

Опять перестало переводить. Наверное опять что-то изменили Гугловцы. Поправте скритп пожалуста. Плачут мышка и клава.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

157

Re: AHK: Переводчик онлайн

Здравствуйте!
Тут плохие новости. Google, видимо что-то поменяли у себя и теперь строка

 PreUrl := "http://translate.google.com/translate_a/t?client=x&sl=" . from . "&tl=" . to . "&text="

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

158

Re: AHK: Переводчик онлайн

Ага, перестало. Но теперь, боюсь, вернуть к жизни будет непросто. «Гугловцы» стали капчу посылать в ответ на фейковую строку с ЮзерАгентом, буду думать. Тут где-то serzh82saratov свой вариант выкладывал со страницей переводчика в ActiveX контроле, пользуйтесь пока им.

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

159

Re: AHK: Переводчик онлайн

teadrinker пишет:

Ага, перестало. Но теперь, боюсь, вернуть к жизни будет непросто. «Гугловцы» стали капчу посылать в ответ на фейковую строку с ЮзерАгентом, буду думать. Тут где-то serzh82saratov свой вариант выкладывал со страницей переводчика в ActiveX контроле, пользуйтесь пока им.

Вы имеете ввиду сообщение #108 в этой теме? Он не работает, при попытке запуска ругается на первый символ входящего объекта "<"! Надеюсь на успешную реанимацию вашего варианта, он был чудесным!

160

Re: AHK: Переводчик онлайн

Нет, имею в виду этот вариант. Если что-то не работает, обновите AHK.

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

161

Re: AHK: Переводчик онлайн

teadrinker пишет:

Нет, имею в виду этот вариант. Если что-то не работает, обновите AHK.

Спасибо большое! да, работает. Не так удобно, конечно, но хотя бы что-то. С нетерпением жду новостей о реанимации Вашего скрипта!

162

Re: AHK: Переводчик онлайн

Кстати, что посоветуете, чтобы было удобнее?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

163

Re: AHK: Переводчик онлайн

По-крайней мере, добавить Ctrl+C+C, что я для себя уже сделал.

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

164

Re: AHK: Переводчик онлайн

Я не в теме, что это?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

165

Re: AHK: Переводчик онлайн

Традиционное сочетание для перевода среди пользователей программы-переводчика Abbyy Lingvo, она довольно популярна.

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

166

Re: AHK: Переводчик онлайн

А, в смысле "запускающая", ну это кому как удобно, я назначение "своих" хоткеев в скрипте не отменял.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

167

Re: AHK: Переводчик онлайн

Так я у тебя не нашел, как поместить выделенное слово в окно в один прием.

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

168

Re: AHK: Переводчик онлайн

А, сорри, фишка чтобы само копировало. Теперь понял.
Ну а вообще советы по поводу отображения сайта, есть? Что там убрать, добавить, для удобства.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

169

Re: AHK: Переводчик онлайн

Главное, чего нехватает — автоматический выбор направления перевода.

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

170

Re: AHK: Переводчик онлайн

Это я знаю, изначально не одолел решение этой проблемы, далее не было времени.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

171

Re: AHK: Переводчик онлайн

Похоже, мой переводчик всё. serzh82saratov, в своём скрипте я определял направление перевода просто: если в исходном слове есть кириллица — переводим на английский, если нет — на русский.

lang := RegExMatch(Clipboard, "i)(*UCP)[а-я]") ? "en" : "ru"
URL = https://translate.google.ru/#auto/%lang%/
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

172

Re: AHK: Переводчик онлайн

Да это понятно,  тут проблема в html.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

173

Re: AHK: Переводчик онлайн

Какая? Я уже под себя почти переписал, всё работает, попозже могу выложить.

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

174

Re: AHK: Переводчик онлайн

Да я уже не помню в чём там у меня был вопрос. Ну а своё конечно выкладывай.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

175

Re: AHK: Переводчик онлайн

Ага, причёсываю. Хочу добавить выделение текста по Ctrl + A, не могу найти как.

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

176

Re: AHK: Переводчик онлайн


^vk41:: oDoc.execCommand("SelectAll")                        ;  Ctrl+A
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

177 (изменено: teadrinker, 2015-04-12 17:19:36)

Re: AHK: Переводчик онлайн

Спасибо! Пока так:

#NoEnv
#SingleInstance Force
Menu, Tray, Icon, Shell32.dll, 239
SetBatchLines -1
SetWinDelay, 0
param = %1%   ; для автозагрузки с параметром "hide"
(param != "" && param != "hide" && param := "")
oGT := new GoogleTranslator(param)
Return

~^vk43::   ; Ctrl + C
   if (A_PriorHotkey = "~^vk43" && A_TimeSincePriorHotkey < 400 && Clipboard)   ; Ctrl + C + C
      oGT.Update()
   else if WinActive("ahk_id" oGT.hGui)
      oGT.SelRng.execCommand("COPY")
   Return
   
#If WinActive("ahk_id" oGT.hGui)
Enter:: rng := oGT.SelRng, rng.text := "`n", rng.select()
Del::   rng := oGT.SelRng
     , (rng.text = "" && rng.moveEnd("character", 1))
     ,  rng.execCommand("DELETE")
^vk41:: oGT.doc.execCommand("SELECTALL")   ; Ctrl + A
^vk56:: oGT.SelRng.execCommand("PASTE")    ; Ctrl + V
^vk58:: oGT.SelRng.execCommand("CUT")      ; Ctrl + X
^vk59:: oGT.doc.execCommand("REDO")        ; Ctrl + Y
^vk5A:: oGT.doc.execCommand("UNDO")        ; Ctrl + Z

class GoogleTranslator
{
   __New(param)  {
      TrayTip, GoogleTranslator, Запуск
      FixIE(0)
      this.oIE := CreateGui(hGui, hIE), this.hGui := hGui
      CreateMenu(hGui, Func("_GuiClose").Bind(hGui))
      OnMessage(0x5, Func("WM_SIZE").Bind(hIE))
      this.Update(param)
      Gui Show, % "w1000 h436 " . param, GoogleTranslator
      TrayTip
   }
   
   __Get(key)  {
      if (key = "doc")
         Return this.oIE.document
      if (key = "SelRng")
         Return this.oIE.document.selection.createRange()
   }
   
   __Delete()  {
      this.oIE.Quit()
   }
   
   Update(NoShow = "")  {
      language := RegExMatch(Clipboard, "i)[а-я]") ? "en" : "ru"
      this.oIE.Navigate("https://translate.google.ru/#auto/" . language)
      While !(this.oIE.readyState = (READYSTATE_COMPLETE := 4) && this.doc.readyState = "complete" && !this.oIE.busy)
        Sleep, 50
        
      for k, id in ["gt-appbar", "ft-r", "gt-ft-mkt", "gb", "gt-logo"]
         this.doc.querySelector("#" id).style.display := "none"
      
      this.doc.querySelector("#source").value := Clipboard
      Gui, Show, % NoShow
   }
}

CreateGui(ByRef hGui, ByRef hIE)
{
   static IE
   Gui +ReSize -DPIScale +HWNDhGui +Owner  
   Gui Add, ActiveX, w1000 h436 vIE hwndhIE, Shell.Explorer   
   IE.Silent := 1, ComObjError(false)
   Return IE
}

CreateMenu(hGui, GuiClose)
{
   Menu, Tray, UseErrorLevel
   Menu, Tray, NoStandard
   Menu, Tray, Click, 1
   Menu, Tray, Add, Hide/Show, % GuiClose
   Menu, Tray, Add, ExitApp
   Menu, Tray, Default, Hide/Show
}

WM_SIZE(hIE, wp, lp)
{
   if (wp = SIZE_MINIMIZED := 1)
      _GuiClose(hIE)
   else
      WinMove, ahk_id %hIE%,, 0, 0, lp & 0xFFFF, lp >> 16
}

_GuiClose(hGui)
{
   Gui, Show, % WinExist("ahk_id" hGui) ? "Hide" : ""
}

GuiEscape()
{
   Gui, Show, Hide
}

ExitApp()
{
   ExitApp
}

FixIE(Fix)
{
   Static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
   If A_IsCompiled
     ExeName := A_ScriptName
   Else
     SplitPath, A_AhkPath, ExeName
   If Fix
     RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, 0
   Else
     RegDelete, HKCU, %Key%, %ExeName%
}

Хотел ради интереса сделать без глобальных переменных. Добавил считывание параметра ("hide") для автозагрузки в свёрнутом виде. Убрал кнопку «Перевести» за ненадобностью.

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

178

Re: AHK: Переводчик онлайн

Добавил ещё строку с исходным языком. Он ведь не всегда русский или английский.

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

179

Re: AHK: Переводчик онлайн

Прикольно. Лично мне тут не хватает кнопки - заменить поле ввода буфером обмена.
Кстати, что значит в RegExMatch - (*UCP)?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

180

Re: AHK: Переводчик онлайн

Убрал кнопку «Перевести» за ненадобностью.

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

181

Re: AHK: Переводчик онлайн

Здесь можно без (*UCP), просто автоматически вставил. Вообще нужно для определения кириллицы в таких случаях:

MsgBox, % RegExMatch("||текст||", "\w+")
MsgBox, % RegExMatch("||текст||", "(*UCP)\w+")
serzh82saratov пишет:

Лично мне тут не хватает кнопки - заменить поле ввода буфером обмена.

По Ctrl + C + C заменяется.

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

Ясно, можно вернуть. Это, естественно, ещё рабочий вариант.

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

182

Re: AHK: Переводчик онлайн

Добавил обработку Ctrl + Z и Delete, кнопку «Перевести» вернул.

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

183

Re: AHK: Переводчик онлайн

И ещё Ctrl + Y (Redo).

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

184 (изменено: k2, 2015-04-12 05:41:52)

Re: AHK: Переводчик онлайн

Предложенный новый скрипт у меня не работает, наверное по причине IE6.
А в Опере у меня почему-то продолжает безо всяких изменений работать старинный яваскрипт google-translate.js версии 1.7.7, это не пригодится? На всякий случай: он зачем-то использует гугловский  light--proxy.appspot.com. И поздние версии, но их не пробовал.

185

Re: AHK: Переводчик онлайн

Совсем не работает? А пример отсюда работает?

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

186

Re: AHK: Переводчик онлайн

Исправлена обработка клавиши Delete, добавлена Enter.

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

187 (изменено: k2, 2015-04-12 23:08:25)

Re: AHK: Переводчик онлайн

Примеры из справки работают! А из переводчик из n.177 -  "Невозможно отобразить страницу".  Выяснил, что если из IE открыть https://translate.google.ru , появляется сообщение: "Не удаётся открыть узел, опреция прервана".  https://google.ru открывается. Всё же IE6 устарел, наверное.

Интересно, что сначала из-за несуществующей у меня иконки n. 239 выдавало ошибку,  я её игнорировал (поскольку вроде нефатальная и скрипт запускался) - а, оказывается, в таком состоянии скрипт не только не прописывает пункты меню, но и вообще ничего не делает. Из-за несуществующей иконки скрипт ломается.  teadrinker, посмотрите, пожалуйста, мой вопрос в cmd/bat.

188

Re: AHK: Переводчик онлайн

Да, иконку надо заменить. По вопросу из CMD не в курсе.

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

189 (изменено: teadrinker, 2015-04-16 15:18:22)

Re: AHK: Переводчик онлайн

Добавлена иконка в скрипт текстом, добавлена проверка на версию IE, и несколько пунктов трей-меню.

#NoEnv
#SingleInstance Force
SetBatchLines -1
SetWinDelay, 0
CreateTrayIconFromBase64()

if !VerifyIeVersion(7)   ; 7 версия IE — минимально поддерживаемая (6 не поддерживается, 7 — не проверялась)
   ExitApp

param = %1%   ; для автозагрузки с параметром "hide"
oGT := new GoogleTranslator(param)
Return

~^vk43::   ; Ctrl + C
   if (A_PriorHotkey = "~^vk43" && A_TimeSincePriorHotkey < 400 && Clipboard)   ; Ctrl + C + C
      oGT.Update()
   else if WinActive("ahk_id" oGT.hGui)
      oGT.SelRng.execCommand("COPY")
   Return
   
#If WinActive("ahk_id" oGT.hGui)
Enter:: rng := oGT.SelRng, rng.text := "`n", rng.select()
Del::   rng := oGT.SelRng
     , (rng.text = "" && rng.moveEnd("character", 1))
     ,  rng.execCommand("DELETE")
^vk41:: oGT.doc.execCommand("SELECTALL")   ; Ctrl + A
^vk56:: oGT.SelRng.execCommand("PASTE")    ; Ctrl + V
^vk58:: oGT.SelRng.execCommand("CUT")      ; Ctrl + X
^vk59:: oGT.doc.execCommand("REDO")        ; Ctrl + Y
^vk5A:: oGT.doc.execCommand("UNDO")        ; Ctrl + Z

class GoogleTranslator
{
   __New(param)  {
      (param != "" && param != "hide" && param := "")
      
      TrayTip, GoogleTranslator, Запуск
      FixIE(0)
      
      this.oIE := CreateGui(hGui, hIE, hIcon16, hIcon32)
      this.hGui := hGui, this.hIcon16 := hIcon16, this.hIcon32 := hIcon32
      OnMessage(0x5, Func("WM_SIZE").Bind(hIE))
      
      CreateMenu(hGui, Func("_GuiClose").Bind(hGui))
      
      this.Update(param)
      Gui Show, % "w1000 h436 " . param, GoogleTranslator
      TrayTip
   }
   
   __Get(key)  {
      if (key = "doc")
         Return this.oIE.document
      if (key = "SelRng")
         Return this.oIE.document.selection.createRange()
   }
   
   __Delete()  {
      DllCall("DestroyIcon", Ptr, this.hIcon16)
      DllCall("DestroyIcon", Ptr, this.hIcon32)
      this.oIE.Quit()
   }
   
   Update(NoShow = "")  {
      language := RegExMatch(Clipboard, "i)[а-я]") ? "en" : "ru"
      this.oIE.Navigate("https://translate.google.ru/#auto/" . language)
      While !(this.oIE.readyState = (READYSTATE_COMPLETE := 4) && this.doc.readyState = "complete" && !this.oIE.busy)
        Sleep, 50
        
      for k, id in ["gt-appbar", "ft-r", "gt-ft-mkt", "gb", "gt-logo"]
         elem := this.doc.querySelector("#" id), elem.parentNode.removeChild(elem)

      for k, ClassName in ["gt-community-promo-img", "gt-community-promo-text"]
         elem := this.doc.getElementsByClassName(ClassName)[0], elem.parentNode.removeChild(elem)
      
      this.doc.querySelector("#source").value := Clipboard
      Gui, Show, % NoShow
   }
}

CreateGui(ByRef hGui, ByRef hIE, ByRef hIcon16, ByRef hIcon32)
{
   static IE, WM_SETICON := 0x80, ICON_SMALL := 0, ICON_BIG := 1
   
   Gui +ReSize -DPIScale +hwndhGui +Owner  
   Gui Add, ActiveX, w1000 h436 vIE hwndhIE, Shell.Explorer
   IE.Silent := 1, ComObjError(false)
   
   hIcon16 := CreateIconFromBase64(GetBase64String(16), 16)
   hIcon32 := CreateIconFromBase64(GetBase64String(32), 32)
   DllCall("SendMessage", Ptr, hGui        , UInt, WM_SETICON, Ptr, ICON_SMALL, Ptr, hIcon16, Ptr)
   DllCall("SendMessage", Ptr, A_ScriptHwnd, UInt, WM_SETICON, Ptr, ICON_BIG  , Ptr, hIcon32, Ptr)
   Return IE
}

CreateMenu(hGui, GuiClose)
{
   Menu, Tray, NoStandard
   Menu, Tray, Click, 1
   Menu, Tray, Add, Показать/Скрыть, % GuiClose
   Menu, Tray, Add, Добавить в Автозагрузку, AddToStartup
   if FileExist(A_Startup "\GoogleTranslatlator.lnk")
      Menu, Tray, Check, Добавить в Автозагрузку
   if !A_IsCompiled  {
      Menu, Tray, Add
      Menu, Tray, Add, Reload, ScriptMenu
      Menu, Tray, Add, Edit, ScriptMenu
      Menu, Tray, Add
   }
   Menu, Tray, Add, Выход, ExitApp
   Menu, Tray, Default, Показать/Скрыть
}

WM_SIZE(hIE, wp, lp)
{
   if (wp = SIZE_MINIMIZED := 1)
      _GuiClose(hIE)
   else
      WinMove, ahk_id %hIE%,, 0, 0, lp & 0xFFFF, lp >> 16
}

_GuiClose(hGui)
{
   Gui, Show, % WinExist("ahk_id" hGui) ? "Hide" : ""
}

GuiEscape()
{
   Gui, Show, Hide
}

AddToStartup()
{
   if FileExist(A_Startup "\GoogleTranslatlator.lnk")
      FileDelete, % A_Startup "\GoogleTranslatlator.lnk"
   else  {
      try FileCreateShortcut, % A_ScriptFullPath, %A_Startup%\GoogleTranslatlator.lnk,, Hide
      catch
         Return, "", DllCall("MessageBox", Ptr, 0, Str, "Не удалось создать ярлык в папке автозагрузки!"
                                                 , Str, "Ошибка создания ярлыка", UInt, MB_ICONERROR := 0x10)
   }
   Menu, Tray, ToggleCheck, Добавить в Автозагрузку
}

ScriptMenu(ItemName)
{
   if (ItemName = "Edit")
      Edit
   else
      Run, "%A_ScriptFullPath%" Hide   ; или Reload
}

ExitApp()
{
   ExitApp
}

FixIE(Fix)
{
   Static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
   If A_IsCompiled
     ExeName := A_ScriptName
   Else
     SplitPath, A_AhkPath, ExeName
   If Fix
     RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, 0
   Else
     RegDelete, HKCU, %Key%, %ExeName%
}

CreateTrayIconFromBase64()
{
   hIcon := CreateIconFromBase64(GetBase64String(16), 16)
   ModifyTrayIcon(hIcon, A_ScriptHwnd)
}

CreateIconFromBase64(StringBASE64, Size)
{
   StringBase64ToData(StringBASE64, IconData)
   Return DllCall("CreateIconFromResourceEx", Ptr, &IconData + 4
      , UInt, NumGet(&IconData, "UInt"), UInt, true, UInt, 0x30000, Int, Size, Int, Size, UInt, 0)
}

ModifyTrayIcon(hIcon, hGui, uID = 0x404)
{
   static NIM_MODIFY := 1, NIF_ICON := 2
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   res := DllCall("shell32\Shell_NotifyIcon", UInt, NIM_MODIFY, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return res
}

StringBase64ToData(StringBase64, ByRef OutData)
{
   DllCall("Crypt32.dll\CryptStringToBinary", Ptr, &StringBase64 
      , UInt, StrLen(StringBase64), UInt, CRYPT_STRING_BASE64 := 1, UInt, 0, UIntP, Bytes, UIntP, 0, UIntP, 0)

   VarSetCapacity(OutData, Bytes) 
   DllCall("Crypt32.dll\CryptStringToBinary", Ptr, &StringBase64 
      , UInt, StrLen(StringBase64), UInt, CRYPT_STRING_BASE64, Str, OutData, UIntP, Bytes, UIntP, 0, UIntP, 0)
   Return Bytes
}

VerifyIeVersion(MinVersion)
{
   RegRead, IE_Version, HKLM\SOFTWARE\Microsoft\Internet Explorer, svcVersion
   if ErrorLevel
      RegRead, IE_Version, HKLM\SOFTWARE\Microsoft\Internet Explorer, Version

   if RegExReplace(IE_Version, "(\d+).*", "$1") < MinVersion  {
      MsgBox, Ваша версия Internet Explorer %IE_Version% не поддерживается. Обновите Internet Explorer!
      Return
   }
   Return 1
}

GetBase64String(Size)
{
   Icon16 = 
   (
      aAQAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAADt5+GR
      /Pr49/78+//p0Ln/sUsA/71iAP+8YQD/vGEA/7xhAP+8YQD/vGEA/7xhAP+8YQD/
      vGEA/7thAPqxawGU/f38+/7+/v7//////Pr4/8yANf/HZwD/y3IQ/8tyEP/Lcg//
      ym8J/8txDv/LchD/y3EP/8puCf/LcQ/+ynMR+v7+/f/////////////////y3cr/
      1XYR/+GLJ//giSf/4Isq/+GPM//fiCX/4Ioo/9+IJP/hjzP/4Iss/96IJv/+/v7/
      /////////////////////+Wnbf/niCD/7ZY1/+mSMP/57eD/8bJr/+h9B//vqVz/
      +/Tu/+uYPP/rki///f7+//7////+/////v/////////37ef/4IQq/++YNP/sjiT/
      9NSx//vn0f/ytHL/+eLI//jiyv/sjiX/7pk6//z9/v/9/v///f7///3+///9/v//
      /////+m5kP/ohR7/8ZYv//CtZP/7+vn/78ab//v7+v/zuXn/75Eq//CbPf/8/P3/
      /v7///7////9/v///f3///7+///7+vv/4o0///GVL//wnD3/+Ora//SxZ//68OT/
      8aFH//GZOP/ynT///f3+//z59//89vH///////7//////////////+/Ruf/nhCD/
      9Zct//XSq////fz/+d2///KULP/0n0D/9J9B//39/v/7+PP/8cmi//PCk//9+vf/
      88WY/+ybS//7+PX/5aBj//KOI//1smj/9uzh//W3dP/2mTT/9qBC//ahQ//7+/3/
      /f7///3////ww5f/6o0y/+uVQv/yxZj//Pjy//Tl2//mhSn/+KA9//ScO//3nz7/
      +KJF//iiRP/4o0X//Pv+//38///+////+e/n/+Z6Ef/0y6T///////3+////////
      6K18//COKf/7pUX/+aNF//mjRv/5o0b/+aRH//v7/f/8/f///v////XWuf/yzqz/
      65VA//3////9/////f7///jx7v/mijb/+qFA//umSP/7pUj/+6VI//ulSf/8/P7/
      +/r7//Xhz//02L7/9+nc/+qcUf/wvYv/+e7i//v9///+////7MGf/+2JJ//9qUv/
      +6ZJ//umSf/7pkr//Pv+//v6/f/59O7/9+3k/+qZSv/58u7/8cqk//nv6P/8/f//
      /P3///r7/f/mk0v/+Jw7//2pS//8p0r//adL//v6/fn8/P/+/P////ny7v/23sr/
      /P3///3////8/v//+/v///v7///+////8tbB/+uKL//+qEn//qhL/v2oTfn69/Sb
      +/v++fr6/v/8///+/v///vv8//77+/7++/v+/vv7/v77/P7++/7+/vv///7nk0/+
      +Jk7//6oTPv5qFOXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
      AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   )
   Icon32 = 
   (
      qBAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAADn3tQD
      6OHatvv49P/8+PX8+/j0/vz59f/58ev/t2ER/7daAf+8YgL/umAA/7thAf+7YQH/
      u2EB/7thAf+7YQH/u2EB/7thAf+7YQH/u2EB/7thAf+7YQH/u2EB/7thAf+7YQH/
      u2EB/7thAf+7YQH+u2AA/LtgAP+sWwHEzogDCfLu6MX+/f38//////////7/////
      /fz6///////Zqn7/tVMA/8RsC//DaAb/w2kG/8NpBv/DaQb/w2kG/8NpBv/DaQb/
      w2kG/8NpBv/DaQb/w2kG/8NpBv/DaQb/w2kG/8NpBv/DaQb/w2kG/8NpBv/DaQb+
      wmgF/8NpBv64bA7E///+///////////////////////+/f3//v7+//v38//EciX/
      xGgJ/8x0Ev/KcQ//y3IQ/8tyEP/LchD/y3IQ/8tyEP/LchD/y3IQ/8tyEP/LchD/
      y3IQ/8tyEP/LchD/y3IQ/8tyEP/LchD/y3IQ/8tyEP/Lcg//ynEP/811Ef/+/fz9
      /////v/////+/v7////////////9/Pv//////+nIqP/DYwb/1H4f/9R8Gv/UfBr/
      1H0b/9R9G//UfRv/1H0b/9R9G//Vfh3/1X4e/9V9HP/UfRv/1H0b/9R9G//UfRv/
      1H0b/9V+Hf/Vfh7/1X0c/9R8Gv/UfBr+1X8d/f79+/7/////////////////////
      /v7+//7+/v/+/Pv//v79/9eSUf/Sdhb/34so/92HJf/eiCb/3ogm/96IJv/eiCb/
      3ogm/92DHP/dghr/3oYi/96JJ//eiCb/3ogm/96IJv/eiSf/3YQd/92CGv/dhR//
      3okn/92HJf/eiyn+/v38//////////////////////////////////38+//+////
      9eLR/9J1Hf/jjS//55Ew/+WQL//nkTD/5pEw/+aRMP/lkC//6qpm/+2xcv/onUj/
      5o8s/+aRMf/nkTD/5pEx/+aQLv/qqF//7bFy/+mjVf/mjiv/5pEw/+eTM//9/f3/
      /v////7////+/////v////7////+/v7//v////38+v//////46l1/9p5G//slzn/
      6pQ0/+uUNf/rlTX/65Y4/+iMKP/w2L7///////XSq//pjSb/65Y4/+uUNf/rkzP/
      65pB//v28v//////7ruE/+mOKP/rljj/65c4//79/P//////////////////////
      /////////////v7//v38//7+/f/57+b/130t/+WNMP/tmDj/65Y2/+yXN//smDn/
      7JAo/+qydf/9/fz/++/h/+yXOP/sljT/7Jg5/+uQKv/vtXT//v79//r07f/qnET/
      7JUz/+yWN//smTr//f39//7////+/////v////7////+/////v////7//v/+////
      /fz7///////pvpn/2Xgd/+yYO//umDj/7Zc3/+2YOf/uljT/6pxG//j07///////
      8a9n/+ySMP/tmj7/65Iu//bXtf/+/v7/9dy//+uRLP/umTv/7Zc3/+6aPP/8/f3/
      /f7///3+///9/v///f7///3+///9/v///f7///3+/v/9/v7//f38//z59v/bi0X/
      44cr/++bPP/umTn/75k5/++aPP/sky//8trA//7+/v/99e7///bu///48f/+9e3/
      /fr2///////xv4f/7pIr/++bPf/umDn/75s9//39/f/+/v///v3///7+///+/v//
      /v7///7+///+/v///v7///7+///8+/r///////DSuv/Zdx//7JY6//CaO//vmTr/
      8Js9//CULv/tuoH//v////r18P/t3Mr/7dvJ//Dk2P//////+/n2/+6jUP/wlzX/
      75o8//CZOv/wnD7//f39//79///+/P///v3///79///+/f///v3///79///+/f//
      /f3+//39/v/9/Pz//v///+CbYf/gfyP/8Jw///CbPP/wmzz/8Zk3/+yhTv/5+fj/
      /PTq/+uYO//qih//77yD//7+/v/34Mf/75Uy//GcPf/wmzv/8Jo7//GdP//9/f3/
      /v7///79///+/v///v7///7+///+/v///v7///7+///+/v///v7///38/P/+/v7/
      9eTW/9p7J//qkzj/8p0+//GcPf/ynkD/75c1//Pex///////9rl3//GULP/65c7/
      //////LBi//xlTD/8p5A//KcPv/xnD3/8p5B//39/f/9/v///fz+//39/v/9/f7/
      /f3+//39/v/+/v///v7///7+///9/f7//v7///z8+///////5q+A/959I//wmz//
      850+//KeQf/ylzL/776I//7+/v/506n/8aBH//37+v/8+/j/8adW//OaOf/ynT//
      850+//KcPf/zn0L//P39//79///+/f///v////39///9/Pv//f3+//3+/v/9/f7/
      /f3+//7+///9/P3//fv6//38/P/68+3/3YU5/+iMMv/0nkD/855A//SbOv/vpVP/
      +vz9//3r2P/0voP///////jizP/ymTj/9J9B//SeP//0nj//850+//SgQ//9/f3/
      /f7+//38/f/67uP//v/////////+/////fz8//7+///9/f7//fz9////////////
      /f7////+/v/txaT/3Xog//CZP//1oEH/9aBC//KaOP/15NL//vr2//nkzv/+/v3/
      9cWR//SZNP/1oUT/9Z9B//WfQf/0nkD/9aFE//z8/f/9/f3//fz8//HStP/sq2z/
      9cme//z38//+/////fz7//3+///+////+OLN/++vcP/21bX///////z6+f/gk1L/
      5YYt//SfQ//2okX/9Zkz//HFlP////////////3////zq1v/9p08//WgQ//2oEL/
      9qBC//WfQf/2okX/+/39//z+/v/8/P3//v////bn2f/nmk7/6o40//XQq//9////
      +/j0//C0eP/pii3/6YIe/+qKK//22r3//v////HXwv/ceST/7ZU+//ahRP/2nTz/
      8ahZ/+zXv//t2cL/7syo//WeP//2oEP/9qBC//agQv/2oEL/9Z9B//aiRf/8/P3/
      /f3+//38///8+/v//v////v9/v/pqm3/53wT//C0ef/tpV7/6IId/+mHJ//qlUL/
      7a5w//PQrv/8+/v//v///+Skbv/igSj/851D//eiRP/2n0D/85s5//ObOf/0nDr/
      96JE//ehQ//3oUP/96FD//ehQ//2oEL/96NG//z7/f/9/P///Pv+//39///8+/z/
      /fz9//r8/f/qqWn/6YMg/+qKLP/qkz7/8cGT//nx6f/9/////v////z7/P/9/v7/
      9+rg/92BMf/qkDn/96FE//eiRP/4o0b/+aRG//ijRv/4okT/+KJE//iiRP/4okT/
      +KJE//ehQ//4pEj//Pz9//39///9/P///Pz+//39///7+fr//v////Tcxv/piSr/
      6ogo//PHnP///////P3///z7/P/8+/z//f3///v6+v//////6reM/+B8Iv/ynEL/
      +aRF//iiRP/5o0X/+aNF//mjRf/5o0X/+aNF//mjRf/5o0X/+KJE//mlSf/8/P3/
      /P3///z8///8/f///Pz+//z7/P/9////7axt/+iHKf/piy7/7Z9S//z49f/8/Pz/
      /Pz+//z8/v/8/P7//Pz9//z8/f/79fH/4IpB/+iKMv/2oUT/+aRG//ijRf/5pEb/
      +aRG//mkRv/5pEb/+aRG//mjRf/4o0X/+aVJ//z7/f/9/P///fv///38///8+/3/
      /f7///js4v/pkDj/9N3H/+mcUP/pgh7/9ti9//3+/f/7+vv//fz+//38///9/f//
      +/r7///////wzLD/33wl//CZQv/6pUf/+aRH//qlR//6pUf/+qVH//qlR//6pUf/
      +qVH//qkRv/6pkr//Pz9//z8/v/8/P///Pz9//v49//9/fz/8cSa//C7iP//////
      7beC/+h+F//wtXv//v////v4+P/8+/z//P3///z8/v/8/P7//Pv8//38+//kmFj/
      5oYu//afRf/7pkj/+qRH//ulSP/7pUj/+6VI//ulSP/7pUj/+6RH//umS//8+/3/
      /P3///v7///8/////f////3////wxJn/+/r5//7////z38z/6Ico/+uQNv/35NH/
      /f////z////7/P7//P3///z8///6+vv//f7///Tfzv/ffyv/7ZQ9//mjR//7pkj/
      +qVI//umSP/7pkj/+6ZI//umSP/7pUf/+6dL//z7/f/7+/3//Pz///fo3P/zz6z/
      8tK0/++/kP/13ML/9uHM//LWuv/njTX/6JpN//HAkP/20rH/9di8//z9///7+/3/
      +/z+//v8///6+fv//v///+iref/jgCj/85xE//ymSP/6pEj/+6VI//ulSP/7pUj/
      +6VI//ukR//7p0z//Pr9//v7/f/8/P//9+vh//TdyP/14tL/9eTV//Xi0f/rqWn/
      8MCR//fp2//05tn/6JVF/+d+Fv/007P//P7+//v6/P/8+////Pv+//v6/P/8/f3/
      +O3k/+CDNf/rjzr/+KJG//ynSf/7pUj//KZJ//ymSf/8pkn//KVI//yoTP/8+/3+
      /Pz///v6///8/////f////z////9////+fLt/+mGJf/slUD//Pz9//3////z38z/
      9NrC//3////7+v3//Pz///z8///7/P7//Pz///r5+//+////7b2X/+J/KP/xmkT/
      /KdJ//ynSv/8p0r//adK//2nSv/9pkn//ahN/vz7/f37+/7+/Pv///v7/f/7+v3/
      +vn6//v9/f/tuYf/6I41//HIoP/7/Pv/+/n7//3////9////+/r9//z8///8+/7/
      +/z///v8///7+/7/+/v+//v7/P/7+Pb/45BL/+mJM//3n0X//qhL//ymSf/9p0v/
      /adK//2mSf79qE79/Pv9//z8///7+v///Pz///v7/v/7/P//+/v+//ju5v/59fT/
      /P////z7/v/8+/7/+/r8//v6/P/8/P///Pv+//z8///8/P///Pz///z8///8/P//
      +vn7//3////y0rn/4X0l/++WQP/7pUj//ahL//2nSv/+qEv//adK//6pTv/79fLG
      +/v9+vv7/v/7+/7++/z///v7///7/P///P////z9///7+v3/+/z///v8///7+/7/
      +/z///v8///7/P//+/z///v8///7/P//+/z///v7/v/7+/7/+/r8//3+///noWf/
      5oUu//ScRP/9qEv//ahL/v6oS//9qUz896lTwPv28Av6+fjD+vv+//r7/vz7+/7+
      +/v+/vv7/v76+/3++vv+/vv7/v77+/7++/v+/vv7/v77+/7++/v+/vv7/v77+/7+
      +/v+/vv7/v77+/7++/v+/vv7/v75+Pr+/P/+/vPTvP7ieCX+75A//vufRv7/pEn8
      /qJI/vylT8z2pE4IgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
      AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
      AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAE=
   )
   Return Icon%Size%
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

190

Re: AHK: Переводчик онлайн

Поудалял ненужные элементы, сменил иконку на нативную Google Translate.

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

191

Re: AHK: Переводчик онлайн

Без посредства IE сделать уже нельзя после изменений на их сервере? IE6 пролетает?

192

Re: AHK: Переводчик онлайн

А зачем вы используете IE6?

По состоянию на апрель 2014 IE6 используют 0,1% пользователей.

193

Re: AHK: Переводчик онлайн

В том-то и дело, что для интернета никогда не использовал (хоть это IE500 будет ), разве что c html-страницами ассоциирован

194

Re: AHK: Переводчик онлайн

Так в чём проблема обновиться?

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

195

Re: AHK: Переводчик онлайн

Можно, но хотелось без этого.

196

Re: AHK: Переводчик онлайн

teadrinker пишет:

Так в чём проблема обновиться?

Нельзя.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

197

Re: AHK: Переводчик онлайн

А, винда, наверно, левая.

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

198

Re: AHK: Переводчик онлайн

А я тоже помню как-то пробовал, но что-то там не заладилось. Значит, скрипт только для правильной винды

199 (изменено: Malcev, 2015-04-20 18:27:47)

Re: AHK: Переводчик онлайн

А тут, как я понял, работает WinHttp запрос.
http://ahkscript.org/boards/viewtopic.p … amp;t=7143

200 (изменено: teadrinker, 2015-04-20 22:58:43)

Re: AHK: Переводчик онлайн

Ага, спасибо! Вроде, действительно работает:

#NoEnv
#SingleInstance, force
SetBatchLines, -1

if !A_IsCompiled
{
   if !FileExist(A_ScriptDir . "\Icons")
   {
      MsgBox, 4,, В директории скрипта отсутствует папка с иконками.`nЗагрузить с сервера?
      IfMsgBox, Yes
      {
         FileCreateDir, % A_ScriptDir "\Icons"
         TrayTip,, Идёт загрузка файлов с сервера`, подождите...
         if !Ping("content.screencast.com")
         {
            MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
            ExitApp
         }
         PreUrl := "http://content.screencast.com/users/teadrinker/folders/icons/media/"
         URLDownloadToFile, % PreUrl . "83188ad1-4a8a-491f-bf70-fb292e73c98c/Change.ico?downloadOnly=true"    , Icons\Change.ico
         URLDownloadToFile, % PreUrl . "57ced9ad-3ccc-4019-a9bd-6f86218f3dd9/Google.ico?downloadOnly=true"    , Icons\Google.ico
         URLDownloadToFile, % PreUrl . "4ed2cdc9-556f-4266-9b23-d8ec665c9b84/PlayPause.ico?downloadOnly=true", Icons\PlayPause.ico
         URLDownloadToFile, % PreUrl . "869c4c44-5e3a-470c-bed4-c8d2bcee621d/Stop.ico?downloadOnly=true"       , Icons\Stop.ico
         URLDownloadToFile, % PreUrl . "0ac5a584-d28c-4ca7-aac8-a45631a2e3c3/Translate.ico?downloadOnly=true", Icons\Translate.ico
         
         if !(FileExist("Icons\Change.ico") && FileExist("Icons\Google.ico") && FileExist("Icons\PlayPause.ico")
            && FileExist("Icons\Stop.ico") && FileExist("Icons\Translate.ico"))
         {
            TrayTip
            MsgBox, Не удалось завершить загрузку.`nЗагрузите папку вручную из аттача к теме на форуме
               ,`nпоместите её в директорию скрипта и запустите скрипт снова.
            ExitApp
         }
         else
         {
            Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
            TrayTip,, Загрузка успешно завершена!
            Sleep, 1500
            TrayTip
         }
      }
      else
      {
         MsgBox, Загрузите папку вручную из аттача к теме на форуме
            ,`nпоместите её в директорию скрипта и запустите скрипт снова.
         ExitApp
      }
   }
   Menu, Tray, Icon, % A_ScriptDir "\Icons\Google.ico"
}

global  MAX_URL_LENGTH := 2076, IMAGE_ICON := 1, WM_INPUTLANGCHANGEREQUEST := 0x50
      , EVENT_SYSTEM_MOVESIZESTART := 0xA, EVENT_SYSTEM_MOVESIZEEND := 0xB
      , GUIs := [], LangArray := {}, Player, Voice := [], ColorGui := "Default", MainTransText
      , SIZING, Edit1HPos, Edit2HPos, Edit2YPos, Button2YPos, Button6YPos, Edit1FontSize, Edit2FontSize
      , IsControlPos, GetControlPos, ScriptPID, GuiActive, SaveSize, AllowMultiWindow
      , IniName := RegExReplace(A_ScriptName, "(.*\.).*", "$1ini")
   
Process, Exist
ScriptPID := ErrorLevel
InitLangArray()

Hotkey, IfWinActive
Hotkey, ~^vk43, HotkeyRun, Off
Hotkey, ~^Ins , HotkeyRun, Off

IniRead, Hotkey            , % IniName, Hotkey   , Hotkey               , C
IniRead, ShowWindowOnStart   , % IniName, Settings, ShowWindowOnStart   , 0
IniRead, SaveSize            , % IniName, Settings, SaveSize            , 0
IniRead, AllowMultiWindow   , % IniName, Settings, AllowMultiWindow   , 0
IniRead, Edit1FontSize      , % IniName, Location, Edit1FontSize      , 8
IniRead, Edit2FontSize      , % IniName, Location, Edit2FontSize      , 8

if InStr(Hotkey, "C")
   Hotkey, ~^vk43, On
if InStr(Hotkey, "Ins")
   Hotkey, ~^Ins, On

Menu, Tray, NoStandard

Menu, Tray, Add, Открыть, Open
Menu, Tray, Default, Открыть
Menu, Tray, Add

Menu, Tray, Add, Показывать окно при запуске, ShowWindowOnStart
if ShowWindowOnStart
   Menu, Tray, Check, Показывать окно при запуске

Menu, Tray, Add, Сохранять размеры окна, SaveSize
if SaveSize
   Menu, Tray, Check, Сохранять размеры окна

Menu, Tray, Add, Разрешить много окон, AllowMultiWindow
if AllowMultiWindow
   Menu, Tray, Check, Разрешить много окон

Menu, Tray, Add
Menu, Tray, Add, Использовать Ctrl+C+C, Hotkey
Menu, Tray, Add, Использовать Ctrl+Ins+Ins, Hotkey
if InStr(Hotkey, "C")
   Menu, Tray, Check, Использовать Ctrl+C+C
if InStr(Hotkey, "Ins")
   Menu, Tray, Check, Использовать Ctrl+Ins+Ins
Menu, Tray, Add

if !A_IsCompiled
{
   Menu, Tray, Add, Edit, Edit
   Menu, Tray, Add, Reload, Reload
   Menu, Tray, Add
}
Menu, Tray, Add, Выход, ExitApp

HWINEVENTHOOK := SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, 0
                                          , RegisterCallback("WinGetControlPos", "F"), 0, 0, 0)
OnExit, Exit

OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x111, "WM_COMMAND")
OnMessage(0x214, "WM_SIZING")

ShowWindowOnStart ? ShowTranslation("", "", "en", "ru")
Return

Open:
   if !WinExist("Google Translate ahk_pid" ScriptPID) || AllowMultiWindow
   ShowTranslation("", "", "en", "ru")
   return
   
ShowWindowOnStart:
AllowMultiWindow:
SaveSize:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   %A_ThisLabel% := !%A_ThisLabel%
   IniWrite, % %A_ThisLabel%, % IniName, Settings, %A_ThisLabel%
   return

Edit:
   Edit
   return
   
Reload:
   Reload
   return

Hotkey:
   Menu, Tray, ToggleCheck, % A_ThisMenuItem
   
   if InStr(A_ThisMenuItem, "Ins")
      Hotkey := InStr(Hotkey, "Ins") ? RegExReplace(Hotkey, "Ins") : Hotkey . "Ins"
   if InStr(A_ThisMenuItem, "C+C")
      Hotkey := InStr(Hotkey, "C") ? RegExReplace(Hotkey, "C") : Hotkey . "C"
   
   Hotkey, ~^Ins, % InStr(Hotkey, "Ins") ? "On" : "Off"
   Hotkey, ~^vk43, % InStr(Hotkey, "C") ? "On" : "Off"
   
   IniWrite, % Hotkey, % IniName, Hotkey, Hotkey
   return

HotkeyRun:
   DoublePress()
   return

ExchangeLang:
   GuiControlGet, to,, ComboBox1
   GuiControlGet, from,, ComboBox2
   
   SourceLangNames := TargetLangNames := ""
   for k In LangArray
      SourceLangNames .= "|" . k . (k = from ? "|" : "")
    , TargetLangNames .= "|" . k . (k = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")
   
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl, Focus, Edit1
   return
   
Exit:
   WinGet, List, List, % "Google Translate ahk_pid" ScriptPID
   Loop % List
   {
      if (List%A_Index% = GUIs.1)
      {
         IniWriteSizeGui(GUIs.1), SaveSize ? IniWriteSizeEdit(GUIs.1)
         break
      }
   }
   DllCall("UnhookWinEvent", Ptr, HWINEVENTHOOK)
   GUIs := LangArray := Voice := ""
ExitApp:
   ExitApp

^!vk56::SendInput, {Raw}%MainTransText%

#If hActive := WinActive("Google Translate ahk_pid" ScriptPID)
Esc::WinClose, A
Enter::ControlClick, Button4, % "Google Translate ahk_pid" ScriptPID
^Tab::
   Gui, %hActive%:Default
   GuiControl, Focus, Static1
   Gosub, ExchangeLang
   Return

#If WinActive("Google Translate ahk_pid" ScriptPID) && NN := GetEditFocus()
^WheelUp::
^WheelDown::
   InStr(A_ThisHotkey, "Up") ? ++Edit%NN%FontSize : --Edit%NN%FontSize
   Edit%NN%FontSize < 6 ? Edit%NN%FontSize := 6
   Edit%NN%FontSize > 25 ? Edit%NN%FontSize := 25
   ToolTip % "FontSize = " . Edit%NN%FontSize
   
   Gui, % WinExist("A") . ":Default"
   Gui, Font, % "q5 s" . Edit%NN%FontSize, Verdana
   GuiControl, Font, Edit%NN%
   SetTimer, IniWriteFontSize, -500
   return
   
IniWriteFontSize:
   ToolTip
   IniWrite, %Edit1FontSize%, % IniName, Location, Edit1FontSize
   IniWrite, %Edit2FontSize%, % IniName, Location, Edit2FontSize
   return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400 And Clipboard
   {
      pressed1 := 0
      if (!(hwnd := WinExist("Google Translate ahk_pid" ScriptPID)) || AllowMultiWindow)
         GuiActive := GetActiveWindow(), Translate(RegExReplace(Clipboard, "\R", "`r`n"))
      else
         TranslateInTheSameWindow(hwnd, Clipboard)
   }   
   else
      pressed1 := 1
}

Translate(Sourse, ByRef _from="", ByRef _to="", NewWindow = 1)
{
   if !Ping("translate.google.com")
   {
      MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Sourse, "[А-Яа-я]")
      from := cyr ? "ru" : "auto", to := cyr ? "en" : "ru"
   }
   else
      from := _from, to := _to

   PreUrl := "https://translate.google.com/translate_a/single?client=t&sl=" . from . "&tl=" . to
      . "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&srcrom=0&ssel=0&tsel=3&q="
   Url := PreUrl . URIEncode(Sourse)

   if StrLen(Url) > MAX_URL_LENGTH
   {
      if RegExMatch(Sourse, "[\.\?!\n]")
      {
         StartPos := 1
         While StartPos := RegExMatch(Sourse, ".+?([\.\?!\r\n]+([ \t\r\n]*)|$)", Found, StartPos) + StrLen(Found)
         {
            Delimiter := Found2 ? Found2 : RegExReplace(Found, ".*(\s*)", "$1")
            Text := RegExReplace(Found, "(.*)\s*", "$1")
            Url := PreUrl . URIEncode(Text)
            if StrLen(Url) > MAX_URL_LENGTH
            {
               If RegExMatch(Text, "[,;:—\r\n]")
               {
                  PrevText := "", StartPos_ := 1

                  While StartPos_ := RegExMatch(Text, "(.+?)(([,;:—\.]+\s*)|$)", Found_, StartPos_) + StrLen(Found_)
                  {
                     txt := Found_1, dlmtr := Found_2

                     If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
                        TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from) . RegExReplace(PrevText, ".*(\s+)$", "$1")
                           . BreakdownByGaps(txt, PreUrl, from) . dlmtr, PrevText := ""

                     else If StrLen(PreUrl . URIEncode(txt . dlmtr . PrevText)) > MAX_URL_LENGTH
                        TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
                           . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

                     else
                        PrevText .= txt . dlmtr
                  }
                  TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
               }
               else
                  TransText .= BreakdownByGaps(Text, PreUrl, ByRef from)
               TransText .= Delimiter
            }
            else
               TransText .= GetTranslation(Url, from) . Delimiter
         }
      }
      else
         TransText := BreakdownByGaps(Sourse, PreUrl, ByRef from)
   }
   else
      TransText := GetTranslation(Url, from)
   
   If NewWindow
      ShowTranslation(Clipboard, TransText, from, to)
   else
   {
      _from := from, _to := to
      Return TransText
   }
}

BreakdownByGaps(Text, PreUrl, ByRef from)
{
   StartPos := 1
   While StartPos := RegExMatch(Text, "(.+?)([ \t]+|$)", Found, StartPos) + StrLen(Found)
   {
      txt := Found1, dlmtr := Found2
      If StrLen(PreUrl . URIEncode(txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= txt . dlmtr, PrevText := ""

      else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > MAX_URL_LENGTH
         TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
            . RegExReplace(PrevText, ".*(\s+)$", "$1"), PrevText := txt . dlmtr

      else
         PrevText .= txt . dlmtr
   }
   Return TransText .= GetTranslation(PreUrl . URIEncode(PrevText), from)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, IntegerFast, H
   Loop, % StrPutVar(Str, Var, "UTF-8")
   {
      Ch:=NumGet(Var, A_Index-1, "UChar")
      If Ch=0
         Break
      If (Ch>0x7f Or Ch<0x30 Or Ch=0x3d)
         s.="%"((StrLen(c:=SubStr(Ch, 3))<2) ? "0"c:c)
      else
         s.=Chr(Ch)
   }
   SetFormat, IntegerFast, % b_Format
   Return, s
}

GetTranslation(Url, byref from)
{
   static JS := GetObjJScript()
   if !JsonTrans := UrlDownloadToVar(Url, "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko")
   {
      MsgBox, 16, Ошибка, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }
   if InStr(JsonTrans, "name=""captcha""")
   {
      MsgBox, 16, Ошибка, Капча!
      Return
   }
;   Clipboard := JsonTrans
   oJSON := JS.eval("(" . JsonTrans . ")")
   
   try PartsOfspeech := oJSON[1]
   catch e
      text := oJSON[0][0][0]

   if !e  {
      Loop % PartsOfspeech.length  {
         obj := PartsOfspeech[A_Index - 1][1]
         i := A_Index
         Loop % obj.length
            text .= obj[A_Index - 1] . (A_Index = 1 ? (i = 1 ? "`n+`n" : "`n`n") : ", ")
      }
   }
   
   from := oJSON[2]
   
   Return Trim(text, ",+`n ")
}

GetObjJScript()
{
   if !FileExist(WscPath := A_ScriptDir . "\JS.wsc")
      FileAppend,
      (LTrim
         <component>
         <public><method name='eval'/></public>
         <script language='JScript'></script>
         </component>
      ), % WscPath

   JS := ComObjGet("script:" . WscPath)
   JS.eval("delete ActiveXObject; delete GetObject;")
   Return JS
}

FinishingText(text)
{
   if RegExMatch(text, "\\u\d\d\d\d")
   {
      StartPos := 1
      While StartPos := RegExMatch(text, "\\u(\d\d\d\d)", Found, StartPos)
         text := RegExReplace(text, "\Q" Found "\E", Chr("0x" Found1)), StartPos++
   }
   text := RegExReplace(text, "\\r\\n", "`r`n")
 , text := RegExReplace(text, "\\(.)", "$1")
 , text := RegExReplace(text, " ``(.)", "$1" Chr(0x301))   ; обработка знака ударения
   Return text
}

WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}

StrPutVar(string, ByRef var, encoding = "CP0")
{
    ; Ensure capacity.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut returns char count, but VarSetCapacity needs bytes.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; Copy or convert the string.
    return StrPut(string, &var, encoding)
}

UrlDownloadToVar(URL, UserAgent = "", ProxyServer = "", UserName = 0, Password = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ProxyServer ? WebRequest.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY := 2, ProxyServer)
   WebRequest.Open("GET", Url)
   ProxyServer ? WebRequest.SetCredentials(UserName, Password, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY := 1)
   UserAgent ? WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}

ShowTranslation(SourceText, TransText, from, to)
{
   static PlayPause1, PlayPause2, Stop1, Stop2, hGui, Control, ExChange1, ExChange2, Source
        , hIconPlayPause, hIconStop, hIconTranslate, hIconGoogle, hIconChange, Icons
        , hButtPlayPause1, hButtPlayPause2, hButtStop1, hButtStop2, hButtTranslate, hButtChange1, hButtChange2
        , BS_ICON := 0x40, WM_SETICON := 0x80, BM_SETIMAGE := 0xF7, ES_NOHIDESEL := 0x100
        , WMSZ_TOP := 3, WMSZ_TOPLEFT := 4, WMSZ_TOPRIGHT := 5

   Gui, New, +AlwaysOnTop +LastFound +Resize +hwndhGui +Owner +MinSize199x220 -MaximizeBox
   Gui, Color, %ColorGui%
   
   oSize := IniReadSizeEdit()
   if (SaveSize && Edit1H := oSize.Edit1H)
      Edit1W := oSize.Edit1W, Edit2H := oSize.Edit2H
   
   Gui, Font, q5 s8, Verdana
   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y15", Исходный язык:

   SourceLangNames := TargetLangNames := ""
   For k,v In LangArray
      SourceLangNames .= (A_Index = 1 ? "" : "|") . k . (v = from ? "|" : "")
    , TargetLangNames .= (A_Index = 1 ? "" : "|") . k . (v = to   ? "|" : "")

   SourceLangNames := RegExReplace(SourceLangNames, "\|$", "||")

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % SourceLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange1 gExchangeLang vExChange1"

   Gui, Font, q5 s%Edit1FontSize%, Verdana
   if !(SaveSize && Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL% vSource, % SourceText
      GuiControlGet, Edit1, Pos
      
      Edit1H < 45 ? Edit1H := 45
      Edit1H > 250 ? Edit1H := 250
      GuiControl, Move, Edit1, h%Edit1H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit1H " vSource " ES_NOHIDESEL, % SourceText

   GuiControlGet, Edit1, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit1Y + Edit1H + 5 " w52 h23 hwndhButtPlayPause1 gPlayPause vPlayPause1 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop1 gStop vStop1" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 " BS_ICON " hwndhButtTranslate gTranslate"

   Gui, Add, Text, % "x" (Edit1W > 310 ? 10 + (Edit1W - 310)//2 : 10) " y+20", Язык перевода:

   Gui, Add, DDL, % "x" (Edit1W > 310 ? 112 + (Edit1W - 310)//2 : 112) " yp-4 w182", % TargetLangNames
   Gui, Add, Button, % "x" (Edit1W > 310 ? 297 + (Edit1W - 310)//2 : 297)
                     . " yp-1 w23 h23 " BS_ICON " hwndhButtChange2 gExchangeLang vExChange2"

   Gui, Font, q5 s%Edit2FontSize%, Verdana
   if !(SaveSize && Edit1H := oSize.Edit1H)
   {
      Gui, Add, Edit, x10 y+9 w310 Multi %ES_NOHIDESEL%, % TransText
      GuiControlGet, Edit2, Pos
      
      Edit2H < 45 ? Edit2H := 45
      Edit2H > 250 ? Edit2H := 250
      GuiControl, Move, Edit2, h%Edit2H%
   }
   else
      Gui, Add, Edit, % "x10 y+9 w" (Edit1W ? Edit1W : 310) " Multi h" Edit2H " " ES_NOHIDESEL, % TransText

   GuiControlGet, Edit2, Pos
   Gui, Font, q5 s8, Verdana
   Gui, Add, Button, % "x10 y" Edit2Y + Edit2H + 5 " w52 h23 hwndhButtPlayPause2 gPlayPause vPlayPause2 " BS_ICON
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButtStop2 gStop vStop2" (Player ? "" : " Disabled")
   Gui, Add, Button, % "x" (Edit1W ? Edit1W - 60 : 250) " yp w70 h23 gGuiClose", OK

   if !IsObject(Icons)
   {
      hIconGoogle    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 1, 24) : ExtractIcon(A_ScriptDir "\Icons\Google.ico"    , 1, 24)
      hIconChange    := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 2, 16) : ExtractIcon(A_ScriptDir "\Icons\Change.ico"    , 1, 16)
      hIconPlayPause := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 3, 25) : ExtractIcon(A_ScriptDir "\Icons\PlayPause.ico", 1, 25)
      hIconStop       := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 4, 12) : ExtractIcon(A_ScriptDir "\Icons\Stop.ico"       , 1, 12)
      hIconTranslate := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 5, 16) : ExtractIcon(A_ScriptDir "\Icons\Translate.ico", 1, 16)
      Icons := [hIconGoogle, hIconChange, hIconPlayPause, hIconStop, hIconTranslate]
   }

   DetectHiddenWindows, On
   Loop 2
   {
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconChange      ,, % "ahk_id" hButtChange%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconPlayPause   ,, % "ahk_id" hButtPlayPause%A_Index%
      PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconStop         ,, % "ahk_id" hButtStop%A_Index%
   }
   PostMessage, BM_SETIMAGE, IMAGE_ICON, hIconTranslate,, ahk_id %hButtTranslate%
   PostMessage, WM_SETICON,, hIconGoogle,, ahk_id %hGui%
   PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[from = "ru" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   DetectHiddenWindows, Off
   
   GuiControlGet, Button8, Pos
   Gui, Show, % "hide h" Button8Y + Button8H + 6, Google Translate
   GuiControl, Focus, Edit1

   if !WinExist("Google Translate ahk_pid" ScriptPID)
   {
      IniRead, xGUI, % IniName, Location, xGUI, % " "
      IniRead, yGUI, % IniName, Location, yGUI, % " "
      Gui, Show, % (xGUI = "" ? "" : "x" xGUI " y" yGUI " ") "w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   else
   {
      WinGetPos, X, Y,,, % "ahk_id " (GuiActive ? GuiActive : GUIs[GUIs.MaxIndex()])
      Gui, Show, % "x" X + 60 " y" Y + 40 " w" (SaveSize && Edit1W ? Edit1W + 20 : 330)
   }
   GUIs.Insert(hGui), GuiActive := ""
   Return
   
GuiSize:
   if !IsControlPos
      return

   SetWinDelay, 0
   if (SIZING ~= WMSZ_TOP "|" WMSZ_TOPLEFT "|" WMSZ_TOPRIGHT)
   {
      if A_GuiHeight - Edit1HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      }
   }
   else
   {
      if A_GuiHeight - Edit2HPos > 32
         Resizing(A_GuiWidth, A_GuiHeight, 2)
      else
      {
         if (GetControlPos = "")
            _WinGetControlPos(A_Gui), GetControlPos := 1
         Resizing(A_GuiWidth, A_GuiHeight, 1)
      }
   }
   return

PlayPause:
   if IsObject(Player)
   {
      if Playing := !Playing
         Player.Controls.pause()
      else
         Player.Controls.play()
   }
   else
   {
      hGui := A_Gui, Control := A_GuiControl
      SetTimer, PlayPauseTimer, -1
   }
   return

PlayPauseTimer:
   n := SubStr(Control, 0)
   ControlGet, Text, Selected,, Edit%n%, ahk_id %hGui%
   if (Text = "")
      ControlGetText, Text, Edit%n%, ahk_id %hGui%
   ControlGetText, lng, ComboBox%n%, ahk_id %hGui%
   Say(RegExReplace(Text, "\R+", "`n"), LangArray[lng])
   return

Stop:
   Player.close()
   Playing := Player := ""
   StopButtonEnableDisable(0)
   return
   
Translate:
   GuiControlGet, from,, ComboBox1
   from := LangArray[from]
   GuiControlGet, to,, ComboBox2
   to := LangArray[to]
   GuiControlGet, SourseText,, Edit1
   if (SourseText = "")  {
      ToolTip Введите в окно текст для перевода!
      Sleep, 1500
      ToolTip
      Return
   }
   TransText := Translate(RegExReplace(SourseText, "\R", "`r`n"), from, to, 0)

   GuiControl,, Edit2, % TransText
   GuiControl, Focus, Edit1
   Return

GuiClose:
   if (A_Gui = GUIs.1)
      IniWriteSizeGui(A_Gui), SaveSize ? IniWriteSizeEdit(A_Gui)
   else
   {
      for k,v in GUIs
         if (A_Gui = v)
            break
      GUIs.Remove(k)
   }
   
   Gui, %A_Gui%: Destroy
   IfWinNotExist, Google Translate ahk_pid %ScriptPID%
   {
      Player.close(), Player := "", Voice := []
      FileDelete, % A_ScriptDir "\mp3\*.mp3"
      Loop % Icons.MaxIndex()
         DllCall("DestroyIcon", Ptr, Icons[A_Index])
      Icons := "", GUIs := []
   }
   return
}

TranslateInTheSameWindow(hwnd, SourceText)
{
   Translation := Translate(RegExReplace(SourceText, "\R", "`r`n"), from, to, 0)

   For k,v In LangArray
      SourceLangNames .= "|" . k . (v = from ? "|" : "")
    , TargetLangNames .= "|" . k . (v = to   ? "|" : "")
   
   Gui, %hwnd%:Default
   GuiControl,, ComboBox1, % SourceLangNames
   GuiControl,, ComboBox2, % TargetLangNames
   GuiControl,, Edit1, % SourceText
   GuiControl,, Edit2, % Translation
}

Resizing(W, H, mode)
{
   E1H := H - Edit1HPos
   E2Y := H - Edit2YPos, E2H := H - Edit2HPos
   B2Y := H - Button2YPos, B6Y := H - Button6YPos

   if mode = 1
   {
      GuiControl, Move, Edit1, % "w" W - 20 " h" E1H
      GuiControl, Move, Edit2, % "w" W - 20 " y" E2Y
      GuiControl, MoveDraw, Button2, % "y" B2Y
      GuiControl, MoveDraw, Button3, % "y" B2Y
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120) " y" B2Y
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10) " y" B2Y + 43
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112) " y" B2Y + 39
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297) " y" B2Y + 38
   }
   else
   {
      GuiControl, Move, Edit1, % "w" W - 20
      GuiControl, Move, Edit2, % "w" W - 20 " h" (E2H > 32 ? E2H : 32)
      GuiControl, MoveDraw, Static2, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
      GuiControl, Move, ComboBox2, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
      GuiControl, MoveDraw, Button5, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
      GuiControl, MoveDraw, Button4, % "x" (W > 200 ? W - 80 : 120)
   }
   GuiControl, Move, Static1, % "x" (W > 330 ? 10 + (W - 330)//2 : 10)
   GuiControl, Move, ComboBox1, % "x" (W > 330 ? 112 + (W - 330)//2 : 112)
   GuiControl, MoveDraw, Button1, % "x" (W > 330 ? 297 + (W - 330)//2 : 297)
   GuiControl, MoveDraw, Button6, % "y" B6Y
   GuiControl, MoveDraw, Button7, % "y" B6Y
   GuiControl, MoveDraw, Button8, % "x" (W > 200 ? W - 80 : 120) " y" B6Y
}

InitLangArray()
{
   Languages =
   (LTrim C
      Азербайджанский|az
      Албанский|sq
      Английский|en
      Арабский|ar
      Армянский|hy
      Африкаанс|af
      Баскский|eu
      Белорусский|be
      Болгарский|bg
      Венгерский|hu
      Вендский|sb
      Вьетнамский|vi
      Голландский|nl
      Греческий|el
      Грузинский|ka
      Датский|da
      Иврит|he
      Идиш|ji
      Индонезийский|id
      Исландский|is
      Испанский|es
      Итальянский|it
      Каталонский|ca
      Китайский|zh
      Китайский (Аомынь)|zh-cn
      Китайский (Тайвань)|zh-tw
      Корейский|ko
      Латынь|la
      Латышский|lv
      Литовский|lt
      Македонский|mk
      Малайский|ms
      Мальтийский|mt
      Немецкий|de
      Норвежский|no
      Польский|pl
      Португальский|pt
      Румынский|ro
      Русский|ru
      Сербский|sr
      Словацкий|sk
      Словенский|sl
      Суахили|sw
      Тайский|th
      Турецкий|tr
      Украинский|uk
      Урду|ur
      Фарси|fa
      Финский|fi
      Французский|fr
      Хинди|hi
      Хорватский|hr
      Чешский|cs
      Шведский|sv
      Эсперанто|eo
      Эстонский|et
      Японский|ja
   )

   Loop, parse, Languages, `n, `r
   {
      Key := RegExReplace(A_LoopField, "(.*)\|.*", "$1")
      Value := RegExReplace(A_LoopField, ".*\|(.*)", "$1")
      LangArray[Key] := Value
   }
}

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   if (ext = "ico")
      IconNumber := 0

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Указанный файл не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError "."
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge)
         , hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall)
         , hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

Ping(strHost)
{
   Loop 4
      bRet := ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
   until bRet
   return bRet
}

Say(Text, lng)
{
   static PlaylistOpenNoMedia := 6, Stopped := 1
   
   Player := ComObjCreate("WMPlayer.OCX")
   objPlaylist := Player.currentPlaylist

   for k,v in Voice
      if (v.Text = RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1") && v.lng = lng)
      {
         var := 1
         break
      }

   if var
   {
      Loop % v.mp3.MaxIndex()
         objPlaylist.appendItem(Player.newMedia(v.mp3[A_Index]))
   }
   else
   {
      if !Ping("translate.google.com")
      {
         MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
         Return
      }

      PreUrl := "http://translate.google.com/translate_tts?ie=UTF-8&tl=" lng "&q="
      Strings := []
      If StrLen(Text) > 100
      {
         StartPos := 1
         While StartPos := RegExMatch(Text, ".+?(\.|$)", Found, StartPos) + StrLen(Found)
         {
            if StrLen(Found) > 100
            {
               StartPos_ := 1
               While StartPos_ := RegExMatch(Found, "(.{1,99}([ ,\t\n]|$))|(.{1,100})", Found_, StartPos_) + StrLen(Found_)
                  Strings.Insert(Found_)
            }
            else
               Strings.Insert(Found)
         }
      }
      else
         Strings.1 := Text

      if !FileExist(A_ScriptDir "\mp3")
         FileCreateDir, %A_ScriptDir%\mp3

      Voice.Insert(o := {Text: RegExReplace(Text, "^\s*(\S.+\S)(\s+$|$)", "$1"), lng: lng, mp3: []})
      Loop % count := Strings.MaxIndex()
      {
         URLDownloadToFile, % PreUrl . URIEncode(RegExReplace(Strings[A_Index], "^\s*([^\s]+)\s*$", "$1"))
            , % mp3file := A_ScriptDir "\mp3\" A_TickCount ".mp3"
         objPlaylist.appendItem(Player.newMedia(mp3file))
         o.mp3.Insert(mp3file)
      }
   }
   StopButtonEnableDisable(1)
   Player.Controls.play()
   While Player.PlayState != Stopped && Player.OpenState != PlaylistOpenNoMedia && IsObject(Player)
      Sleep, 100
   Player.close(), Player := objPlaylist := ""
   StopButtonEnableDisable(0)
}

StopButtonEnableDisable(key)
{
   WinGet, List, List, Google Translate ahk_pid %ScriptPID%
   Loop % List
   {
      Control , % key ? "Enable" : "Disable",, Button3, % "ahk_id" List%A_Index%
      Control , % key ? "Enable" : "Disable",, Button7, % "ahk_id" List%A_Index%
   }
}

WM_COMMAND(wp, lp)
{
   static EN_SETFOCUS := 0x100, CBN_SETFOCUS := 3
   
   if !WinActive("Google Translate") || !(wp>>16 = EN_SETFOCUS || wp>>16 = CBN_SETFOCUS)
      return
   
   Gui, %A_Gui%:Default
   DetectHiddenWindows, On
   
   if (wp>>16 = EN_SETFOCUS)
   {
      GuiControlGet, Name, Name, %lp%
      if Name != Source
         return
      
      GuiControlGet, lang,, ComboBox1
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList()[lang = "Русский" ? "Ru" : "En"],, ahk_id %A_ScriptHwnd%
   }
   
   if (wp>>16 = CBN_SETFOCUS)
      PostMessage, WM_INPUTLANGCHANGEREQUEST,, GetLayoutList().Ru,, ahk_id %A_ScriptHwnd%
   
   DetectHiddenWindows, Off
}

GetLayoutList()
{
   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
   SetFormat, IntegerFast, D
   Return {En: En, Ru: Ru}
}

WM_SIZING(wp)
{
   SIZING := wp
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin, UInt, eventMax
                                    , Ptr, hmodWinEventProc, Ptr, lpfnWinEventProc
                                    , UInt, idProcess, UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

WinGetControlPos(hWinEventHook, event, hwnd)
{
   if !GetActiveWindow()
      return
   
   if (event = EVENT_SYSTEM_MOVESIZEEND)
      IsControlPos := GetControlPos := "", CorrectPos(hwnd)
   else
      _WinGetControlPos(hwnd)
}

_WinGetControlPos(hwnd)
{
   Gui, %hwnd%:Default
   
   GuiControlGet, Edit1, Pos
   GuiControlGet, Edit2, Pos
   GuiControlGet, Button2, Pos
   GuiControlGet, Button6, Pos
   
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")

   Edit1HPos := ClientH - Edit1H
   Edit2HPos := ClientH - Edit2H
   Edit2YPos := ClientH - Edit2Y
   Button2YPos := ClientH - Button2Y
   Button6YPos := ClientH - Button6Y
   IsControlPos := 1
}

CorrectPos(hwnd)
{
   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &Rect)
   ClientH := NumGet(Rect, 12, "UInt")
   
   Gui, %hwnd%:Default
   GuiControlGet, Edit2, Pos
   GuiControl, Move, Edit2, % "h" ClientH - Edit2Y - 34
   
   Loop 3
      GuiControl, MoveDraw, % "Button" A_Index + 5, % "y" ClientH - 29
}

GetActiveWindow()
{
   WinGetActiveTitle, Title
   WinGetClass, Class, A
   WinGet, PID, PID, A
   Return (Title = "Google Translate" && Class = "AutoHotkeyGUI" && PID = ScriptPID) ? WinExist("A") : ""
}

IniReadSizeEdit()
{
   IniRead, Edit1W, % IniName, Location, Edit1W, % " "
   IniRead, Edit1H, % IniName, Location, Edit1H, % " "
   IniRead, Edit2H, % IniName, Location, Edit2H, % " "
   Return {Edit1W: Edit1W, Edit1H: Edit1H, Edit2H: Edit2H}
}

IniWriteSizeEdit(hwnd)
{
   ControlGetPos,,, Edit1W, Edit1H, Edit1, % "ahk_id" hwnd
   ControlGetPos,,,, Edit2H, Edit2, % "ahk_id" hwnd
   
   IniWrite, % Edit1W, % IniName, Location, Edit1W
   IniWrite, % Edit1H, % IniName, Location, Edit1H
   IniWrite, % Edit2H, % IniName, Location, Edit2H
}

IniWriteSizeGui(hwnd)
{
   WinGetPos, X, Y,,, % "ahk_id" hwnd
   IniWrite, % X, % IniName, Location, xGUI
   IniWrite, % Y, % IniName, Location, yGUI
}

GetEditFocus()
{
   if !WinActive("Google Translate ahk_pid" ScriptPID)
      return
   
   ControlGetFocus, Control, A
   return InStr(Control, "Edit") ? SubStr(Control, 0) : ""
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg