AutoHotkey Community

It is currently May 27th, 2012, 11:29 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: September 14th, 2009, 10:30 am 
Offline

Joined: November 20th, 2008, 6:00 pm
Posts: 72
Location: Thionville, France
Hi.

Here is a standalone function which displays a balloon tooltip at the caret position.
I posted it in another topic but improved it.
Code:
/*
Use:
BalloonTip(sTitle = "", sText = "", hlicon=0, TitleCodePage = "", TextCodePage = "", Clickable=1, Timeout = 10000, MinTimeDisp = 200, RefreshRate = 100)
- sTitle: Title of the tooltip. Leave it empty for no title.
- sText: Text of the tooltip. Cannot be empty.
- hlicon: Icon displayed left to the title (0: None, 1:Info, 2: Warning, 3: Error, >3: assumed to be an hIcon.)
- TitleCodePage: Code page used for the title (empty: ascii, U8: UTF8, U16: UTF16) Note that if U16 is to be used, you must use the address of the variable containing the title for sTitle instead of the variable itself (by means of &Var instead of Var).
- TextCodePage: Same as TitleCodePage, for the text.
- Clickable: Determines the balloontip behavior when clicked (0: clicks are forwarded through the balloontip, 1: the balloontip disappears when clicked (flickers the active win), 2: the balloontip gets focused on click, 3: Same as 1, plus the balloontip displays a close button,  4: the balloontip gets focused on click and has a working close button). Note that on 98 and previous, the close button won't show and the balloontip may not show properly when using 0.
- Timeout: Delay before the balloontip disappears (in ms).
- MinTimeDisp: Delay during which the balloontip cannot disappear, except when control focus changes or active window loses focus. After this delay, moving the window or the caret will destroy the balloontip.
- RefreshRate: Delay between two checks of caret position, active win and focused control.
Entering no parameters at all (or simply an empty string as sText parameter) hides the balloontip unconditionally.
*/

BalloonTip(sTitle = "", sText = "", hlicon=0, TitleCodePage = "", TextCodePage = "", Clickable=1, Timeout = 10000, MinTimeDisp = 200, RefreshRate = 100)
{
   Static hwnd, ActiveWinID, ActiveCtrl, CtrlContent, CaretX, CaretY, MinTime, ClickableSave
   If !sText
      Goto _DestroyBalloonTip
   ActiveWinID := WinExist("A")
   SetTimer, _DestroyBalloonTip, Off
   Gosub _DestroyBalloonTip
   ClickableSave := Clickable
   ControlGetFocus, ActiveCtrl, Ahk_ID %ActiveWinID%
   If !ActiveCtrl
      Return
   MinTime = 1
   ControlGetText, CtrlContent, %ActiveCtrl%, Ahk_ID %ActiveWinID%
   coordmode, caret, screen
   CaretX := A_CaretX
   CaretY := A_CaretY
   hwnd := DllCall("CreateWindowEx", "Uint", (Clickable ? 0x80088 : 0x80028), "str", "tooltips_class32", "str", "", "Uint", (Clickable>2 ? 0xC3 : 0x42), "int", 0, "int", 0, "int", 0, "int", 0, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0)
   VarSetCapacity(ti, 40, 0)
   ti := Chr(40)
   DllCall("ntdll\RtlFillMemoryUlong", "Uint", &ti + 4, "Uint", 4, "Uint", 0x20)   ; TTF_TRACK
   If !TitleCodePage
   {
      If (StrLen(sTitle)>99)
         sTitle := SubStr(sTitle, 1, 98) "…"
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1056, "Uint", hlicon, "Uint", &sTitle)   ; TTM_SETTITLE   ; 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   }
   Else If (TitleCodePage = "U8")
   {
      ;Retrieve size of the title in unicode
      nSize := DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &sTitle, "int",  -1, "Uint", 0, "int",  0)
      VarSetCapacity(sU16, nSize * 2)
      DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &sTitle, "int",  -1, "Uint", &sU16, "int",  nSize)
      ;Cut the string at the proper size by writing an end char in memory.
      If (nSize>100) ;100=string+end char
         NumPut(0x2026, &sU16+196, "UInt") ;2026 is "…" .UInt is 32bits. The remaining bits will be filled with 0, creating the end char.
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1057, "Uint", hlicon, "Uint", &sU16)
   }
   Else If (TitleCodePage = "U16")
   {
      ;The variable sTitle contains the address of the U16-formatted title
      ;Cut the string if too long
      Loop
      {
         If (A_Index>100)
         {
            NumPut(0x2026, sTitle+196, "UInt") ;2026 is "…" .UInt is 32bits. The remaining bits will be filled with 0, creating the end char.
            Break
         }
         If !NumGet(sTitle+0, 2*(A_Index-1), "UShort")
            Break
      }
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1057, "Uint", hlicon, "Uint", sTitle)
   }
   If !TextCodePage
      DllCall("ntdll\RtlFillMemoryUlong", "Uint", &ti +36, "Uint", 4, "Uint", &sText)
   Else If (TextCodePage = "U8")
   {
      ;Retrieve size of the text in unicode
      nSize := DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &sText, "int",  -1, "Uint", 0, "int",  0)
      VarSetCapacity(sU16, nSize * 2)
      ;Converts U8 to unicode
      DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &sText, "int",  -1, "Uint", &sU16, "int",  nSize)
      DllCall("ntdll\RtlFillMemoryUlong", "Uint", &ti +36, "Uint", 4, "Uint", &sU16)
   }
   Else If (TextCodePage = "U16")
      DllCall("ntdll\RtlFillMemoryUlong", "Uint", &ti +36, "Uint", 4, "Uint", sText)
   DllCall("SendMessage", "Uint", hWnd, "Uint", 1028, "Uint", 0, "Uint", &ti)   ; TTM_ADDTOOL
   WinGetPos, WinX, WinY, , , Ahk_ID %ActiveWinID%
   ControlGetPos, CtrlX, CtrlY, CtrlW, CtrlH, %ActiveCtrl%, Ahk_ID %ActiveWinID%
   ; TTM_TRACKPOSITION
   If ((CaretY < CtrlY+WinY) || (CaretY > CtrlY+CtrlH-11+WinY) || (CaretX < CtrlX+WinX) || (CaretX > CtrlX+CtrlW-4+WinX))
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1042, "Uint", 0, "Uint", (CtrlX+4+WinX & 0xFFFF)|(CtrlY+CtrlH-9+WinY & 0xFFFF)<<16)
   Else
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1042, "Uint", 0, "Uint", (CaretX+4 & 0xFFFF)|(CaretY+11 & 0xFFFF)<<16)
   DllCall("SendMessage", "Uint", hWnd, "Uint", 1048, "Uint", 0, "Uint", A_ScreenWidth)   ; TTM_SETMAXTIPWIDTH (allows A_Tab to be displayed)
   If !TextCodePage
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1036, "Uint", 0, "Uint", &ti)   ; TTM_UPDATETIPTEXT
   Else
      DllCall("SendMessage", "Uint", hWnd, "Uint", 1081, "Uint", 0, "Uint", &ti)   ; TTM_UPDATETIPTEXTW
   DllCall("SendMessage", "Uint", hWnd, "Uint", 1041, "Uint", 1, "Uint", &ti)   ; TTM_TRACKACTIVATE
   ;WinShow, Ahk_ID %hwnd%
   SetTimer, _UpdateBalloonTip, %RefreshRate%
   If MinTimeDisp
      SetTimer, _MinTimeDisp, -%MinTimeDisp%
   If Timeout
      SetTimer, _DestroyBalloonTip, -%Timeout%
   Return
   _MinTimeDisp:
   MinTime =
   Return
   _UpdateBalloonTip:
   F := WinExist("A")
   If (F = ActiveWinID)
   {
      ControlGetFocus, F, Ahk_ID %ActiveWinID%
      If (F = ActiveCtrl)
      {
         ControlGetText, F, %F%, Ahk_ID %ActiveWinID%
         coordmode, caret, screen
         If ((A_CaretX = CaretX) && (A_CaretY = CaretY) && (CtrlContent = F))
            Return
         Else If MinTime
         {
            CaretX := A_CaretX
            CaretY := A_CaretY
            CtrlContent := F
            WinGetPos, WinX, WinY, , , Ahk_ID %ActiveWinID%
            ControlGetPos, CtrlX, CtrlY, CtrlW, CtrlH, %ActiveCtrl%, Ahk_ID %ActiveWinID%
            If ((CaretY < CtrlY+WinY) || (CaretY > CtrlY+CtrlH-11+WinY) || (CaretX < CtrlX+WinX) || (CaretX > CtrlX+CtrlW-4+WinX))
               DllCall("SendMessage", "Uint", hWnd, "Uint", 1042, "Uint", 0, "Uint", (CtrlX+4+WinX & 0xFFFF)|(CtrlY+CtrlH-9+WinY & 0xFFFF)<<16)
            Else
               DllCall("SendMessage", "Uint", hWnd, "Uint", 1042, "Uint", 0, "Uint", (CaretX+4 & 0xFFFF)|(CaretY+11 & 0xFFFF)<<16)
            Return
         }
      }
   }
   Else If ((F = hwnd) && InStr("2|4", ClickableSave))
      Return
   _DestroyBalloonTip:
   SetTimer, _UpdateBalloonTip, Off
   SetTimer, _MinTimeDisp, Off
   SetWinDelay, -1
   DllCall("SendMessage", "Uint", hWnd, "Uint", 0x10, "Uint", 0)
   hwnd =
   Return
}

Example:
- Press F1 to display ASCII tooltip.
- Copy some (unicode) text into clipboard and press F2 and/or F3.
- Press F4 to destroy the balloontips.
Code:
#SingleInstance, Force

F1::
BalloonTip()
sleep 200 ;Waits for the previous tooltip to disappear and the previous window to retrieve focus, if Clickable is >0
i++
BalloonTip("Tooltip n°" i, "A" A_Tab "few`n" A_Space A_Space "words.", 1)
KeyWait F1
return

F2::
Transform, U8Str, Unicode ;Retrieves the UTF8-formatted clipboard content.
BalloonTip()
sleep 200
i++
BalloonTip(U8Str, U8Str, 1, "U8", "U8")
KeyWait F2
return

F3::
Transform, U8Str, Unicode ;Retrieves the UTF8-formatted clipboard content.
;Transforms it into unicode
nSize := DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &U8Str, "int",  -1, "Uint", 0, "int",  0)
VarSetCapacity(sU16Title, nSize * 2)
DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &U8Str, "int",  -1, "Uint", &sU16Title, "int",  nSize)
VarSetCapacity(sU16Text, nSize * 2)
DllCall("MultiByteToWideChar", "Uint", 65001, "Uint", 0, "Uint", &U8Str, "int",  -1, "Uint", &sU16Text, "int",  nSize)
BalloonTip()
sleep 200
i++
BalloonTip(&sU16Title, &sU16Text, 1, "U16", "U16")
KeyWait F3
return

F4::
BalloonTip()
KeyWait F4
Return

Feedback and suggestions are welcome.
Enjoy.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot], Google Feedfetcher, MSN [Bot], nomissenrojb and 68 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group