26

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

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

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

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg

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
Skype dmitry_fiveg