1 (изменено: hrnvam, 2011-03-28 14:46:16)

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

Здравствуйте.
Здесь интересный скрипт (переводчик) http://forum.script-coding.com/viewtopic.php?id=4492
Подскажите как сделать текст белым и фон синим + горячею клавишу поменять на "T" вместо "CTRL+C+C" (если это возможно)

Пример (прога Client for Google Translate - переводит только текст в браузере)
http://s43.radikal.ru/i101/1103/ff/6f12a339d211.png

2 (изменено: Grey, 2011-05-16 22:11:07)

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

hrnvam пишет:

...горячею клавишу поменять на "T" вместо "CTRL+C+C" (если это возможно)

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

hrnvam пишет:

...как сделать текст белым и фон синим

Где-то я видел пример оформления цвета фона и текста тултипа в не зависимости от установленных цветов операционки, только после чистки форума не могу найти (искомое - AHK: изменение цвета фона ToolTip).

3 (изменено: hrnvam, 2011-05-17 14:36:28)

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

Есть кто в этом шарит?

4

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

Напишу, как будет время.

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

5

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

Жду

6

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

В таком виде можно выбрать горячую клавишу, цвет текста и фона:

;#NoTrayIcon    ; не отображать иконку скрипта в трее
;--------------------------------------------------
; Translate text using translate.google.com
; by Mikhail Kuropyatnikov (micdelt@mail.ru)
;
; доработано teadrinker (dfiveg@mail.ru):
; выбор горячей клавиши
; выбор цвета фона и текста в ToolTip'е
;--------------------------------------------------

#NoEnv
SetBatchLines, -1

lang1 = en
lang2 = ru

ColorBack = 0x313A47   ; цвет фона в RGB
ColorText = 0xFFFFFF   ; цвет текста в RGB

HotKey = vk54   ; T, но лучше изменить на ^!vk54 (Ctrl+Alt+T),
                ; чтобы можно было пользоваться Т как обычно

HotKey, %HotKey%, Translate, On
Return

Translate:
   Clipboard = 
   SendInput, ^{vk43}
   ClipWait, 2
   if ErrorLevel
   {
      MsgBox, Буфер обмена пуст!
      Return
   }
   Translate(lang1, lang2)
   Return

Translate(to,anti)
{
   global hTT, ColorBack, ColorText
   use_anti = 0
   translate_to := to
   if clipboard =
       return

   Transform, unicodeClipboard, Unicode
anti_translate:
   url := "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="
            . uriEncode(unicodeClipboard) . "&langpair=%7C" . translate_to

   ; simulate UrlDownloadToVAR
   UrlDownloadToFile, %url%, %A_ScriptDir%\translate.html
   FileRead, json_trans, %A_ScriptDir%\translate.html
   json_trans := UTF82Ansi(json_trans)

   rgxText = \Q{"translatedText":"\E(?P<Text>.*)\"\,
   rgxDetectedLanguage = \Q"detectedSourceLanguage":"\E(?P<DetectedLanguage>.*)\"\}
   rgxDetails = \Q"responseDetails": "\E(?P<Details>.*)\"\,
   rgxStatus = \Q"responseStatus": \E(?P<Status>\d*)

   RegExMatch(json_trans,rgxText,trans)
   RegExMatch(json_trans,rgxDetails,trans)
   RegExMatch(json_trans,rgxStatus,trans)
   RegExMatch(json_trans,rgxDetectedLanguage,trans)

   if transStatus = 200
   {
      if (transDetectedLanguage = to and translate_to <> anti)
      {
         translate_to := anti
         goto anti_translate
      }

      t := UnHTM(UnSlashUnicode(transText))
      ; split long line to smaller lines about 40-50 symbols length
      t := RegExReplace(t,".{40,50}(\s)","$0`n")
      if transDetectedLanguage =
      {
         WinClose, ahk_id %hTT%
         hTT := TrackToolTip(t, "", 0, ColorBack, ColorText)
      }
      else
      {
         WinClose, ahk_id %hTT%
         hTT := TrackToolTip(transDetectedLanguage ">" translate_to ":" t, "", 0, ColorBack, ColorText)
      }

      ; copy result to clipboard
      Clipboard := t
   }
   else
   {
      WinClose, ahk_id %hTT%
      hTT := TrackToolTip(transDetails, "", 0, ColorBack, ColorText)
   }
}

~LButton:: ; Remove tooltip left click
WinClose, ahk_id %hTT%
return

;---------------------------------------
; Convert strings
;---------------------------------------

/*
CP_ACP   = 0
CP_OEMCP = 1
CP_MACCP = 2
CP_UTF7  = 65000
CP_UTF8  = 65001
*/

UTF82Ansi(zString)
{
   Ansi2Unicode(zString, wString, 65001)
   Unicode2Ansi(wString, sString, 0)
   Return sString
}

Ansi2Unicode(ByRef sString, ByRef wString, CP = 0)
{
     nSize := DllCall("MultiByteToWideChar"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", 0
      , "int",  0)

   VarSetCapacity(wString, nSize * 2)

   DllCall("MultiByteToWideChar"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", &wString
      , "int",  nSize)
}

Unicode2Ansi(ByRef wString, ByRef sString, CP = 0)
{
     nSize := DllCall("WideCharToMultiByte"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &wString
      , "int",  -1
      , "Uint", 0
      , "int",  0
      , "Uint", 0
      , "Uint", 0)

   VarSetCapacity(sString, nSize)

   DllCall("WideCharToMultiByte"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &wString
      , "int",  -1
      , "str",  sString
      , "int",  nSize
      , "Uint", 0
      , "Uint", 0)
}

;-------------------------------------------------
; HTML encode/decode
;------------------------------------------------

UriEncode(str)
{ ; v 0.3 / (w) 24.06.2008 by derRaphael / zLib-Style release
   b_Format := A_FormatInteger
   data := ""
   SetFormat,Integer,H
   Loop,Parse,str
      if ((Asc(A_LoopField)>0x7f) || (Asc(A_LoopField)<0x30) || (asc(A_LoopField)=0x3d))
         data .= "%" . ((StrLen(c:=SubStr(ASC(A_LoopField),3))<2) ? "0" . c : c)
      Else
         data .= A_LoopField
   SetFormat,Integer,%b_format%
   return data
}

UriDecode(str)
{ ; v 0.1 / (w) 28.06.2008 by derRaphael / zLib-Style release
   Loop,Parse,str,`%
      txt := (A_Index=1) ? A_LoopField : txt chr("0x" substr(A_LoopField,1,2)) SubStr(A_LoopField,3)
   return txt
}

UnHTM( HTM ) { ; Remove HTML formatting / Convert to ordinary text     by SKAN 19-Nov-2009
 Static HT     ; Forum Topic: www.autohotkey.com/forum/topic51342.html
 IfEqual,HT,,   SetEnv,HT, % "&aacutea&acirca&acute?&aelig?&agravea&amp&aringa&atildea&au"
 . "mla&bdquo„&brvbar¦&bull•&ccedilc&cedil?&cent?&circ?&copy©&curren¤&dagger†&dagger‡&deg"
 . "°&divide?&eacutee&ecirce&egravee&eth?&eumle&euro?&fnof?&frac12?&frac14?&frac34?&gt>&h"
 . "ellip…&iacutei&icirci&iexcl?&igravei&iquest?&iumli&laquo«&ldquo“&lsaquo‹&lsquo‘&lt<&m"
 . "acr?&mdash—&microµ&middot·&nbsp &ndash–&not¬&ntilden&oacuteo&ocirco&oelig?&ograveo&or"
 . "df?&ordm?&oslasho&otildeo&oumlo&para¶&permil‰&plusmn±&pound?&quot""&raquo»&rdquo”&reg"
 . "®&rsaquo›&rsquo’&sbquo‚&scarons&sect§&shy&sup1?&sup2?&sup3?&szlig?&thorn?&tilde?&tim"
 . "es?&trade™&uacuteu&ucircu&ugraveu&uml?&uumlu&yacutey&yen?&yumly"
 TXT := RegExReplace( HTM,"<[^>]+>" )               ; Remove all tags between  "<" and ">"
 Loop, Parse, TXT, &`;                              ; Create a list of special characters
   L := "&" A_LoopField ";", R .= (!(A_Index&1)) ? ( (!InStr(R,L,1)) ? L:"" ) : ""
 StringTrimRight, R, R, 1
 Loop, Parse, R , `;                                ; Parse Special Characters
  If F := InStr( HT, A_LoopField )                  ; Lookup HT Data
    StringReplace, TXT,TXT, %A_LoopField%`;, % SubStr( HT,F+StrLen(A_LoopField), 1 ), All
  Else If ( SubStr( A_LoopField,2,1)="#" )
    StringReplace, TXT, TXT, %A_LoopField%`;, % Chr(SubStr(A_LoopField,3)), All
Return RegExReplace( TXT, "(^\s*|\s*$)")            ; Remove leading/trailing white spaces
}

UnSlashUnicode(s)
{
  ; unslash unicode sequences like \u0026
  ; by Mikhail Kuropyatnikov 2009 (micdelt@mail.ru)
   rx = \\u([0-9a-fA-F]{4})
   pos = 0

   loop
   {
   pos := RegExMatch(s,rx,m,pos+1)
   if (pos = 0)
      break
   StringReplace, s, s, %m%, % Chr("0x" . SubStr(m,3,4))
   }

   return s
}

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0
            , x = ""   ; координаты, если не указаны, то вблизи курсора
            , y = "" )
{
   ; BalloonTip — это ToolTip с хвостиком
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon.

   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (xtt = "" || ytt = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      yyy := y = "" ? ytt + 10 : y
   }

   NumPut(VarSetCapacity(TOOLINFO, 40), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, 500         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7 (изменено: Grey, 2011-05-21 13:50:46)

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

ColorBack = 0x313A47   ; цвет фона в RGB
ColorText = 0xFFFFFF   ; цвет текста в RGB

Очень удобный переводчик, пользуюсь им ещё взяв с той темы, а тут апдэйт - спасибо! Правда заданные в скрипте цвет фона и цвет текста для тултипа у меня системные (W7).

8

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

Так ты можешь другие задать! Или ты в том смысле, что цвета не меняются?

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

9

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

teadrinker пишет:

Или ты в том смысле, что цвета не меняются?

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

10

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

Ремарка к сообщениям TTM_SETTIPBKCOLOR и TTM_SETTIPTEXTCOLOR:

When visual styles are enabled, this message has no effect.

Возможно, в этом проблема.

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

11

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

Вы правы, в упрощенной теме (не прозрачные окантовки окон) тултип имеет цвета отличные от системных.

12

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

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

13 (изменено: Grey, 2012-01-09 02:54:41)

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

Досадная строка раздражает, когда пытаешься воспользоваться переводчиком:

Suspected Terms of Service Abuse. Please see http://code.google.com/apis/errors

Гуголь поставил на коммерческие рельсы свой переводчик, и теперь 1000000 символов стоит 20$. В общем, предлагаю альтернативу, отписывайте свои багрепорты :

#NoEnv
#SingleInstance, Force
DetectHiddenWindows, On
CoordMode, Mouse
SetBatchLines, -1
VarSetCapacity(TRACKMOUSEEVENT, 16, 0)
NumPut(16, TRACKMOUSEEVENT, 0) ; cbSize
NumPut(3, TRACKMOUSEEVENT, 4) ; dwFlags
NumPut(1, TRACKMOUSEEVENT, 12) ; dwHoverTime
Tracking:=False, TextColor:="cBlue"
TipText:=XPos:=YPos:=0, OffXPos:=OffYPos:=35
TipBackColor:=0x808080, TipForeColor:=0xC0C0C0
VarSetCapacity(TOOLINFO, 44, 0), NumPut(44, TOOLINFO, 0)
NumPut(0xA0, TOOLINFO, 4) ; TTF_TRACK+TTF_ABSOLUTE
NumPut(hToolTip, TOOLINFO, 12), NumPut(&TipText, TOOLINFO, 36)
TipWidth:=A_ScreenWidth/3, hToolTip:=CreateToolTip()
DirectLang1:="auto", DirectLang2:="en", DirectLang3:="ru"
PostMessage, 0x411,, &TOOLINFO,, % "ahk_id"hToolTip ; TTM_TRACKACTIVATE
Menu, Tray, NoStandard
Menu, Tray, Icon, shell32.dll, 14
Menu, Tray, Tip, Online translator
Menu, Tray, Add, &About, About
Menu, Tray, Add
Menu, Tray, Add, &Exit (Tilde+Esc), ExitScript
OnMessage(0x404, "WM_LBUTTONUP") ; WM_USER+4
Return

~vkA3:: ; rctrl
   If IsPaused Or IsAbout
      Return
   Else If (!GetKeyState("vk04", "P") ; mmb
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang1, DirectLang3)
   Else If (GetKeyState("vk04", "P")
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang3, DirectLang2)
   KeyWait, vkA3
   Return

~LButton::
   If IsPaused Or IsAbout
      Return
   Else If !GetKeyState("vkA3", "P")
      StopTimer(), OnWork:=False
   Return

TrackingCursor:
   MouseGetPos, XPosAbs, YPosAbs
   If (XPos!=XPosAbs Or YPos!=YPosAbs)
   {
      XPos:=XPosAbs, YPos:=YPosAbs
      SendMessage, 0x41E,, &TOOLINFO,, % "ahk_id"hToolTip ; TTM_GETBUBBLESIZE
      Width:=ErrorLevel&0xFFFF, Height:=ErrorLevel>>16
      CurXPos:=XPosAbs, CurYPos:=YPosAbs
      If (CurXPos+OffXPos+Width>A_ScreenWidth)
         CurXPos-=(Width+OffXPos)
      Else
         CurXPos+=OffXPos
      If (CurYPos+OffYPos+Height>A_ScreenHeight)
         CurYPos-=(Height+OffYPos)
      Else
         CurYPos+=OffYPos
      PostMessage, 0x412,, (CurXPos|CurYPos<<16),
                 , % "ahk_id"hToolTip ; TTM_TRACKPOSITION
   }
   SendMessage, 0x413, TipBackColor,,
              , % "ahk_id"hTooltip ; TTM_SETTIPBKCOLOR
   SendMessage, 0x414, TipForeColor^0xFFFFFF,,
              , % "ahk_id"hTooltip ; TTM_SETTipForeColor
   Return

About:
   IsAbout:=True
   If !Paused
   {
      Menu, Tray, Icon, shell32.dll, 28
      StopTimer()
   }
   Gui, GUI1: Font, Bold
   Gui, GUI1: Add, Text
      , x32 y30 w140 h20 Center
      , Online translator
   Gui, GUI1: Font
   Gui, GUI1: Add, Text
      , x32 y50 w140 h20 Center
      , Made using AutoHotkey
   Gui, GUI1: Font, Underline cBlue
   Gui, GUI1: Add, Text
      , x24 y90 w156 h20 gAHKHome HwndGUIhWnd Center
      , www.autohotkey.com
   Gui, GUI1: Font
   Gui, GUI1: Add, GroupBox, x22 y10 w160 h110
   Gui, GUI1: -MinimizeBox -Resize HwndGUINamehWnd
   Gui, GUI1: Show, Center h135 w205, About
   hHandCursor:=DllCall("LoadCursor", "UInt", 0, "Int", 32649) ; IDC_HAND
   DllCall("SetClassLong", "UInt", GUIhWnd, "Int", -12, "UInt", hHandCursor)
   NumPut(GUINamehWnd, TRACKMOUSEEVENT, 8) ; hwndTrack
   OnMessage(0x200, "WM_MOUSEMOVE"), OnMessage(0x2A1, "WM_MOUSEHOVER")
   OnMessage(0x2A3, "WM_MOUSELEAVE")
   Return

AHKHome:
   Run, http://www.autohotkey.com,, UseErrorLevel
   Return

Gui1GuiClose:
   Gui, GUI1: Destroy
   IsAbout:=False
   If !IsPaused
      Menu, Tray, Icon, shell32.dll, 14
   Return

~vkC0 & Esc::
ExitScript:
   PostMessage, 0x405,, &TOOLINFO,
              , % "ahk_id"hToolTip ; TTM_DELTOOLA
   DllCall("DestroyWindow", "UInt", hToolTip)
   ExitApp

Translate(From, To)
{
   global
   Clipboard:=TransText:=""
   Send, ^{Insert} ; ctrl+ins
   ClipWait, 2
   If ErrorLevel
   {
      MsgBox, 786448, Error, Clipboard is empty!, 1
      Return
   }
   Transform, UnicodeClipboard, Unicode
   URL:="http://translate.google.com/translate_a/t?client=a&text="
      . UriEncode(UnicodeClipboard) . "&sl=" . From . "&tl=" . To
   URLDownloadToFile, % URL, % A_ScriptDir "\translate.html"
   FileRead, JSON_Trans, % A_ScriptDir "\translate.html"
   StringReplace, JSON_Trans, JSON_Trans, \r\n,`r`n, All
   StringReplace, JSON_Trans, JSON_Trans, \", ", All
   RetrievedDirectLang:=JSON(JSON_Trans, "src")
   ElapsedTime:=JSON(JSON_Trans, "server_time")
   Loop
   {
      Sentence:=JSON(JSON_Trans, "sentences["(A_Index-1)"].trans")
      If Sentence
         TransText.=Sentence
      Else
         Break
   }
   TipText:=Chr(0x95)" "RetrievedDirectLang ">"To
                              . " (elapsed time: "ElapsedTime "ms) "Chr(0x95)
                              . "`n"TransText
   OnWork:=True, SetToolTipText(&TipText), ResumeTimer()
}

JSON(ByRef js, s, v="")
{
   j=% js
   Loop, Parse, s, .
   {
      p=2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop
      {
         If (!p:=RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*"
            . "((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)"
            . "?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2==q2 Or q2=="*")
         {
            j=% x3
            z+=p+StrLen(x2)-2
            If (q3!="" And InStr(j, "[")==1)
            {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z+=1+RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|"
                  . "(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                  . SubStr(A_LoopField, 1)+1 . "}", x)
                  j=% x1
               }
            }
            Break
         }
         Else p+=StrLen(x)
      }
   }
   If v!=
   {
      vs="
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)"
         . "?|true|false|null?)\s*(?:""|')*\s*$", vx)
      And (vx1+0 Or vx1==0 Or vx1=="true"
                           Or vx1=="false" Or vx1=="null" Or vx1=="nul"))
         vs:="", v:=vx1
      StringReplace, v, v, ", \", All
      js:=SubStr(js, 1, z:=RegExMatch(js, ":\s*", zx, z)+StrLen(zx)-1)
                          . vs . v . vs . SubStr(js, z + StrLen(x3)+1)
   }
   Return, j=="false" ? 0:j=="true" ? 1:j=="null" Or j=="nul"
           ? "":SubStr(j, 1, 1)=="""" ? SubStr(j, 2, -1):j
}

UriEncode(Str)
{
   b_Format:=A_FormatInteger
   Data:=""
   SetFormat, Integer, Hex
   Loop, Parse, Str
      If ((Asc(A_LoopField)>0x7f) Or (Asc(A_LoopField)<0x30)
                                  Or (Asc(A_LoopField)=0x3d))
         Data.="%" . ((StrLen(c:=SubStr(Asc(A_LoopField), 3))<2) ? "0" . c:c)
      Else
         Data.=A_LoopField
   SetFormat, Integer, % b_Format
   Return, Data
}

Ansi2Unicode(ByRef sString, ByRef wString, CP=0)
{
   nSize:=DllCall("MultiByteToWideChar", "UInt", CP
                                       , "UInt", 0
                                       , "UInt", &sString
                                       , "Int", -1
                                       , "UInt", 0
                                       , "Int", 0)
   VarSetCapacity(wString, nSize*2)
   DllCall("MultiByteToWideChar", "UInt", CP
                                , "UInt", 0
                                , "UInt", &sString
                                , "Int", -1
                                , "UInt", &wString
                                , "Int", nSize)
}

Unicode2Ansi(ByRef wString, ByRef sString, CP=0)
{
   nSize:=DllCall("WideCharToMultiByte", "UInt", CP
                                       , "UInt", 0
                                       , "UInt", &wString
                                       , "Int", -1
                                       , "UInt", 0
                                       , "Int", 0
                                       , "UInt", 0
                                       , "UInt", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "UInt", CP
                                , "UInt", 0
                                , "UInt", &wString
                                , "Int", -1
                                , "Str", sString
                                , "Int", nSize
                                , "UInt", 0
                                , "UInt", 0)
}

CreateToolTip()
{
   global
   hToolTip:=DllCall("CreateWindowEx", "UInt", 8 ; WS_EX_TOPMOST
                                     , "Str", "tooltips_class32" ; TOOLTIP_CLASS
                                     , "Str", ""
                                     , "UInt", 3 ; TTS_NOPREFIX+TTS_ALWAYSTIP
                                     , "UInt", 0x80000000 ; CW_USEDEFAULT
                                     , "UInt", 0x80000000
                                     , "UInt", 0x80000000
                                     , "UInt", 0x80000000
                                     , "UInt", 0
                                     , "UInt", 0
                                     , "UInt", 0
                                     , "UInt", 0)
   PostMessage, 0x404,, &TOOLINFO,
              , % "ahk_id"hToolTip ; TTM_ADDTOOLA
   PostMessage, 0x411, 1, &TOOLINFO,, % "ahk_id"hToolTip ; TTM_TRACKACTIVATE
   PostMessage, 0x418,, TipWidth,, % "ahk_id"hToolTip ; TTM_SETMAXTIPWIDTH
   Dllcall("UxTheme\SetWindowTheme", "Int", hToolTip, "Str", "", "Str", "")
   Return, hToolTip
}

SetToolTipText(TText)
{
   global
   NumPut(TText, TOOLINFO, 36)
   PostMessage, 0x40C,, &TOOLINFO,
              , % "ahk_id"hToolTip ; TTM_UPDATETIPTEXTA
}

SetTextColor(DefinedColor)
{
   global
   TextColor:=DefinedColor
   Gui, GUI1: Font, % "Underline" DefinedColor
   GuiControl, GUI1: Font, Static3
}

WM_MOUSEMOVE()
{
   global
   If !Tracking
      DllCall("TrackMouseEvent", "Int", &TRACKMOUSEEVENT)
   Else
   {
      MouseGetPos,,,, WinControl
      If WinControl=Static3
         SetTextColor("cRed")
      Else If TextColor!=cBlue
         SetTextColor("cBlue")
   }
}

WM_MOUSEHOVER()
{
   global
   Tracking:=True
}

WM_MOUSELEAVE()
{
   global
   MouseGetPos,,,, WinControl2
   If (WinControl2="Static3")
      Return
   SetTextColor("cBlue"), Tracking:=False
}

WM_LBUTTONUP(wParam, lParam, Msg, hWnd)
{
   global
   If lParam=0x202 ; WM_LBUTTONUP
   {
      If IsAbout
         Return
      Menu, Tray, Icon, shell32.dll, % (IsPaused:=!IsPaused) ? 28:14
      IsPaused ? StopTimer():ResumeTimer()
   }
}

StopTimer()
{
   global
   SetTimer, TrackingCursor, Off
   PostMessage, 0x411,, &TOOLINFO,, % "ahk_id"hToolTip
}

ResumeTimer()
{
   global
   If OnWork
   {
      PostMessage, 0x411, 1, &TOOLINFO,, % "ahk_id"hToolTip
      SetTimer, TrackingCursor, 100
   }
}

14

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

И как же сим пользоваться? И чем отличается от предыдущего?

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

15 (изменено: Grey, 2012-01-09 02:20:59)

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

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

P.S.: В сыром виде: пользоваться ANSI интерпретатором, если компилировать, то опять-таки выбрать в Optional Parametrs: Base File (.bin) v1.1.5.1 ANSI 32-bit

16

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

На английский вообще не получается. Где это в коде отражено (про MButton) ?

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

17 (изменено: Grey, 2012-01-09 02:33:09)

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

...
~vkA3:: ; rctrl
   If IsPaused Or IsAbout
      Return
   Else If (!GetKeyState("vk04" "P")
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang1, DirectLang3)
   Else If (GetKeyState("vk04" "P")
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang3, DirectLang2)
   KeyWait, vkA3
   Return
...

Хах!, ну да, там в комменте чуть не так написчано, но сути не меняет.

18

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

Ещё такие баги: перестала клавиша "Ё" работать в любой раскладке, при переходе по ссылкам после перевода на короткое время появляется такое окно:

http://s018.radikal.ru/i503/1201/55/c18fcd5f2ad9.jpg

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

19

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

Grey пишет:
...
~vkA3:: ; rctrl
   If IsPaused Or IsAbout
      Return
   Else If (!GetKeyState("vk04" "P") ; rmb
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang1, DirectLang3)
   Else If (GetKeyState("vk04" "P")
   And A_TimeSincePriorHotkey<=500
   And A_PriorHotkey="~vkA3")
      Translate(DirectLang3, DirectLang2)
   KeyWait, vkA3
   Return
...

Так здесь

GetKeyState("vk04" "P")

между параметрами функции запятая должна быть!

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

20 (изменено: Grey, 2012-01-09 02:47:57)

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

...
~vkC0 & Esc::
...

Это можно поправить.

GetKeyState("vk04" "P")

У меня и так работает , суть не в этом, а в:

Grey пишет:

...кодировка перевода не корректно отображается, м.б. поможете разобраться почему?

21

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

Grey пишет:

У меня и так работает

Так в принципе работать не может, поскольку это

(GetKeyState("vk04" "P")

равно этому:

(GetKeyState("vk04P")

Приведи исправленный код, посмотрю уже завтра, мне на лыжи с утра

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

22 (изменено: Grey, 2012-01-09 03:50:32)

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

Исправил, не вопрос.

23

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

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

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

24

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

Решения так и нет?

25

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

Решение есть, автор идеи обновил свой код.

26

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

Да, тоже нашёл его вчера. Только направление перевода плохо определяет (у меня всё время "ru" стоит, переводит правильно). Можно определять, исходя из наличия кириллицы в исходном тексте.

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

27

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

Спасибо!

28

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

Очень медленно работает ;/

29

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

hrnvam пишет:

Очень медленно работает ;/

Сервис присылает вместе с переводом и время, переменная ElapsedTime есть в коде, только её значение не выводится. Можно это поправить, заменить в коде:

...
   ToolTip %FromLang%: %t%
...

на строку вида:

...
   ToolTip, % "elapsed time: "ElapsedTime "ms"
          . ", source lang: "FromLang "`n`n"t
...

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

30

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

Сейчас пользуюсь слегка подправленным этим вариантом, никаких тормозов не заметил — менее секунды от нажатия Ctrl+C+C до получения ответа.

http://i.imgur.com/IiG0i.png

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

31 (изменено: Grey, 2012-03-13 14:43:46)

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

А ещё у этого переводчика есть функция словаря (когда выделяешь только одно слово), и есть ещё такая фича как TTS (Text To Speech). Я добавил эти вещи в свою переделанную версию (кстати мой код работал даже тогда, когда обновлённый код с оффорума работал не полностью):

#NoEnv
DetectHiddenWindows, On
CoordMode, Mouse
OnExit, ExitScript
SetBatchLines, -1
VarSetCapacity(TRACKMOUSEEVENT, 16, 0), NumPut(16, TRACKMOUSEEVENT, 0)
NumPut(3, TRACKMOUSEEVENT, 4), NumPut(1, TRACKMOUSEEVENT, 12)
ReleaseTime:=IsTracking:=False, TextColor:="cBlue"
TipBackColor:=0x808080, TipForeColor:=0xC0C0C0, OffXPos:=OffYPos:=35
VarSetCapacity(TOOLINFO, 44, 0), NumPut(44, TOOLINFO, 0)
NumPut(0xA0, TOOLINFO, 4), NumPut(hToolTip, TOOLINFO, 12)
NumPut(&TipText, TOOLINFO, 36), hToolTip:=CreateToolTip()
Menu, Tray, NoStandard
Menu, Tray, Icon, shell32.dll, 14
Menu, Tray, Tip, % " • Online translator •`n"
                 . "RCtrl(x2)      - translate`n"
                 . "RCtrl(hold)  - play tts`n"
                 . "LClick(icon) - pause`n"
                 . "Esc(hold)     - exit"
Menu, Tray, Add, &About, About
Menu, Tray, Add
Menu, Tray, Add, &Exit, ExitScript
OnMessage(0x404, "WM_LBUTTONUP"), OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x2A1, "WM_MOUSEHOVER"), OnMessage(0x2A3, "WM_MOUSELEAVE")

~Esc::
~RCtrl::
   StartTime:=A_TickCount
   If IsPaused Or IsAbout
      Return
   If SubStr(A_ThisHotkey, 2)="Esc"
      While GetKeyState(SubStr(A_ThisHotkey, 2), "P")
      {
         Sleep, 50
         If A_TickCount-StartTime>500
         {
            KeyWait, % SubStr(A_ThisHotkey, 2)
            Gosub, ExitScript
         }
      }
   Else
   {
      If A_TickCount-ReleaseTime<150
      {
         Translate("en", "ru")
         KeyWait, % SubStr(A_ThisHotkey, 2)
         Return
      }
      While GetKeyState(SubStr(A_ThisHotkey, 2), "P")
      {
         Sleep, 50
         If A_TickCount-StartTime>250
         {
            FileGetSize, OutputVar, TTS.mp3
            SoundPlay, % OutputVar ? "TTS.mp3":"*16", 1
            KeyWait, % SubStr(A_ThisHotkey, 2)
         }
      }
      ReleaseTime:=A_TickCount
   }
   Return

~LButton::
   If IsPaused Or IsAbout
      Return
   Else If !GetKeyState("RCtrl", "P")
      StopTimer(), IsWork:=False
   Return

TrackingCursor:
   UpdateTooltipPos()
   Return

UpdateTooltipPos()
{
   global
   MouseGetPos, XPosAbs, YPosAbs
   If (XPos!=XPosAbs Or YPos!=YPosAbs)
   {
      XPos:=XPosAbs, YPos:=YPosAbs
      SendMessage, 0x41E,, &TOOLINFO,, % "ahk_id"hToolTip
      Width:=ErrorLevel&0xFFFF, Height:=ErrorLevel>>16
      CurXPos:=XPosAbs, CurYPos:=YPosAbs
      If (CurXPos+OffXPos+Width>A_ScreenWidth)
         CurXPos-=(Width+OffXPos)
      Else
         CurXPos+=OffXPos
      If (CurYPos+OffYPos+Height>A_ScreenHeight)
         CurYPos-=(Height+OffYPos)
      Else
         CurYPos+=OffYPos
      PostMessage, 0x412,, (CurXPos|CurYPos<<16),, % "ahk_id"hToolTip
   }
   SendMessage, 0x413, TipBackColor,,, % "ahk_id"hTooltip
   SendMessage, 0x414, TipForeColor^0xFFFFFF,,, % "ahk_id"hTooltip
}

About:
   IsAbout:=True
   If !IsPaused
   {
      Menu, Tray, Icon, shell32.dll, -200
      StopTimer()
   }
   Gui, Font, Bold
   Gui, Add, Text, x32 y30 w140 h20 Center, Online translator
   Gui, Font
   Gui, Add, Text, xp yp+20 wp hp Center, Made using AutoHotkey
   Gui, Font, Underline cBlue
   Gui, Add, Text, xp-8 yp+40 wp+16 hp Center gAHKHome HwndhStr
      , www.autohotkey.com
   Gui, Font
   Gui, Add, GroupBox, xp-2 yp-80 wp+4 hp+90
   Gui, -MinimizeBox -Resize HwndhWnd
   Gui, Show, Center h135 w205, About
   DllCall("SetClassLong", "UInt", hStr
                         , "Int", -12
                         , "UInt", DllCall("LoadCursor", "UInt", 0
                                                       , "UInt", 32649))
   NumPut(hWnd, TRACKMOUSEEVENT, 8)
   Return

AHKHome:
   Run, http://www.autohotkey.com,, UseErrorLevel
GuiClose:
   Gui, Destroy
   IsAbout:=False
   If !IsPaused
      Menu, Tray, Icon, shell32.dll, 14
   Return

ExitScript:
   FileDelete, Convert.html
   FileDelete, TTS.mp3
   PostMessage, A_IsUnicode ? 0x433:0x405,, &TOOLINFO,, % "ahk_id"hToolTip
   DllCall("DestroyWindow", "UInt", hToolTip)
   ExitApp

Translate(From, To)
{
   global
   Clipboard:=TransText:="", SourceLang:=From
   SendInput, ^{Insert}
   ClipWait, 2
   If ErrorLevel
   {
      MsgBox, 262160, Error, Clipboard is empty!, 1
      Return
   }
SendRequest:
   URL:="http://translate.google.com/translate_a/t?client=a&text="
      . URIEncode(Clipboard)"&tl="SourceLang
   JSON_Trans:=URLDownload(Url)
   StringReplace, JSON_Trans, JSON_Trans, \r\n,`r`n, All
   StringReplace, JSON_Trans, JSON_Trans, \", ", All
   RetrievedDirectLang:=JSON(JSON_Trans, "src")
   ElapsedTime:=JSON(JSON_Trans, "server_time")
   If % RetrievedDirectLang==From And SourceLang<>To
   {
      SourceLang:=To
      Goto, SendRequest
   }
   Loop
   {
      Sentence:=JSON(JSON_Trans, "sentences["(A_Index-1)"].trans")
      If Sentence
         TransText.=Sentence
      Else
         Break
   }
   i:=0
   Loop
   {
      If !JSON(JSON_Trans, "dict["(i+0)"].terms")
         Break
      If i=0
         TransText.="`n"
      pos:=JSON(JSON_Trans, "dict["(i+0)"].pos")
      TransText.="`n"(pos ? pos:"general")":`n"
      j:=0
      Loop
      {
         Term:=JSON(JSON_Trans, "dict["(i+0)"].terms["(j+0)"]")
         If !Term
            Break
         TransText.=Term "`n"
         j++
      }
      i++
   }
   BaseFileEnc:=A_FileEncoding
   FileEncoding
   FileDelete, Convert.html
   FileDelete, TTS.mp3
   FileAppend, % TransText, Convert.html
   FileEncoding, UTF-8
   FileRead, TransText, Convert.html
   FileEncoding, % BaseFileEnc
   URLDownload("http://translate.google.com/translate_tts?ie=UTF-8&q="
          . URIEncode(TransText)"&tl="SourceLang, "TTS.mp3")
   TipText:=" • "RetrievedDirectLang ">"SourceLang
          . " (elapsed time: "ElapsedTime "ms) • `n"ClipBoard:=TransText
   IsWork:=True, SetToolTipText(&TipText), ResumeTimer(), UpdateTooltipPos()
   PostMessage, 0x411, 1, &TOOLINFO,, % "ahk_id"hToolTip
}

JSON(ByRef js, s, v="")
{
   j:=js
   Loop, Parse, s, .
   {
      p:=2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop
      {
         If !p:=RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*"
            . "((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)"
            . "?|true|false|null?)\s*(?:,|$|\})", x, p)
            Return
         Else If (x2==q2 Or q2=="*")
         {
            j:=x3, z+=p+StrLen(x2)-2
            If (q3!="" And InStr(j, "[")==1)
            {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z+=1+RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|"
                  . "(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                  . SubStr(A_LoopField, 1)+1 . "}", x), j:=x1
               }
            }
            Break
         }
         Else p+=StrLen(x)
      }
   }
   If !v
   {
      vs:=""""
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)"
         . "?|true|false|null?)\s*(?:""|')*\s*$", vx)
      And (vx1+0 Or vx1==0 Or vx1=="true"
                           Or vx1=="false" Or vx1=="null" Or vx1=="nul"))
         vs:="", v:=vx1
      StringReplace, v, v, ", \", All
      js:=SubStr(js, 1, z:=RegExMatch(js, ":\s*", zx, z)+StrLen(zx)-1)
                          . vs . v . vs . SubStr(js, z+StrLen(x3)+1)
   }
   Return, j=="false" ? 0:j=="true" ? 1:j=="null" Or j=="nul"
           ? "":SubStr(j, 1, 1)=="""" ? SubStr(j, 2, -1):j
}

URLDownload(URL, ToFile="")
{
   Headers:="Accept-Language: ru-RU,ru;q=0.9,en;q=0.8`r`n"
   . "Accept: text/html, application/xml;q=0.9, application"
   . "/xhtml+xml, image/png, image/webp, image/jpeg, image"
   . "/gif, image/x-xbitmap, */*;q=0.1`n`r"
   . "Referer: http://translate.google.com"
   UserAgent:="Opera/9.80 (Windows NT 6.1; U; MRA 5.8 (build 4664)"
   . "; en) Presto/2.10.229 Version/11.61", Bool:=A_IsUnicode ? "W":"A"
   hModule:=DllCall("LoadLibrary"Bool, "Str", "wininet.dll")
   hIO:=DllCall("wininet\InternetOpen"Bool, "Str", UserAgent
                                             , "UInt", 1
                                             , "Str", ""
                                             , "Str", ""
                                             , "UInt", 0)
   hIOU:=DllCall("wininet\InternetOpenUrl"Bool, "UInt", hIO
                                                 , "Str", URL
                                                 , "Str", Headers
                                                 , "Int", StrLen(Headers)
                                                 , "UInt", 0x400000
                                                 , "UInt", 0)
   If ErrorLevel OR !hIOU
   {
      DllCall("FreeLibrary", "UInt", hModule)
      Return, False
   }
   VarSetCapacity(Buffer, 10240, 0)
   If % ToFile!=""
      File:=FileOpen(ToFile, 1)
   Loop
   {
      IRF:=DllCall("wininet\InternetReadFile", "UInt", hIOU
                                             , "UInt", &Buffer
                                             , "UInt", 10240
                                             , "UInt*", BytesRead)
      VarSetCapacity(Buffer, -1)
      If IRF And !BytesRead
         Break
      Else
      {
         If % ToFile!=""
            File.RawWrite(Buffer, BytesRead)
         Else
         {
            Buffer:=A_IsUnicode ? StrGet(&Buffer, "CP0"):Buffer
            Result.=SubStr(Buffer, 1, BytesRead*(A_IsUnicode ? 2:1))
         }
      }
   }
   If % ToFile!=""
      File.Close()
   DllCall("wininet\InternetCloseHandle", "UInt", hIO)
   DllCall("wininet\InternetCloseHandle", "UInt", hIOU)
   DllCall("FreeLibrary", "UInt", hModule)
   Return, Result
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

StrPutVar(String, ByRef Var, Encoding)
{
   SizeInBytes:=VarSetCapacity(Var, StrPut(String, Encoding))
   StrPut(String, &Var, Encoding)
   Return, SizeInBytes
}

CreateToolTip()
{
   global
   hToolTip:=DllCall("CreateWindowEx", "UInt", 8
                                     , "Str", "tooltips_class32"
                                     , "Str", ""
                                     , "UInt", 3
                                     , "UInt", 0x80000000
                                     , "UInt", 0x80000000
                                     , "UInt", 0x80000000
                                     , "UInt", 0x80000000
                                     , "UInt", 0
                                     , "UInt", 0
                                     , "UInt", 0
                                     , "UInt", 0)
   PostMessage, A_IsUnicode ? 0x432:0x404,, &TOOLINFO,, % "ahk_id"hToolTip
   PostMessage, 0x418,, A_ScreenWidth/3,, % "ahk_id"hToolTip
   Dllcall("UxTheme\SetWindowTheme", "Int", hToolTip, "Str", "", "Str", "")
   Return, hToolTip
}

SetToolTipText(TText)
{
   global
   NumPut(TText, TOOLINFO, 36)
   PostMessage, A_IsUnicode ? 0x439:0x40C,, &TOOLINFO,, % "ahk_id"hToolTip
}

SetTextColor(DefinedColor)
{
   global
   Gui, Font, % "Underline"TextColor:=DefinedColor
   GuiControl, Font, Static3
}

WM_MOUSEMOVE()
{
   global
   If !IsTracking
      DllCall("TrackMouseEvent", "Int", &TRACKMOUSEEVENT)
   Else
   {
      MouseGetPos,,,, WinControl
      If % WinControl="Static3"
         SetTextColor("cRed")
      Else If % TextColor!="cBlue"
         SetTextColor("cBlue")
   }
}

WM_MOUSEHOVER()
{
   global IsTracking:=True
}

WM_MOUSELEAVE()
{
   global
   If % WinControl="Static3"
      Return
   SetTextColor("cBlue"), IsTracking:=False
}

WM_LBUTTONUP(wParam, lParam, Msg, hWnd)
{
   global
   If lParam=0x202
   {
      If IsAbout
         Return
      Menu, Tray, Icon, shell32.dll, % (IsPaused:=!IsPaused) ? -200:14
      IsPaused ? StopTimer():ResumeTimer()
   }
}

StopTimer()
{
   global
   SetTimer, TrackingCursor, Off
   PostMessage, 0x411,, &TOOLINFO,, % "ahk_id"hToolTip
}

ResumeTimer()
{
   global
   If IsWork
      SetTimer, TrackingCursor, 100
}

Управление:
два быстрых нажатия на правый контрол - перевод
нажатие с небольшим удержанием того же правого контрола - прослушивание звукового файла TTS (если таковой был прислан сервисом, либо воспроизводится звук системной ошибки)
нажатие с небольшим удержанием Esc - завершение работы скрипта
Примечание:
Скрипт при работе создаёт два файла в рабочей папке, но по выходу они удаляются.

2 teadrinker Хотелось бы посмотреть Вашу версию кода.
                  .

32

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

Grey пишет:

А ещё у этого переводчика есть функция словаря

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

Grey пишет:

есть ещё такая фича как TTS (Translate To Speak)

Не удалось озвучить ничего Кроме того, там с тултипом что-то не так — сначала мелькает в левом верхнем углу, потом перемещается к курсору.
У меня сейчас так выглядит:

;--------------------------------------------------
; Translate text using translate.google.com
; after Google Translate API depreciated
;
; Ctrl+C, Ctrl+C
; Author: Mikhail Kuropyatnikov (micdelt@mail.ru),
;       Volgograd, Russia
;--------------------------------------------------
#NoEnv
SetBatchLines, -1
 
;Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return
 
~^vk43:: DoublePress()
 
~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return
 
   SendInput, {LButton Down}{LButton Up}
   Return
 
DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}
 
Translate(_from="", _to="")
{
   if Clipboard =
       return
 
   sText := Clipboard
   if (_from = "" && _to = "")
   {
      if RegExMatch(sText, "[А-Яа-я]")
         from := "ru", to := "en"
      Else
         from := "auto", to := "ru"
   }
   else
      from := _from, to := _to
 
   Url := "http://translate.google.com/translate_a/t?client=x&text="
            . UrlEncode(sText) . "&sl=" . from . "&tl=" . to
 
   ; Simulate Google Chrome
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }
 
   StringReplace, JsonTrans, JsonTrans, \r\n,`r`n, All
   StringReplace, JsonTrans, JsonTrans, \", ", All
   from:=JSON(JsonTrans, "src")
 
   Loop
   {
     Sentence:=JSON(JsonTrans, "sentences["(A_Index-1)"].trans")
     If Sentence
       TransText.=Sentence
     Else
       Break
   }
 
   ; Convert To UTF-8
   StrPutVar(TransText, Buff)
   TransText := StrGet(&Buff, "UTF-8")
 
   ; split long line to smaller lines about 40-50 symbols length
   t := RegExReplace(transText,".{40,50}(\s)","$0`n")
 
   TrackToolTip(sText "`n>`n" t, from ">" to, 0, 0xFFFFE1, 0x002288)
   ; copy result to clipboard
   clipboard := t
}
 
;-------------------------------------------------
; HTML encode/decode
;------------------------------------------------
 
UrlEncode(str)
{
   b_Format := A_FormatInteger
   SetFormat,Integer,H
   SizeInBytes := StrPutVar(str,var,"utf-8")
   Loop, %SizeInBytes%
   {
   ch := NumGet(var,A_Index-1,"UChar")
   If (ch=0)
      Break
   if ((ch>0x7f) || (ch<0x30) || (ch=0x3d))
      s .= "%" . ((StrLen(c:=SubStr(ch,3))<2) ? "0" . c : c)
   Else
      s .= Chr(ch)
   }
   SetFormat,Integer,%b_format%
   return s
}
 
WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
 
TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = "" )
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80
 
   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (xtt = "" || ytt = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      yyy := y = "" ? ytt + 10 : y
   }
 
   NumPut(VarSetCapacity(TOOLINFO, 40), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)
 
   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%
 
   SendMessage, 1048,, 500         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE
 
   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }
 
   DetectHiddenWindows, % DHW
   Return hWnd
}
 
RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
 
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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")
 
    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS
 
    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags
 
    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext
 
    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }
 
    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)
 
    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, "UInt", &buffer, "UInt", 10240, "UInt", &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length
 
        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall
 
        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }
 
        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }
 
    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}

JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

Переводит по Ctrl+C+C, тултип перемещается левой кнопкой мыши, убирается нажатием на крестик, можно вывести несколько сообщений одновременно.
Главная проблема — не "понимает" символы с надстройками, поэтому нельзя переводить с немецкого, французского. Надо тоже как-то заняться этим, исправить функцию UrlEncode().

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

33 (изменено: Grey, 2012-03-06 04:47:59)

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

Туллтип инициализируется в точке x0 y0, потом сопровождает курсор со смещением в 35ть пикселей, а звук может не прийти от сервиса в двух случаях: когда длинна текста превышает какой-то ихний там лимит, или когда на выделеное слово звукового сопровождения просто нет.

34

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

Grey пишет:

Туллтип инициализируется в точке x0 y0

Да, но делать его видимым можно уже когда он перемещён в нужное место (см. у меня ф-цию TrackToolTip()). Показывает его сообщение

SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

оно у меня в самом конце. Ну и изначально при создании окна в качестве координат у тебя использовано CW_USEDEFAULT, а у меня — нули, а размеры задаются потом сообщениями.

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

35

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

Понятно, поправил свой код. Туда ещё нужно добавить возможность менять цвета в туллтипе, и устанавливать свой хоткей.

36

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

Исправленный вариант. Добавлена возможность переводить текст с юникодовскими символами, а также переводить большие куски текста, превышающие максимальные размеры запроса. Перевод по Ctrl+C+C.

global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288

#NoEnv
SetBatchLines, -1

; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return

   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}

Translate(_from="", _to="")
{
   if Clipboard =
       return

   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH

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

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

   if GetUrlLength(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(sText, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . Found.Value(1)
         Delimiter := Found.Value(3)
         if GetUrlLength(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ Text%A_Index% . "." . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)

   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}

GetUrlLength(str)
{
   b_Format := A_FormatInteger
   SetFormat,Integer,H
   Loop, % StrLen(str)
   {
      ch := NumGet(str,A_Index-1,"UChar")
      If (ch=0)
         Break
      if ((ch>0x7f) || (ch<0x30) || (ch=0x3d))
         s .= "%" . ((StrLen(c:=SubStr(ch,3))<2) ? "0" . c : c)
      Else
         s .= Chr(ch)
   }
   SetFormat,Integer,%b_format%
   return StrLen(s)
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, 40), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, "UInt", &buffer, "UInt", 10240, "UInt", &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}

JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

37

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

Не работает.
http://postimage.org/image/bqqgzkhaf/

38

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

Ссылка на картинку так делается:
http://s15.postimage.org/509zq4u4p/uio.jpg
Не знаю, наверное, обновиться нужно, всё правильно:
Transform

Unicode [, String]: Retrieves or stores Unicode text on the clipboard. Note: The entire clipboard may be saved and restored by means of ClipboardAll, which allows "Transform Unicode" to operate without losing the original contents of the clipboard.

There are two modes of operation as illustrated in the following examples:

Transform, OutputVar, Unicode  ; Retrieves the clipboard's Unicode text as a UTF-8 string.
Transform, Clipboard, Unicode, %MyUTF_String%  ; Places Unicode text onto the clipboard.

Какая версия AHK?

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

39 (изменено: creature.ws, 2012-03-12 00:03:30)

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

Unicode [, String]: (This command is not available in Unicode builds of AutoHotkey_L.)

OFF: Вот незадача, один вариант переводчика падает на x64, второй — не для Unicode-версии

40

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

Да, mea culpa, плохо проверил.
Вот Unicode-версия, совместить пока не удалось:

global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288

#NoEnv
SetBatchLines, -1

; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return

   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}

Translate(_from="", _to="")
{
   if Clipboard =
       return

   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Clipboard, "[А-Яа-я]")
      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(Clipboard)

   if StrLen(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(Clipboard, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . URIEncode(Found.Value(1))
         Delimiter := Found.Value(3)
         if StrLen(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ Text%A_Index% . "." . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)

   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, 40), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, "UInt", &buffer, "UInt", 10240, "UInt", &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}

JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

На x64 работает?

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

41

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

Faulting application name: AutoHotkey.exe, version: 1.1.7.1, time stamp: 0x4f50adda
Faulting module name: KERNELBASE.dll, version: 6.1.7601.17651, time stamp: 0x4e21213c
Exception code: 0xc000041d

Это что-то труднодиагностируемое раньше имя модуля при ошибке было иным.

42

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

А когда ошибка, при запуске, или после Ctrl+C+C?

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

43 (изменено: Malcev, 2012-03-12 02:47:39)

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

После Ctrl+C+C, если очень много раз нажать CTRL C + C

44

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

Вот такой вариант попробуйте:

global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288

#NoEnv
SetBatchLines, -1

; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return

   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}

Translate(_from="", _to="")
{
   if Clipboard =
       return

   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Clipboard, "[А-Яа-я]")
      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(Clipboard)

   if StrLen(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(Clipboard, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . URIEncode(Found.Value(1))
         Delimiter := Found.Value(3)
         if StrLen(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ Text%A_Index% . "." . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)

   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 40 : 48), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 40)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, Ptr, &buffer, "UInt", 10240, Ptr, &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}

JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

45

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

Обводил слово "TEST"
Не переводит и пишет вот, что

024: pressed1 := 0
001: ColorToolTip := 0xFFFFE1
002: ColorText := 0x002288
005: SetBatchLines,-1
008: OnMessage(0x201, "WM_LBUTTONDOWN") 
009: Return (0.08)
014: MouseGetPos,,,ID
015: WinGetClass,Class,ahk_id %ID%
016: if (Class != "tooltips_class32") 
017: Return (1.44)
014: MouseGetPos,,,ID
015: WinGetClass,Class,ahk_id %ID%
016: if (Class != "tooltips_class32") 
017: Return (1.16)
011: DoublePress() 
025: if pressed1 &&  A_TimeSincePriorHotkey <= 400 
028: pressed1 = 1
029: }
011: Return (0.17)
011: DoublePress() 
025: if pressed1 &&  A_TimeSincePriorHotkey <= 400 
026: pressed1 := 0, Translate() 
033: if Clipboard =
036: INTERNET_MAX_SCHEME_LENGTH := 32
037: INTERNET_MAX_PATH_LENGTH := 2048
038: INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH
040: if (_from = "" && _to = "") 
042: cyr := RegExMatch(Clipboard, "[А-Яа-я]")
043: from := cyr ? "ru" : "auto", to := cyr ? "en" : "ru" 
044: }
048: PreUrl := "http://translate.google.com/translate_a/t?client=x&sl=" . from . "&tl=" . to . "&text="
049: Url := PreUrl . URIEncode(Clipboard)
078: b_Format := A_FormatInteger
079: SetFormat,Integer,Hex
080: Loop,StrPutVar(Str, Var, "UTF-8")
203: VarSetCapacity( var, StrPut(string, encoding) * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) ) 
207: Return,StrPut(string, &var, encoding)
082: Ch := NumGet(Var, A_Index-1, "UChar")
083: if Ch = 0
085: if (Ch>0x7f || Ch<0x30 || Ch=0x3d) 
088: s.=Chr(Ch) 
089: }
082: Ch := NumGet(Var, A_Index-1, "UChar")
083: if Ch = 0
085: if (Ch>0x7f || Ch<0x30 || Ch=0x3d) 
088: s.=Chr(Ch) 
089: }
082: Ch := NumGet(Var, A_Index-1, "UChar")
083: if Ch = 0
085: if (Ch>0x7f || Ch<0x30 || Ch=0x3d) 
088: s.=Chr(Ch) 
089: }
082: Ch := NumGet(Var, A_Index-1, "UChar")
083: if Ch = 0
085: if (Ch>0x7f || Ch<0x30 || Ch=0x3d) 
088: s.=Chr(Ch) 
089: }
082: Ch := NumGet(Var, A_Index-1, "UChar")
083: if Ch = 0
084: Break
090: SetFormat,Integer,b_Format
091: Return,s
051: if StrLen(Url) > INTERNET_MAX_URL_LENGTH 
071: TransText := GetTranslate(Url, from)
096: if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10") 
214: pFix := a_isunicode ? "W" : "A"
215: hModule := DllCall("LoadLibrary", "Str", "wininet.dll")
217: AccessType := Proxy != "" ? 3 : 1
223: io := DllCall("wininet\InternetOpen" . pFix, "Str", UserAgent, "UInt", AccessType, "Str", Proxy, "Str", ProxyBypass, "UInt", 0) (0.02)
230: iou := DllCall("wininet\InternetOpenUrl" . pFix, "UInt", io, "Str", url, "Str", "", "UInt", 0, "UInt", 0x80000000, "UInt", 0) (0.16)
238: if (ErrorLevel != 0 || iou = 0) 
243: VarSetCapacity(buffer, 10240, 0) 
244: VarSetCapacity(BytesRead, 4, 0) 
246: Loop
249: irf := DllCall("wininet\InternetReadFile", "UInt", iou, Ptr, &buffer, "UInt", 10240, Ptr, &BytesRead)
250: VarSetCapacity(buffer, -1) 
252: BytesRead_ = 0
253: Loop,4
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
258: if (irf = 1 &&  BytesRead_ = 0) 
262: a_isunicode ? buffer:=StrGet(&buffer, "CP0") 
263: Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1)) 
264: }
271: }
249: irf := DllCall("wininet\InternetReadFile", "UInt", iou, Ptr, &buffer, "UInt", 10240, Ptr, &BytesRead) (0.01)
250: VarSetCapacity(buffer, -1) 
252: BytesRead_ = 0
253: Loop,4
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
254: BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1)
258: if (irf = 1 &&  BytesRead_ = 0) 
259: Break
273: DllCall("wininet\InternetCloseHandle",  "UInt", iou) 
274: DllCall("wininet\InternetCloseHandle",  "UInt", io) 
275: DllCall("FreeLibrary", "UInt", hModule) 
276: Return,Result
102: from := JSON(JsonTrans, "src")
280: j = %js%
281: Loop,Parse,s,.
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
305: p += StrLen(x)
306: }
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
305: p += StrLen(x)
306: }
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
303: Break
307: }
308: if v <>
318: Return,j == "false" ? 0 : j == "true" ? 1 : j == "null" || j == "nul" ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
104: While,Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
280: j = %js%
281: Loop,Parse,s,.
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
294: StringTrimRight,q3,q3,1
295: Loop,Parse,q3,],[
297: z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)
300: j = %x1%
301: }
302: }
303: Break
307: }
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
303: Break
307: }
308: if v <>
318: Return,j == "false" ? 0 : j == "true" ? 1 : j == "null" || j == "nul" ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
105: TransText .= Sentence 
104: While,Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
280: j = %js%
281: Loop,Parse,s,.
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
294: StringTrimRight,q3,q3,1
295: Loop,Parse,q3,],[
297: z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)
300: j = %x1%
301: }
302: }
303: Break
307: }
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
289: Return
107: if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]")) 
280: j = %js%
281: Loop,Parse,s,.
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
305: p += StrLen(x)
306: }
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
294: StringTrimRight,q3,q3,1
295: Loop,Parse,q3,],[
297: z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)
300: j = %x1%
301: }
302: }
303: Break
307: }
283: p = 2
284: RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q) 
285: Loop
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
305: p += StrLen(x)
306: }
286: if (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|" . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?
290: if (x2 == q2 || q2 == "*") 
291: j = %x3%
292: z += p + StrLen(x2) - 2
293: if (q3 != "" &&  InStr(j, "[") == 1) 
294: StringTrimRight,q3,q3,1
295: Loop,Parse,q3,],[
297: z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)
300: j = %x1%
301: }
302: }
303: Break
307: }
308: if v <>
318: Return,j == "false" ? 0 : j == "true" ? 1 : j == "null" || j == "nul" ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
119: dict ? TransText.= "
+
" dict 
121: StringReplace,TransText,TransText,\r\n,
,All
122: StringReplace,TransText,TransText,\",",All
123: StrPutVar(TransText, Buff) 
203: VarSetCapacity( var, StrPut(string, encoding) * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) ) 
207: Return,StrPut(string, &var, encoding)
124: Return,StrGet(&Buff, "UTF-8")
073: TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText) 
142: TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80 
144: hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8, Str, "tooltips_class32", Str, "", UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0), Int, 0, Int, 0, Int, 0,
149: if (x = "" || y = "") 
151: CoordMode,Mouse
152: MouseGetPos,xtt,ytt
153: xtt := x = "" ? xtt + 10 : x
154: ytt := y = "" ? ytt + 10 : y
155: }
159: NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 40 : 48), TOOLINFO) 
160: NumPut(0x20, TOOLINFO, 4) 
161: NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 40) 
163: DHW := A_DetectHiddenWindows
164: DetectHiddenWindows,On
165: WinWait,ahk_id %hWnd% (0.11)
167: SendMessage,1048,,w
168: SendMessage,1028,,&TOOLINFO
169: SendMessage,1043,RGB_to_BGR(nColorBack)
192: CurrentFormat := A_FormatInteger
193: SetFormat,IntegerFast,H
194: C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
195: BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
196: SetFormat,IntegerFast,%CurrentFormat%
197: Return,BGR
170: SendMessage,1044,RGB_to_BGR(nColorText)
192: CurrentFormat := A_FormatInteger
193: SetFormat,IntegerFast,H
194: C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
195: BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
196: SetFormat,IntegerFast,%CurrentFormat%
197: Return,BGR
171: SendMessage,1056 + (A_IsUnicode ? 1 : 0),h_icon,&sTitle
172: SendMessage,1036 + (A_IsUnicode ? 45 : 0),,&TOOLINFO
173: SendMessage,1042,,xtt|(ytt<<16)
174: SendMessage,1041,1,&TOOLINFO
176: WinGetPos,,,w,H
177: if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight) 
186: DetectHiddenWindows,DHW
187: Return,hWnd
074: }
029: }
011: Return (7.47)

46

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

Это мне ничего не говорит. Тултип появляется, или нет?

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

47

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

Нет

48

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

Такой скрипт срабатывает?
Должен появиться тултип с заголовком вблизи курсора.

#Persistent
TrackToolTip("Тестовый текст", "Заголовок")

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 40 : 48), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 40)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

49

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

На Xp 32 -тултип есть
На Виста 64 - нету

50

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

А так на 64?

#Persistent
TrackToolTip("Тестовый текст", "Заголовок")

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, Ptr, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 60, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 40)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1043, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, 1044, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

51

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

Нет, не показывает.

52

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

А в переменных до выхода из TrackToolTip()

BallonTip[1 of 3]: 0
DHW[3 of 3]: Off
H[2 of 3]: 32
h_icon[1 of 3]: 0
hWnd[7 of 7]: 2032904
nColorBack[8 of 63]: 16777185
nColorText[1 of 3]: 0
sText[14 of 63]: Тестовый текст
sTitle[9 of 63]: Заголовок
TOOLINFO[1 of 30]: <
TTS_ALWAYSTIP[1 of 3]: 1
TTS_BALLOON[4 of 7]: 0x40
TTS_CLOSE[4 of 7]: 0x80
TTS_NOPREFIX[1 of 3]: 2
w[3 of 3]: 126
WS_EX_TOPMOST[1 of 3]: 8
x[0 of 0]:  
xtt[2 of 3]: 43
y[0 of 0]:  
ytt[3 of 3]: 129

53

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

А вот эти переменные я не понимаю куда вписывать.

54

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

Ненужно их вписывать, это лишь для информации, мол, hWnd есть, видимо sendmessage не доходят

55

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

Ну ладно, временно оставим TrackToolTip(). Проверим другое. Следующий код должен дать перевод слова "test" в обычном тултипе. Проверяем на win64.

#Persistent
URL := "http://translate.google.com/translate_a/t?client=x&sl=en&tl=ru&text=test"
ToolTip, % GetTranslate(URL, from)

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0].terms[0]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; " . (!Mod(A_Index, 3) ? "`n" : "")
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, Ptr, &buffer, "UInt", 10240, Ptr, &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}

JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

56

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

Да, ToolTip присутствует, перевод отображается.

57

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

Нашёл ещё ошибку в TrackToolTip(). Проверьте:

#Persistent
TrackToolTip("Тест", "Заголовок")

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 60, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 40)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

58

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

Проверено, ToolTip не отобразился.

59 (изменено: Someone, 2012-03-12 19:43:00)

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

Просто у кого-то с математикой плохо.

http://i.imgur.com/ja6Sm.png

Вот так все отображается и в x86 и в x64:


#Persistent
TrackToolTip("Тест", "Заголовок")
 
TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80
 
   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , Ptr, 0, Ptr, 0, Ptr, 0, Ptr, 0)

   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y
 
   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 72, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 48)
 
   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%
 
   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE
 
   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }
 
   DetectHiddenWindows, % DHW
   Return hWnd
}
 
RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

60

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

Вот и замечательно. Вариант ниже проверен на AHK_L x64 & x86 Unicode.


global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288
 
#NoEnv
SetBatchLines, -1
 
; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return
 
~^vk43:: DoublePress()
 
~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return
 
   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return
 
DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}
 
Translate(_from="", _to="")
{
   if Clipboard =
       return
 
   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH
 
   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Clipboard, "[А-Яа-я]")
      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(Clipboard)
 
   if StrLen(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(Clipboard, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . URIEncode(Found.Value(1))
         Delimiter := Found.Value(3)
         if StrLen(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ Text%A_Index% . "." . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)
 
   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}
 
URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}
 
GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }
 
   from:=JSON(JsonTrans, "src")
 
   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence
 
   if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }
 
   dict ? TransText.= "`n+`n" dict
 
   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}
 
WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
 
 
TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80
 
   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , Ptr, 0, Ptr, 0, Ptr, 0, Ptr, 0)
 
   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y
 
   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 72, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 48)
 
   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%
 
   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE
 
   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }
 
   DetectHiddenWindows, % DHW
   Return hWnd
}
 
RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}
 
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 = "", Proxy = "", ProxyBypass = "") {
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary", "Str", "wininet.dll")
 
    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS
 
    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags
 
    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "UInt", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "UInt", 0) ;dwContext
 
    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "UInt", hModule)
        return 0
    }
 
    VarSetCapacity(buffer, 10240, 0)
    VarSetCapacity(BytesRead, 4, 0)
 
    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", "UInt", iou, Ptr, &buffer, "UInt", 10240, Ptr, &BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length
 
        BytesRead_ = 0 ; reset
        Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
            BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall
 
        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead_ = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))
        }
 
        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }
 
    DllCall("wininet\InternetCloseHandle",  "UInt", iou)
    DllCall("wininet\InternetCloseHandle",  "UInt", io)
    DllCall("FreeLibrary", "UInt", hModule)
   Return Result
}
 
JSON(ByRef js, s, v = "") {
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

61

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

Тогда уже так:


global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288

#NoEnv
SetBatchLines, -1

; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return

   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}

Translate(_from="", _to="")
{
   if Clipboard =
       return

   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Clipboard, "[А-Яа-я]")
      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(Clipboard)

   if StrLen(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(Clipboard, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . URIEncode(Found.Value(1))
         Delimiter := Found.Value(3)
         if StrLen(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ Text%A_Index% . "." . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)

   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0].terms[1]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , Ptr, 0, Ptr, 0, Ptr, 0, Ptr, 0)

   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 72, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 48)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

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 = "", Proxy = "", ProxyBypass = "")
{
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary" . pFix, "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "Ptr", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "Ptr", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "Ptr", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    ;VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", Ptr, iou, Ptr, &buffer, "UInt", 10240, "Int*", BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        ;BytesRead_ = 0 ; reset
        ;Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
        ;    BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle", "Ptr", iou)
    DllCall("wininet\InternetCloseHandle", "Ptr", io)
    DllCall("FreeLibrary", "Ptr", hModule)
    Return Result
}

JSON(ByRef js, s, v = "")
{
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

И вообще запомните: размер указателя в 64-битных процессах - 8 байт, это так же относится ко всем видам хэндлов (HWND, HMODULE, HINTERNET и пр.).

62

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

Запомним, запомним! Я был уверен, что только указатель изменился. Хотя, вот даже справка пишет:

Also note that handles (including types like HWND and HBITMAP) are essentially pointer-types.

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

63

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

Windows Data Types. В типах вида UINT_PTR, "PTR" означает размер. Т.е. UINT размером с PTR, а не указатель на UINT. HFILE и HRESULT —  4-байтные, несмотря на первую букву.

В 64-битных структурах надо ещё учитывать выравнивание. Все члены должны лежать на своей естественной границе. Например, 8-байтные должны начинаться на границе 8 байт, т.е. если первый член DWORD, а второй HANDLE, то первый фактически тоже займёт 8 байт, т.к. второй будет сдвинут на 8-байтную границу. Начало и конец структуры тоже должны будут лежать на 8-байтной границе. Вообще они должны выравниваться на естественную границу самого большого из членов, но, насколько понимаю, тут имеются в виду только базовые типы. Например, формально в TOOLINFO самый большой член — структура RECT, величиной в 16 байт, но TOOLINFO по ней не выравнивается, т.е. она считается просто за 4 DWORD'a. Если конец структуры выравнивается путём добавления байтов, система может использовать эти байты для своих нужд — что-то в них сохранять своё, так что лучше про них не забывать, иначе могут быть переписаны данные, которые идут сразу за структурой. Возможно, выравнивающие байты внутри структуры тоже могут быть так использованы, но об этом я упоминаний не встречал.

В общем, размер 64-битной структуры кратен самому большому члену базового типа.

64

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

YMP, спасибо за разъяснения.

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

65

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

Некоторые исправления, касающиеся перевода больших кусков текста.

global ColorToolTip := 0xFFFFE1
global ColorText := 0x002288

#NoEnv
SetBatchLines, -1

; Menu, Tray, Icon, google.ico
OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

~LButton Up::
   MouseGetPos,,, ID
   WinGetClass, Class, ahk_id %ID%
   if (Class != "tooltips_class32")
      Return

   SendInput, {LButton Up}{LButton Down}{LButton Up}
   Return

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400
      pressed1 := 0, Translate()
   else
      pressed1 = 1
}

Translate(_from="", _to="")
{
   if Clipboard =
       return

   INTERNET_MAX_SCHEME_LENGTH := 32
   INTERNET_MAX_PATH_LENGTH := 2048
   INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + StrLen("://")+ INTERNET_MAX_PATH_LENGTH

   if (_from = "" && _to = "")
   {
      cyr := RegExMatch(Clipboard, "[А-Яа-я]")
      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(Clipboard)

   if StrLen(Url) > INTERNET_MAX_URL_LENGTH
   {
      StartPos := 1
      While RegExMatch(Clipboard, "O)(.*?[\.\?!])(([^\.\?!]*?)[^ \t\n\r]|$)", Found, StartPos)
      {
         StartPos := Found.Pos(1) + Found.Len(1)
         Url := PreUrl . URIEncode(Found.Value(1))
         Delimiter := Found.Value(3), d := SubStr(Delimiter, 1, 1)
         if d not in `n,`r, ,%A_Tab%
            Delimiter := ""
         if StrLen(Url) > INTERNET_MAX_URL_LENGTH
         {
            MsgBox, 20, Ошибка!, % "Предложение """ . Found.Value(1) . """ слишком велико.`nПродолжить?"
            IfMsgBox, Yes
               Continue
            Else
               Break
         }
         TransText .= GetTranslate(Url, from, 0) . Delimiter
      }
   }
   Else
      TransText := GetTranslate(Url, from)

   TrackToolTip(TransText, from ">" to, 0, ColorToolTip, ColorText)
}

URIEncode(Str)
{
   b_Format:=A_FormatInteger
   SetFormat, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      TrackToolTip("Нет ответа от сервера.`nПроверьте соединение с интернетом!", "Ошибка!", 3)
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0]"))
   {
      While JSON(JsonTrans, "dict[" A_Index - 1 "]")
      {
         i := A_Index - 1
         While d := JSON(JsonTrans, "dict[" i "].terms[" A_Index - 1 "]")
            if (d != TransText)
               dict .= d . "; "
      }
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   StrPutVar(TransText, Buff)
   Return StrGet(&Buff, "UTF-8")
}

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

TrackToolTip( sText
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , w = 400)  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_CLOSE|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , Ptr, 0, Ptr, 0, Ptr, 0, Ptr, 0)

   if (x = "" || y = "")
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }
   Else
      xtt := x, ytt := y

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 72, 0), TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 48)

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_to_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_to_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   WinGetPos,,, W, H
   if (xtt + W + 10 > A_ScreenWidth || ytt + H + 10 > A_ScreenHeight)
   {
      WinHide
      xtt := xtt + W + 10 > A_ScreenWidth ? A_ScreenWidth - W - 10 : xtt
      ytt := ytt + H + 10 > A_ScreenHeight ? A_ScreenHeight - H - 10 : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_to_BGR(RGB)
{
   CurrentFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   C := SubStr("0x000000", 1, -(StrLen(RGB+0) - 2)) . SubStr(RGB+0, 3)
   BGR := RegExReplace(C, "0x(..)(..)(..)", "0x$3$2$1")
   SetFormat, IntegerFast, %CurrentFormat%
   Return BGR
}

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 = "", Proxy = "", ProxyBypass = "")
{
    ; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,
    ; Windows Me, Windows 98, or Windows 95.
    ; Requires Internet Explorer 3.0 or later.
    pFix:=a_isunicode ? "W" : "A"
    hModule := DllCall("LoadLibrary" . pFix, "Str", "wininet.dll")

    AccessType := Proxy != "" ? 3 : 1
    ;INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
    ;INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
    ;INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
    ;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

    io := DllCall("wininet\InternetOpen" . pFix
    , "Str", UserAgent ;lpszAgent
    , "UInt", AccessType
    , "Str", Proxy
    , "Str", ProxyBypass
    , "UInt", 0) ;dwFlags

    iou := DllCall("wininet\InternetOpenUrl" . pFix
    , "Ptr", io
    , "Str", url
    , "Str", "" ;lpszHeaders
    , "UInt", 0 ;dwHeadersLength
    , "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
    , "Ptr", 0) ;dwContext

    If (ErrorLevel != 0 or iou = 0) {
        DllCall("FreeLibrary", "Ptr", hModule)
        return 0
    }

    VarSetCapacity(buffer, 10240, 0)
    ;VarSetCapacity(BytesRead, 4, 0)

    Loop
    {
        ;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp
        irf := DllCall("wininet\InternetReadFile", Ptr, iou, Ptr, &buffer, "UInt", 10240, "Int*", BytesRead)
        VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length

        ;BytesRead_ = 0 ; reset
        ;Loop, 4  ; Build the integer by adding up its bytes. (From ExtractInteger-function)
        ;    BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall

        ; To ensure all data is retrieved, an application must continue to call the
        ; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
        If (irf = 1 and BytesRead = 0)
            break
        Else ; append the buffer's contents
        {
            a_isunicode ? buffer:=StrGet(&buffer, "CP0")
            Result .= SubStr(buffer, 1, BytesRead * (a_isunicode ? 2 : 1))
        }

        /* optional: retrieve only a part of the file
        BytesReadTotal += BytesRead_
        If (BytesReadTotal >= 30000) ; only read the first x bytes
        break                      ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)
        */
    }

    DllCall("wininet\InternetCloseHandle", "Ptr", iou)
    DllCall("wininet\InternetCloseHandle", "Ptr", io)
    DllCall("FreeLibrary", "Ptr", hModule)
    Return Result
}

JSON(ByRef js, s, v = "")
{
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

66 (изменено: Крепыш, 2012-09-06 16:44:59)

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

teadrinker пишет:

Некоторые исправления, касающиеся перевода больших кусков текста.

Добрый день!
Подскажите, пожалуйста, как скомпилировать рабочий исполняемый файл?
Скопировал вышеприведённый текст скрипта. Далее беру дистрибутив отсюда: http://www.autohotkey.com/download/AutoHotkey.zip. С помощью Ahk2Exe.exe делаю исполняемый файл. Запускаю его и получаю вот такое сообщение:
http://s1.ipicture.ru/uploads/20120906/OkVeSJQm.png
Что я сделал не так?

67

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

Эта версия autohotkey устарела, и больше не развивается. Скрипт рассчитан на Autohotkey_L by Lexicos, брать тут:  http://l.autohotkey.net/

68 (изменено: Крепыш, 2012-09-06 18:38:09)

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

Спасибо большое!
Так намного лучше. Как сделать, чтобы при открытии нового окна с переводом закрывалось старое?

А вот теперь версия http://forum.script-coding.com/viewtopi … 544#p57544 при двойном нажатии на RCtrl в Windows XP вылетает с ошибкой. Можно в последнюю версию добавить озвучку?

69

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

Подскажите пожалуйста - что где надо изменить чтобы скрипт работал из под прокси?
192.168.206.230:3128
login: mikki
pass: 1

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

70 (изменено: teadrinker, 2012-10-31 13:12:23)

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

Большое спасибо за скрипт, очень полезен.
PS. Было бы не плохо, чтобы текст можно было копировать.

71

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

Планирую выложить новую версию с текстом в поле Edit и с озвучкой. kilzar, у нас принято пользоваться шифтом. Не надо использовать "зы", здесь не вконтактик.

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

72

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

Mikki, вопрос ещё актуален?

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

73 (изменено: teadrinker, 2012-11-11 19:28:47)

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

Новая версия:

#NoEnv
SetBatchLines, -1

if (!A_IsCompiled && FileExist(A_ScriptDir "\Google.ico"))
   Menu, Tray, Icon, %A_ScriptDir%\Google.ico
else
   Menu, Tray, Icon, Shell32.dll, 161

global ColorGui := "Default"
   , INTERNET_MAX_SCHEME_LENGTH := 32, INTERNET_MAX_PATH_LENGTH := 2048
   , INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + INTERNET_MAX_PATH_LENGTH
   , BS_ICON := 0x40, IMAGE_ICON := 1, BM_SETIMAGE := 0xF7, ES_NOHIDESEL := 0x100
   , LangArray := {}, Player, Voice := [], ScriptPID
   , PlaylistOpenNoMedia := 6, Stopped := 1

Process, Exist
ScriptPID := ErrorLevel

InitLangArray()

OnMessage(0x201, "WM_LBUTTONDOWN")
Return

~^vk43:: DoublePress()

#IfWinActive Google Translate ahk_class AutoHotkeyGUI
Esc::WinClose, A

DoublePress()
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400 And Clipboard
      pressed1 := 0, Translate(RegExReplace(Clipboard, "\R", "`r`n"))
   else
      pressed1 := 1
}

Translate(Sourse, _from="", _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) > INTERNET_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) > INTERNET_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)) > INTERNET_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)) > INTERNET_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, 0) . 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, ColorGui, ColorText)
   Else
      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)) > INTERNET_MAX_URL_LENGTH
         TransText .= txt . dlmtr, PrevText := ""

      Else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > INTERNET_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, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0]"))
   {
      Pos := 0
      While Pos := RegExMatch(JsonTrans, """terms"":\[(.*?)]", Found, ++pos)
         dict .= RegExReplace(RegExReplace(Found1, """,""", "; "), """") . "`n`n"
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   Return TransText
}

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 = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   WebRequest.Open("GET", Url)
   WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}

JSON(ByRef js, s, v = "")
{
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

ShowTranslation(SourceText, TransText, from, to, ColorGui=0xDAD6CA, ColorText=0)
{
   static ButtonPos, EditPos, PlayPause1, PlayPause2, Stop1, Stop2, hGui, Control
          , hIcon1, hIcon2, hIcon3, hIcon4, hIcon5, ExtractIcon

   Gui, New, +AlwaysOnTop +LastFound +Resize +hwndhGui +Owner
   Gui, Color, %ColorGui%
   Gui, Font, q5 s8, Verdana
   Gui, Add, Text, x10 y20, Исходный язык:

   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, x112 yp-4 w207 gChangeLang, % SourceLangNames

   TextLen := StrLen(SourceText)
   StrCount := Ceil(TextLen/50) + StrLen(RegExReplace(SourceText, "[^\n]")) + 1
   If StrCount > 20
      StrCount := 20
   Gui, Add, Edit, x10 y+10 w310 Multi r%StrCount% %ES_NOHIDESEL%, % SourceText

   Gui, Add, Button, x10 y+5 w52 h23 %BS_ICON% hwndhButt1 gPlayPause vPlayPause1
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButt2 gStop vStop1" (Player ? "" : " Disabled")
   Gui, Add, Button, x250 yp w70 h23 %BS_ICON% hwndhButt3 gTranslate

   Gui, Add, Text, x10 y+20, Язык перевода:

   Gui, Add, DDL, x112 yp-4 w207 gChangeLang, % TargetLangNames

   TextLen := StrLen(TransText)
   StrCount := Ceil(TextLen/50) + StrLen(RegExReplace(TransText, "[^\n]")) + 1
   If StrCount > 20
      StrCount := 20

   Gui, Add, Edit, x10 y+10 w310 Multi r%StrCount% %ES_NOHIDESEL%, % TransText
   GuiControlGet, Edit2, Pos

   Gui, Add, Button, x10 y+5 w52 h23 %BS_ICON% hwndhButt4 gPlayPause vPlayPause2
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButt5 gStop vStop2" (Player ? "" : " Disabled")
   Gui, Add, Button, x250 yp w70 h23 %BS_ICON% hwndhButt6 gGuiClose
   GuiControlGet, Button6, Pos

   if !ExtractIcon
   {
      hIcon1 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath,  9, 16) : ExtractIcon("Shell32.dll", 218, 16)
      hIcon2 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 10, 16) : ExtractIcon("Shell32.dll", 216, 16)
      hIcon3 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 11, 16) : ExtractIcon("Shell32.dll", 177, 16)
      hIcon4 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 12, 16) : ExtractIcon("Shell32.dll", 132, 16)
      hIcon5 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath
         , 1, 24) : FileExist(A_ScriptDir "\Google.ico") ? ExtractIcon(A_ScriptDir "\Google.ico", 0, 24) : ""
      ExtractIcon := 1
   }

   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon1,, ahk_id %hButt1%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon1,, ahk_id %hButt4%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon2,, ahk_id %hButt2%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon2,, ahk_id %hButt5%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon3,, ahk_id %hButt3%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon4,, ahk_id %hButt6%
   if hIcon5
      DllCall("SendMessage", Ptr, hGui, UInt, WM_SETICON := 0x80, UInt, 0, Ptr, hIcon5)
   Gui, Show, hide, Google Translate

   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, WinExist(), Ptr, &Rect)
   ClientW := NumGet(Rect, 8, "UInt"), ClientH := NumGet(Rect, 12, "UInt")

   EditPos := ClientH - Edit2H
   ButtonPos := ClientH - Button6Y
   
   GuiControl, Focus, Edit1
   Gui, Show, w330 h%ClientH%
   Return

GuiSize:
   SetWinDelay, 0
   p := A_GuiHeight - ButtonPos, q := A_GuiHeight - EditPos
   GuiControl, Move, Edit1, % "w" A_GuiWidth - 20
   GuiControl, Move, Edit2, % "w" A_GuiWidth - 20 " h" (q > 29 ? q : 29)
   GuiControl, Move, Static1, % "x" (A_GuiWidth > 330 ? 10 + (A_GuiWidth - 330)//2 : 10)
   GuiControl, Move, Static2, % "x" (A_GuiWidth > 330 ? 10 + (A_GuiWidth - 330)//2 : 10)
   GuiControl, Move, ComboBox1, % "x" (A_GuiWidth > 330 ? 112 + (A_GuiWidth - 330)//2 : 112)
   GuiControl, Move, ComboBox2, % "x" (A_GuiWidth > 330 ? 112 + (A_GuiWidth - 330)//2 : 112)
   GuiControl, MoveDraw, Button3, % "x" (A_GuiWidth > 200 ? A_GuiWidth - 80 : 120)
   GuiControl, MoveDraw, Button4, % "y" yp := (p > EditPos ?  p : EditPos)
   GuiControl, MoveDraw, Button5, % "y" yp
   GuiControl, MoveDraw, Button6, % "x" (A_GuiWidth > 200 ? A_GuiWidth - 80 : 120) " y" yp
   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:
ChangeLang:
   FontSize := "s8"
   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)

   Loop, parse, TransText
      If Asc(A_LoopField) > 1300
         FontSize := "s11"
   until A_Index = 50 || FontSize = "s11"

   Gui, Font, %FontSize% q5
   GuiControl, Font, Edit2

   GuiControl,, Edit2, % TransText
   Return

GuiClose:
   Gui, %A_Gui%: Destroy
   IfWinNotExist, Google Translate ahk_class AutoHotkeyGUI ahk_pid %ScriptPID%
   {
      Player.close(), Player := "", Voice.Remove(1, Voice.MaxIndex())
      FileDelete, % A_ScriptDir "\mp3\*.mp3"
   }
   return
}

InitLangArray()
{
   Languages =
   (LTrim C
      Азербайджанский|az
      Албанский|sq
      Английский|en
      Арабский|ar
      Армянский|hy
      Африкаанс|af
      Баскский|eu
      Белорусский|be
      Болгарский|bg
      Венгерский|hu
      Вендский|sb
      Вьетнамский|vi
      Голландский|nl
      Греческий|el
      Грузинский|ka
      Датский|da
      Иврит|he
      Идиш|ji
      Индонезийский|in
      Исландский|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)
{
   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_class AutoHotkeyGUI ahk_pid %ScriptPID%
   Loop % List
   {
      Control , % key ? "Enable" : "Disable",, Button2, % "ahk_id" List%A_Index%
      Control , % key ? "Enable" : "Disable",, Button5, % "ahk_id" List%A_Index%
   }
}

По нажатию Ctrl+C+C появляется окно (resizable) с исходным текстом из буфера обмена и с его переводом. По умолчанию, если в исходном тексте присутствует кириллица, переводит с русского на английский, если нет, то язык исходного текста определяется автоматически и переводится на русский. В окне можно сменить языки источника и перевода. В том же окне можно осуществить новый перевод, изменив исходный текст вручную и нажав кнопку http://i.imgur.com/fD3K9.jpg или сменив язык.

Текст в любом из полей Edit можно озвучить, нажав кнопку http://i.imgur.com/lkBH2.jpg. Сначала ищется выделенный текст, при его отсутствии озвучивается весь. После загрузки mp3 файла (или нескольких, если текст большой) активируется кнопка http://i.imgur.com/dfLB2.jpg Stop и начинается озвучивание. Пока активна кнопка Stop, кнопка http://i.imgur.com/lkBH2.jpg работает в режиме Play/Pause. После проигрывания кнопка Stop деактивируется. Озвучка есть не для всех языков. В таком случае кнопка Stop активируется на короткое время и сразу деактивируется без озвучки.

Окно закрывается по Esc или нажатию на крестик.

Ограничение для Windows XP — в контролах Edit отображаются только ANSI-символы, по-крайней мере у меня так.

Буду рад замечаниям и дополнениям.

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

74 (изменено: creature.ws, 2012-11-09 15:22:29)

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

Спасибо.
В последней версии ahk доступны без кавычек юникод-имена полей массива

global LangArray
InitLangArray()

MsgBox % LangArray.Английский  " " LangArray["Китайский (Аомынь)"]

InitLangArray()
{
    LangArray := {
    (Join,
        Азербайджанский: "az"
        Албанский: "sq"
        Английский: "en"
        Арабский: "ar"
        Армянский: "hy"
        Африкаанс: "af"
        Баскский: "eu"
        Белорусский: "be"
        Болгарский: "bg"
        Венгерский: "hu"
        Вендский: "sb"
        Вьетнамский: "vi"
        Голландский: "nl"
        Греческий: "el"
        Грузинский: "ka"
        Датский: "da"
        Иврит: "he"
        Идиш: "ji"
        Индонезийский: "in"
        Исландский: "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"
    )}
}

75

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

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

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

76

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

teadrinker, да, вопрос еще актуален.

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

77

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

UrlDownloadToVar(URL, UserAgent = "", ProxyServer = "", UserName = "", Password = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ProxyServer ? WebRequest.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY := 2, ProxyServer)
   WebRequest.Open("GET", Url)
   UserName != "" ? WebRequest.SetCredentials(UserName, Password, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY := 1)
   UserAgent ? WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

78

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

т.к. ни каких дополнительных примечаний не было озвучено, то я вставил дополнительный кусок текста вместо одноименной функции "как есть".

После Ctrl+C+C некоторое время ни чего не происходило - потом появилось окошко "Нет ответа от сервера. Проверьте соединения с интернетом"

Подумав, вписал между кавычками айпи прокси, логин и пароль. => Результат аналогичен.


Вдогонку вопрос - по какому порту идет соединение?

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

79

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

Mikki пишет:

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

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

Mikki пишет:

Вдогонку вопрос - по какому порту идет соединение?

По всей видимости, по тому, который указан в IP-адресе в конце после двоеточия.

Mikki пишет:

192.168.206.230:3128
login: mikki
pass: 1

С этим адресом у меня соединения не происходит даже через браузер.

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

80 (изменено: sna, 2013-01-26 21:09:15)

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

Классный скрипт. Спасибо автору. Поставил себе на компутер и получаю большое удовольствие от того, что не нужно постоянно лазить в Гугл за переводом. Со знанием ин. языков у меня сущий ад. Поработал со скриптом и пришел к ряду небольших усовершенствований. Возможно, они придутся ко двору, потому привожу измененный скрипт  и комментирую здесь. Я здесь новичок и потому не знаю, этично ли поступать так. Так что извините, если что...

Основные мотивы:
1. Шрифт мелковат, увеличил до 10 пунктов, потому немного изменил расчет количества строк в окошечке просмотра перевода.
2. Лично меня больше интересует перевод. Вдруг, еще кого-то. Потому, макс. количество строк в окнах просмотра исходного текста и перевода вынес в глобальные переменные, устанавливаются в начале скрипта. Для себя выставил по максимуму количество строк в окне полученного перевода. Каждый может подстроить эти параметры исходя из размеров монитора по вертикали.
3. То, что окно с переводом появляется всегда в центре, - не совсем удобно. Теперь допустима настройка позиции окна на рабочем столе. Более того, при перемещении окна, позиция запоминается и потом очередные окошки выпадают в новом месте
4. При выводе очередного окна перевода, предыдущее удаляется.
5. И последнее... после вывода окна с переводом, фокус возвращается окну с исходным текстом.

Привожу текст полученного скрипта...

+ открыть спойлер
;Дополнительные опции
global    xPosGUI, yPosGUI        ;Положение окна Google Traslate
global    CurrentGUIId            ;Id последнего сформированного окна Google Traslate
global    RememberGUIPosition     ;Запоминать положение окна Google Traslate
global    OnlyOneGUI              ;Только одно окно Google Traslate
global    ParentWinId             ;Id активного окна, из которого вызываем перевод
global    FocusTheParent          ;Получив перевод, возвращаемся в окно с ParentWinId
global  MaxStrCountInSourceText ;Макс. количество строк в окошечке исходного текста
global  MaxStrCountInTransText  ;Макс. количество строк в окошечке перевода
RememberGUIPosition=%true%
OnlyOneGUI=%true%
FocusTheParent=%true%
xPosGUI=x0
yPosGUI=
MaxStrCountInSourceText=5
MaxStrCountInTransText=55
;~ При выставленных (ниже) параметрах, скрипт работает в первозданном виде.
;~ RememberGUIPosition=%false%
;~ OnlyOneGUI=%false%
;~ FocusTheParent=%false%
;~ xPosGUI=
;~ yPosGUI=
;~ MaxStrCountInSourceText=20
;~ MaxStrCountInTransText=20

#NoEnv
SetBatchLines, -1

if !A_IsCompiled
   Menu, Tray, Icon, Shell32.dll, 161
else
{
   Menu, Tray, NoStandard
   Menu, Tray, Add, Exit, Exit
}

global ColorGui := "Default"
   , INTERNET_MAX_SCHEME_LENGTH := 32, INTERNET_MAX_PATH_LENGTH := 2048
   , INTERNET_MAX_URL_LENGTH := INTERNET_MAX_SCHEME_LENGTH + INTERNET_MAX_PATH_LENGTH
   , BS_ICON := 0x40, IMAGE_ICON := 1, BM_SETIMAGE := 0xF7, ES_NOHIDESEL := 0x100, WM_SETICON := 0x80
   , LangArray := {}, Player, Voice := [], ScriptPID
   , PlaylistOpenNoMedia := 6, Stopped := 1

Process, Exist
ScriptPID := ErrorLevel

InitLangArray()

OnMessage(0x201, "WM_LBUTTONDOWN")
Return
   
Exit:
   ExitApp

~^vk43:: DoublePress()

#If WinActive("Google Translate ahk_pid" ScriptPID)
Esc::WinClose, A

DoublePress()
{
    
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 400 And Clipboard
   {
      WinGet, ParentWinId, Id, A
      pressed1 := 0, Translate(RegExReplace(Clipboard, "\R", "`r`n"))
      if FocusTheParent
         WinActivate, ahk_id %ParentWinId%
      
   }
   else
      pressed1 := 1
}

Translate(Sourse, _from="", _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) > INTERNET_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) > INTERNET_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)) > INTERNET_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)) > INTERNET_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, 0) . 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, ColorGui, ColorText)
   Else
      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)) > INTERNET_MAX_URL_LENGTH
         TransText .= txt . dlmtr, PrevText := ""

      Else If StrLen(PreUrl . URIEncode(PrevText . txt . dlmtr)) > INTERNET_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, Integer, Hex
   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, Integer, % b_Format
   Return, s
}

GetTranslate(Url, byref from, ReadDict = 1)
{
   if !JsonTrans := UrlDownloadToVar(Url, "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10")
   {
      MsgBox, 16, Ошибка!, Нет ответа от сервера.`nПроверьте соединение с интернетом!
      Return
   }

   from:=JSON(JsonTrans, "src")

   While Sentence := JSON(JsonTrans, "sentences[" A_Index - 1 "].trans")
      TransText .= Sentence

   if (ReadDict && JSON(JsonTrans, "dict[0]"))
   {
      Pos := 0
      While Pos := RegExMatch(JsonTrans, """terms"":\[(.*?)]", Found, ++pos)
         dict .= RegExReplace(RegExReplace(Found1, """,""", "; "), """") . "`n`n"
      StringTrimRight, dict, dict, 2
   }

   dict ? TransText.= "`n+`n" dict

   StringReplace, TransText, TransText, \r\n,`r`n, All
   StringReplace, TransText, TransText, \", ", All
   Return TransText
}

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 = "")
{
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   WebRequest.Open("GET", Url)
   WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
   WebRequest.Send()
   Text := WebRequest.ResponseText
   WebRequest := ""
   return Text
}

JSON(ByRef js, s, v = "")
{
   j = %js%
   Loop, Parse, s, .
   {
      p = 2
      RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
      Loop {
         If (!p := RegExMatch(j
            , "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
            . "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
            Return
         Else If (x2 == q2 or q2 == "*") {
            j = %x3%
            z += p + StrLen(x2) - 2
            If (q3 != "" and InStr(j, "[") == 1) {
               StringTrimRight, q3, q3, 1
               Loop, Parse, q3, ], [
               {
                  z += 1 + RegExMatch(SubStr(j, 2, -1)
                     , "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){"
                     . SubStr(A_LoopField, 1) + 1 . "}", x)
                  j = %x1%
               }
            }
            Break
         }
         Else p += StrLen(x)
      }
   }
   If v !=
   {
      vs = "
      If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
         and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
         vs := "", v := vx1
      StringReplace, v, v, ", \", All
      js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1)
         . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
   }
   Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
      ? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}

ShowTranslation(SourceText, TransText, from, to, ColorGui=0xDAD6CA, ColorText=0)
{
   static ButtonPos, EditPos, PlayPause1, PlayPause2, Stop1, Stop2, hGui, Control
          , hIcon1, hIcon2, hIcon3, hIcon4, hIcon5, ExtractIcon


   if OnlyOneGUI
   {
      Loop
      {
         IfWinNotExist, ahk_id %CurrentGUIId%
             Break
         else
             IfWinExist, ahk_id %CurrentGUIId%
                 WinKill, ahk_id %CurrentGUIId%
      }
   }


   Gui, New, +AlwaysOnTop +LastFound +Resize +hwndhGui +Owner
   Gui, Color, %ColorGui%
   ;~ Gui, Font, q5 s8, Verdana
   Gui, Font, q5 s10, Verdana
   Gui, Add, Text, x10 y20, Исходный язык:

   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, x112 yp-4 w207 gChangeLang, % SourceLangNames

   TextLen := StrLen(SourceText)
   StrCount := Ceil(TextLen/50) + StrLen(RegExReplace(SourceText, "[^\n]")) + 1
   If (StrCount > MaxStrCountInSourceText)
      StrCount := MaxStrCountInSourceText
   
   Gui, Add, Edit, x10 y+10 w310 Multi r%StrCount% %ES_NOHIDESEL%, % SourceText

   Gui, Add, Button, x10 y+5 w52 h23 %BS_ICON% hwndhButt1 gPlayPause vPlayPause1
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButt2 gStop vStop1" (Player ? "" : " Disabled")
   Gui, Add, Button, x250 yp w70 h23 %BS_ICON% hwndhButt3 gTranslate

   Gui, Add, Text, x10 y+20, Язык перевода:

   Gui, Add, DDL, x112 yp-4 w207 gChangeLang, % TargetLangNames

   TextLen := StrLen(TransText)
   ;~ StrCount := Ceil(TextLen/50) + StrLen(RegExReplace(TransText, "[^\n]")) + 1       ;расчет для шрифта s8 (базовый вариант)
   StrCount := Ceil(TextLen/(50/10*8)) + Ceil(1.5*StrLen(RegExReplace(TransText, "[^\n]"))) + 2   ;расчет для шрифта s10
   If (StrCount > MaxStrCountInTransText)
      StrCount := MaxStrCountInTransText

   Gui, Add, Edit, x10 y+10 w310 Multi r%StrCount% %ES_NOHIDESEL%, % TransText
   GuiControlGet, Edit2, Pos

   Gui, Add, Button, x10 y+5 w52 h23 %BS_ICON% hwndhButt4 gPlayPause vPlayPause2
   Gui, Add, Button, % "x+3 yp w52 h23 " BS_ICON " hwndhButt5 gStop vStop2" (Player ? "" : " Disabled")
   Gui, Add, Button, x250 yp w70 h23 %BS_ICON% hwndhButt6 gGuiClose
   GuiControlGet, Button6, Pos

   if !ExtractIcon
   {
      hIcon1 := ExtractIcon("Shell32.dll", 218, 16)
      hIcon2 := ExtractIcon("Shell32.dll", 216, 16)
      hIcon3 := ExtractIcon("Shell32.dll", 177, 16)
      hIcon4 := ExtractIcon("Shell32.dll", 132, 16)
      hIcon5 := A_IsCompiled ? ExtractIcon(A_ScriptFullPath, 1, 24) : ""
      ExtractIcon := 1
   }

   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon1,, ahk_id %hButt1%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon1,, ahk_id %hButt4%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon2,, ahk_id %hButt2%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon2,, ahk_id %hButt5%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon3,, ahk_id %hButt3%
   SendMessage, BM_SETIMAGE, IMAGE_ICON, hIcon4,, ahk_id %hButt6%
   if hIcon5
      DllCall("SendMessage", Ptr, hGui, UInt, WM_SETICON, UInt, 0, Ptr, hIcon5)
   Gui, Show, %xPosGUI% %yPosGUI% hide, Google Translate

   VarSetCapacity(Rect, 16)
   DllCall("GetClientRect", Ptr, WinExist(), Ptr, &Rect)
   ClientW := NumGet(Rect, 8, "UInt"), ClientH := NumGet(Rect, 12, "UInt")

   EditPos := ClientH - Edit2H
   ButtonPos := ClientH - Button6Y
   GuiControl, Focus, Edit1
   Gui, Show, w330 h%ClientH%
   Sleep, 200
   WinGet, CurrentGUIId, Id
 Return

GuiSize:
   SetWinDelay, 0
   p := A_GuiHeight - ButtonPos, q := A_GuiHeight - EditPos
   GuiControl, Move, Edit1, % "w" A_GuiWidth - 20
   GuiControl, Move, Edit2, % "w" A_GuiWidth - 20 " h" (q > 29 ? q : 29)
   GuiControl, Move, Static1, % "x" (A_GuiWidth > 330 ? 10 + (A_GuiWidth - 330)//2 : 10)
   GuiControl, Move, Static2, % "x" (A_GuiWidth > 330 ? 10 + (A_GuiWidth - 330)//2 : 10)
   GuiControl, Move, ComboBox1, % "x" (A_GuiWidth > 330 ? 112 + (A_GuiWidth - 330)//2 : 112)
   GuiControl, Move, ComboBox2, % "x" (A_GuiWidth > 330 ? 112 + (A_GuiWidth - 330)//2 : 112)
   GuiControl, MoveDraw, Button3, % "x" (A_GuiWidth > 200 ? A_GuiWidth - 80 : 120)
   GuiControl, MoveDraw, Button4, % "y" yp := (p > EditPos ?  p : EditPos)
   GuiControl, MoveDraw, Button5, % "y" yp
   GuiControl, MoveDraw, Button6, % "x" (A_GuiWidth > 200 ? A_GuiWidth - 80 : 120) " y" yp
   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:
ChangeLang:
   FontSize := "s8"
   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)

   Loop, parse, TransText
      If Asc(A_LoopField) > 1300
         FontSize := "s11"
   until A_Index = 50 || FontSize = "s11"

   Gui, Font, %FontSize% q5
   GuiControl, Font, Edit2

   GuiControl,, Edit2, % TransText
   Return

GuiClose:
   if RememberGUIPosition
   {
      WinGetPos, XWin, YWin
      xPosGUI=x%XWin%
      yPosGUI=y%YWin%
   }
   
   Gui, %A_Gui%: Destroy
   IfWinNotExist, Google Translate ahk_pid %ScriptPID%
   {
      Player.close(), Player := "", Voice.Remove(1, Voice.MaxIndex())
      FileDelete, % A_ScriptDir "\mp3\*.mp3"
   }
   return
}

InitLangArray()
{
   Languages =
   (LTrim C
      Азербайджанский|az
      Албанский|sq
      Английский|en
      Арабский|ar
      Армянский|hy
      Африкаанс|af
      Баскский|eu
      Белорусский|be
      Болгарский|bg
      Венгерский|hu
      Вендский|sb
      Вьетнамский|vi
      Голландский|nl
      Греческий|el
      Грузинский|ka
      Датский|da
      Иврит|he
      Идиш|ji
      Индонезийский|in
      Исландский|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)
{
   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",, Button2, % "ahk_id" List%A_Index%
      Control , % key ? "Enable" : "Disable",, Button5, % "ahk_id" List%A_Index%
   }
}

Отравляет жизнь только то, что не удалось настроить этот скрипт на работу через прокси. Может быть, кому-то еще удастся...
Спасибо.

81

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

Спасибо за отзыв! Я уже тоже модернизировал скрипт, большая часть из того, о чём ты говоришь, учтена, и ещё добавлено многое другое. Попозже выложу.

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

82

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

Не плохо было бы настройку для буфера обмена включить в новую версию скрипта. Варианты:

  • Cкрипт не меняет содержимое Clipboard

  • В Clipboard после перевода исходный текст

  • В Clipboard после перевода переведенный текст

83

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

ОК, добавлю.

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

84

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

Вдогонку, по буферу обмена, уж коли teadrinker любезно согласился учесть пожелание в новой версии скрипта. Как вариант: указать только опцию, запрещающую изменять содержимое буфера обмена при работе скрипта. Но, если его содержимое скрипту менять разрешено, то таки оставить в буфере обмена исходный текст. По нажатию Ctrl+V его оттуда можно будет извлечь в требуемое место; а, например, по Shift+Ctrl+V, добавленному в скрипт, вставлять в требуемое место полученный текст перевода. Наверное, вариант с двойным нажатием Ctrl+V, как более красивый, не прокатит для вставки переведенного текста...

85

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

sna пишет:

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

На данный момент скрипт и так не меняет содержание буфера обмена. Если перевод осуществляется нажатием Ctrl+C+C, то там находится исходный текст независимо от работы скрипта.

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

86

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

Новый вариант. Добавлено:

  • Настройки скрипта через трей-меню.

  • Открытие пустого окна по двойному клику по иконке в трее для ввода текста вручную.

  • Скрипт запоминает положение окна на экране, если разрешено много окон, запоминает положение первого появившегося.

  • «Интеллектуальный» ресайзинг окна: тянем за верх — изменяется размер верхнего поля Edit, за низ — нижнего.

  • Возможность запомнить и сохранить постоянный размер окна и полей Edit, независимо от размера текста.

  • Возможность менять размер шрифта в полях Edit по отдельности. Для этого кликаем по нужному полю, нажимаем Ctrl и вращаем колесо мыши (так же, как это делается в браузерах).

  • Автоматическое переключение раскладки при фокусе на верхнем поле Edit в зависимости от языка-источника. Также переключение раскладки на русскую при фокусе на DropDownList для выбора языка с клавиатуры по первой букве.

  • Теперь при смене языка автоматического перевода не происходит, нужно нажать на кнопку "Перевод" или "Enter" на клавиатуре.

  • Смена местами языков источника и перевода по кнопке.

  • Вставка последнего перевода по горячей клавише Ctrl + Alt + V.

  • Иконки изменены на "несистемные", папка с ними в аттаче, однако скрипт может загрузить их и самостоятельно. Для скомпилированного скрипта (также в аттаче, 32-bit) иконки отдельно не нужны, они добавлены в исполняемый файл в качестве ресурсов.

#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
   }

   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 : ""))
}

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
}

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
}

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
}

GetEditFocus()
{
   if !WinActive("Google Translate ahk_pid" ScriptPID)
      return
   
   ControlGetFocus, Control, A
   return InStr(Control, "Edit") ? SubStr(Control, 0) : ""
}

http://i.imgur.com/QuMllzh.jpg
На всякий случай ещё раз описание работы скрипта.

По нажатию Ctrl+C+C и/или Ctrl+Ins+Ins (по выбору через трей-меню) появляется окно (resizable) с исходным текстом из буфера обмена и с его переводом. По умолчанию, если в исходном тексте присутствует кириллица, переводит с русского на английский, если нет, то язык исходного текста определяется автоматически и переводится на русский. В окне можно сменить языки источника и перевода. В том же окне можно осуществить новый перевод, изменив исходный текст вручную и нажав кнопку "Перевод" или "Enter" на клавиатуре.

Текст в любом из полей Edit можно озвучить, нажав кнопку "Play-Pause". Сначала ищется выделенный текст, при его отсутствии озвучивается весь. После загрузки mp3 файла (или нескольких, если текст большой) активируется кнопка "Stop" и начинается озвучивание. После проигрывания кнопка Stop деактивируется. Озвучка есть не для всех языков. В таком случае кнопка Stop активируется на короткое время и сразу деактивируется без озвучки.

Окно закрывается по Esc (если активно) или по нажатию на кнопку OK.

Post's attachments

GoogleTranslator.zip 392.83 kb, 27 downloads since 2013-02-02 

You don't have the permssions to download the attachments of this post.
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

87

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

Mikki пишет:

"Докладаю, таксссать, из-за прокси, гражданин модератор".


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

Огромное спасибо за программу.

added: Единственное "но" - после моей компиляции скрипта он не отображает Ваши иконки на кнопках. Показывает какието свои. Но папка есть.

Mikki, в Коллекции комментировать не нужно.
Информация в скрипте, откуда берутся иконки, с 485 строки.

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

88

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

Извините!...Поиском нашел тему и отписался

...думал доделать окошко с вводом прокси и пароля, а потом подумал, и ограничился записью этих данных в ини файл... И пытаюсь сделать, чтобы по двойному клику на иконке в трее окно "пряталось/показывалось". Но, пока что, получается "уничтожается/создается". Вот с этим я пока еще не разобрался.

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

89

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

Mikki пишет:

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

global WM_LBUTTONDBLCLK := 0x203

Menu, Tray, NoStandard
Menu, Tray, Add, Exit, Exit

Gui, Show, w300 h200, Google Translate
OnMessage(0x404, "AHK_NOTIFYICON")
return

Exit:
   ExitApp

AHK_NOTIFYICON(wp, lp)
{
   if (lp = WM_LBUTTONDBLCLK)
   {
      if WinExist("Google Translate")
         WinHide
      else
         WinShow, Google Translate
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

90 (изменено: creature.ws, 2013-04-11 18:08:48)

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

Незначительное уточнение:

global WM_LBUTTONDBLCLK := 0x203
global hwndGui

Menu, Tray, NoStandard
Menu, Tray, Add, Exit, Exit

Gui +hwndhwndGui
Gui, Show, w300 h200, Google Translate
OnMessage(0x404, "AHK_NOTIFYICON")
return

Exit:
   ExitApp

AHK_NOTIFYICON(wp, lp)
{
   if (lp = WM_LBUTTONDBLCLK)
   {
      if WinExist("ahk_id" hwndGui)
         WinHide
      else
         WinShow ahk_id %hwndGui%
   }
}

Всё-таки окно «родное», незачем искать по заголовку.

91

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

Ох тыж!!!....(это возглас восхищения)

...А, можно заменить обработку двойного клика на обработку одинарного клика?

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

92

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

Можно.

global WM_LBUTTONDOWN := 0x201, hGui

Gui, +hwndhGui
Gui, Show, w300 h200, Google Translate
OnMessage(0x404, "AHK_NOTIFYICON")
return

AHK_NOTIFYICON(wp, lp)
{
   if (lp = WM_LBUTTONDOWN)
      Gui, %hGui%: Show, % WinExist("ahk_id" hGui) ? "Hide" : ""
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

93 (изменено: serzh82saratov, 2013-04-11 22:48:23)

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

Классный скрипт! Много раз проходил мимо, а тут оказалось очень полезная и удобная штука.
teadrinker как всегда на высоте. "Заморочки" с ресайзом окна и иконками на кнопках чего только стоят. Вообщем в коллекцию ежедневно полезных скриптов
-----

Mikki пишет:

А, можно заменить обработку двойного клика на обработку одинарного клика?


+ Ещё можно так:

Menu, Tray, Add, Показать или Скрыть, ShowHide
Menu, Tray, Default, Показать или Скрыть
Menu, Tray, Click, 1 

Gui, +hwndhGui 
Gui, Show, w300 h200, Google Translate 
return

ShowHide: 
    Gui, % WinExist("ahk_id" hGui) ? "Hide" : "Show"     
    return

Когда одиночный "срывается" на двойной клик, не очень выходит, когда есть дефолтный пункт.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

94 (изменено: Mikki, 2013-04-12 11:16:25)

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

Проблема в том, что в скрипте teadrinker-а окно везде уничтожается, а не скрывается. Т.е. не сохраняется результат перевода.

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

95

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

Было бы замечательно в новой версии скрипта увидеть голосовой ввод=).
А еще лучше, что бы работал даже в фоновом режиме. Нажал кнопку, сказал что хочешь, оно перевело и по нажатию Ctrl + Alt + V вставляет наш последний перевод.

96

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

Может кто поможет в реализации, времени нету вообще, что бы самому это сделать.
Нужно немного переделать переводчик. Что бы по нажатию горячих клавиш, копировал выделенный текст в буфер обмена, переводил и снова копировал в буфер обмена, но уже переведенный текст.
Сам перевод должен происходить в фоновом режиме.
Давно столкнулся с трудностями общения с нашими забугорными товарищами. Моего знания английского не достаточно, что бы они меня полноценно понимали.
А времени на переключения из окна игры чаще всего нет.
Так что такой вот переводчик поможет всем игроманам преодолеть языковой барьер.

97

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

В общем попытался поправить последнюю выложенную версию кода teadrinker.
То что я возможно криво правил код меня переубедила попытка запуска исходника...
Вот такая вот ошибка вылазит
http://i47.fastpic.ru/big/2013/0518/75/1cd167d1c887949e90d65c449d9a4d75.jpg

98

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

DaVinchi пишет:

То что я возможно криво правил код меня переубедила попытка запуска исходника...

В смысле, мой код выдаёт ошибку?

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

99

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

teadrinker пишет:

В смысле, мой код выдаёт ошибку?

Да. Причем исходник который лежит в архиве с рабочим переводчиков и тот, что в этой теме выше в теге "код"... Думал мб где то опечатка и опробовал оба варианта.

100

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

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

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