;: Title: TT.ahk Object based ToolTip Library by HotKeyIt ; ; Function: TT() - Object based ToolTip Library by HotKeyIt ; Description: ; TT is based on AHK_L Objects and supports both, ANSI and UNICODE version, so to use it you will require Lexikos AutoHotkey_L.exe or other versions based on it that supports objects.

TT is used to work with ToolTip controls. You can create standalone ToolTips but also ToolTips for Controls of your GUI. ; Syntax: TTObj:=TT(Options,Text,Title) ; Parameters: ; TTObj - ToolTip Object to control ToolTip using its functions and ToolTip messages. ; Options - Description (If Options is a digit or hexadecimal number TT will assume this is the parent window) ; Options requiring a value - All these options need to be followed by = and a value. For example Parent=99 ; GUI/PARENT - Parent HWND or Gui Id (Parent can be 1-99 as well). When no Parent or GUI ID is given, GUI +LastFound will be used, when you do not want to have a parent use PARENT=0 (OnShow,OnClick,OnClose is only possible if PARENT is an AutoHotkey window) ; AUTOPOP / INITIAL / RESHOW - Option for Control ToolTips.
AUTOPOP - How long to remain visible.
INITIAL - Delay showing.
RESHOW - Delay showing between tools.
For reference see TTM_SETDELAYTIME Message. ; MAXWIDTH - Maximum tooltip window width, or -1 to allow any width.
For reference see TTM_SETMAXTIPWIDTH Message. ; ICON - 0=none 1=info 2=warning 3=error (> 3 = hIcon). (!!! Use "" to show the image as icon from a jpg, bmp and other image files.
For reference see TTM_SETTITLE Message.
Since the Icon is in the title, it will appear only if there is a title. ; Color - RGB color for ToolTip text color.
For reference see TTM_SETTIPTEXTCOLOR Message. ; BackGround - RGB ToolTip background color.
For reference see TTM_SETTIPBKCOLOR Message. ; OnClose/OnClick - A function to be launched when a ToolTip was closed or a link was clicked. ParseLinks option will be set automatically.

Links are created using Text.
Your OnClick function can accept up to two parameters ToolTip_Message(action[,Tool]).
When action is not specified Text will be used.
Tool is your ToolTip object that you can access inside your function.
OnClose uses same parameters but first passed parameter will be empty. ; Options not requiring a value - HWND CENTER RTL SUB TRACK ABSOLUTE TRANSPARENT PARSELINKS - For reference see TOOLINFO Structure
- CloseButton for your ToolTip
- ClickTrough will enable clicking trough ToolTip
- Balloon ToolTip
- Style uses themed hyperlinks.
- NoFade disables fading in.
- NoAnimate disables sliding on Win2000.
- NoPrefix Prevents the system from stripping ampersand characters from a string or terminating a string at a tab character.
- AlwaysTip - Indicates that the tooltip control appears even if the tooltip control's owner window is inactive. ; ToolTip functions - All function beside Add, Del, Show, Color, Remove and Text are ToolTip messages, for reference see ToolTip Messages.
To call them use for example TTObj.TRACKACTIVATE(x,y)
; ToolTip.Add() - ToolTip.Add(Control[,text,uFlags/options,parent])
- Control can be text like Button1 or hwnd of control.
- Text to be displayed.
- uFlags/options can be a value or list of strings HWND CENTER RTL SUB TRACK ABSOLUTE TRANSPARENT PARSELINKS.
- Parent can be a parent window, default is set in TT function, see above.
To enable ToolTip for Static controls like Text and Picture add 0x100 to Controls options. ; ToolTip.Remove() - Removes a ToolTip object and all control associations. Call TT_Remove() to remove all ToolTips (will be called automatically when scripts exits). ; ToolTip.Del() - ToolTip.Del(Control)
Delete a ToolTip associated with a control only, other ToolTips will remain. ; ToolTip.Show() - ToolTip.Show([Text,x,y,title,icon,iconIdx])
Show a ToolTip. x and y can be TrayIcon to show ToolTip at TrayIcon coordinates of your app. ; ToolTip.Hide() - Hides a ToolTip. Same as ToolTip.TrackPosition(0).
Note NoFade only disables fade in, to have no fade out use ToolTip.Text("")! ; ToolTip.Color() - ToolTip.Color(textcolor,backgroundcolor)
Used to set both colors and string colors like White,Black,Yellow,Red,Blue.... You can also use wrapped message straight away: TTObj.SETTIPBKCOLOR(RGBValue) and ToolTip.SETTIPTEXTCOLOR(RGBValue) ; ToolTip.Font() - ToolTip.Font(Font)
Change Font of ToolTip. Example ToolTip.Font("S20 bold italic striceout underline, Arial") ; ToolTip.Text() - ToolTip.Text(text)
Update text for main ToolTip (created when TT() is called). ; ToolTip.Title() - ToolTip.Title([title,icon,iconIdx])
Update title and icon for ToolTip. Icon can be 0 - 3 or a hIcon or a file path and iconIdx if it is an exe,dll or cur file.
IconIdx must be an empty string ("") if you want to load an icon from jpg, png, bmp, gif or other supported files by gdi as well as from HEX string.
Otherwise associated icon for given file type will be loaded. ; ToolTip.Icon() - ToolTip.Icon([icon,iconIdx])
Update only icon for ToolTip. Icon can be a file path, see title function. TT_GetIcon can be used to get a hIcon. "" for iconIdx will load the image as icon from jpg, bmp ... file.
Since the Icon is in the title, it will appear only if there is a title. ; Return Value: ; TT returns a ToolTip object that can be used to perform all action on a ToolTip. ; Remarks: ; When no Parent is given when calling TT(), Gui +LastFound will be used, when first parameter of TT(0x283475) is digit or xdigit, it will be used as parent.
Options TRACK and NOPREFIX are forced by default, to disable use TRACK=0 NOPREFIX=0. ; Related: ; Example: ; file:TT_Example.ahk ; ;~ #Include TT_Init(){ ;initialize structures function global _TOOLINFO:="cbSize,uFlags,PTR hwnd,PTR uId,_RECT rect,PTR hinst,LPTSTR lpszText,PTR lParam,void *lpReserved" ,_RECT:="left,top,right,bottom" ,_NMTVGETINFOTIP:="HWND hwndFrom,UINT_PTR idFrom,UINT code,UINT uFlags,UInt link" ,_CURSORINFO:="cbSize,flags,HCURSOR hCursor,x,y" ,_ICONINFO:="fIcon,xHotspot,yHotSpot,HBITMAP hbmMask,HBITMAP hbmColor" ,_BITMAP:="LONG bmType,LONG bmWidth,LONG bmHeight,LONG bmWidthBytes,WORD bmPlanes,WORD bmBitsPixel,LPVOID bmBits" ,_SHFILEINFO:="HICON hIcon,iIcon,DWORD dwAttributes,TCHAR szDisplayName[260],TCHAR szTypeName[80]" ,_TBBUTTON:="iBitmap,idCommand,BYTE fsState,BYTE fsStyle,BYTE bReserved[" (A_PtrSize=8?6:2) "],DWORD_PTR dwData,INT_PTR iString" ,_RECT:="left,top,right,bottom" } TT(options="",text="",title=""){ global _RECT,_TOOLINFO static temp:=TT_Init() ; Options ;WS_POPUP=0x80000000,TTS_ALWAYSTIP=0x1,TTS_NOPREFIX=0x2,TTS_USEVISUALSTYLE=0x100,TTS_NOFADE=0x20,TTS_NOANIMATE=0x10 static HWND_TOPMOST:=-1,SWP_NOMOVE=0x2, SWP_NOSIZE=0x1, SWP_NOACTIVATE=0x10 ; Objects static @:={},base:={Color:"TT_Color",Show:"TT_Show",Hide:"TTM_Trackactivate",Close:"TT_Close",Add:"TT_Add",AddTool:"TTM_AddTool" ,Del:"TT_Del",Title:"TTM_SetTitle",Text:"TT_Text",ACTIVATE:"TTM_ACTIVATE",Set:"TT_Set" ,ADDTOOL:"TTM_ADDTOOL",Remove:"TT_Remove",Icon:"TT_Icon",Font:"TT_Font",ADJUSTRECT:"TTM_ADJUSTRECT" ,DELTOOL:"TTM_DELTOOL",ENUMTOOLS:"TTM_ENUMTOOLS",GETBUBBLESIZE:"TTM_GETBUBBLESIZE" ,GETCURRENTTOOL:"TTM_GETCURRENTTOOL",GETDELAYTIME:"TTM_GETDELAYTIME",GETMARGIN:"TTM_GETMARGIN" ,GETMAXTIPWIDTH:"TTM_GETMAXTIPWIDTH",GETTEXT:"TTM_GETTEXT",GETTIPBKCOLOR:"TTM_GETTIPBKCOLOR" ,GETTIPTEXTCOLOR:"TTM_GETTIPTEXTCOLOR",GETTITLE:"TTM_GETTITLE",GETTOOLCOUNT:"TTM_GETTOOLCOUNT" ,GETTOOLINFO:"TTM_GETTOOLINFO",HITTEST:"TTM_HITTEST",NEWTOOLRECT:"TTM_NEWTOOLRECT",POP:"TTM_POP" ,POPUP:"TTM_POPUP",RELAYEVENT:"TTM_RELAYEVENT",SETDELAYTIME:"TTM_SETDELAYTIME",SETMARGIN:"TTM_SETMARGIN" ,SETMAXTIPWIDTH:"TTM_SETMAXTIPWIDTH",SETTIPBKCOLOR:"TTM_SETTIPBKCOLOR",SETTIPTEXTCOLOR:"TTM_SETTIPTEXTCOLOR" ,SETTITLE:"TTM_SETTITLE",SETTOOLINFO:"TTM_SETTOOLINFO",SETWINDOWTHEME:"TTM_SETWINDOWTHEME" ,TRACKACTIVATE:"TTM_TRACKACTIVATE",TRACKPOSITION:"TTM_TRACKPOSITION",UPDATE:"TTM_UPDATE" ,UPDATETIPTEXT:"TTM_UPDATETIPTEXT",WINDOWFROMPOINT:"TTM_WINDOWFROMPOINT" ,__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity" ,_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey" ,_Clone:"_Clone",Insert:"Insert",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity" ,GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone" ,"base":{__Call:"TT_Set",__Delete:"TT_Delete"}} Parent:="",Gui:="",ClickTrough:="",Style:="",NOFADE:="",NoAnimate:="",NOPREFIX:="",AlwaysTip:="",ParseLinks:="",CloseButton:="",Balloon:="",maxwidth:="" ,INITIAL:="",AUTOPOP:="",RESHOW:="",OnClick:="",OnClose:="",OnShow:="",ClickHide:="",HWND:="",Center:="",RTL:="",SUB:="",Track:="",Absolute:="" ,TRANSPARENT:="",Color:="",Background:="",icon:="" If (options=-0x8000000000000000) Return @ else if options is xdigit Parent:=options else If (options){ Loop,Parse,options,%A_Space%,%A_Space% If istext { If (SubStr(A_LoopField,0)="'") %istext%:=string A_Space SubStr(A_LoopField,1,StrLen(A_LoopField)-1),istext:="",string:="" else string.= A_Space A_LoopField } else If A_LoopField contains AUTOPOP,INITIAL,PARENT,RESHOW,MAXWIDTH,ICON,Color,BackGround,OnClose,OnClick,OnShow,GUI,NOPREFIX,TRACK { RegExMatch(A_LoopField,"^(\w+)=?(.*)?$",option) If ((Asc(option2)=39 && SubStr(A_LoopField,0)!="'") && (istext:=option1) && (string:=SubStr(option2,2))) Continue %option1%:=option2 } else if A_LoopField %A_LoopField% := 1 } If (Parent && Parent<100 && !DllCall("IsWindow","PTR",Parent)){ Gui,%Parent%:+LastFound Parent:=WinExist() } else if (GUI){ Gui, %GUI%:+LastFound Parent:=WinExist() } else if (Parent=""){ Parent:=A_ScriptHwnd } T:=Object("base",base) T.HWND := DllCall("CreateWindowEx", "UInt", (ClickTrough?0x20:0)|0x8, "str", "tooltips_class32", "PTR", 0 , "UInt",0x80000000|(Style?0x100:0)|(NOFADE?0x20:0)|(NoAnimate?0x10:0)|((NOPREFIX+1)?(NOPREFIX?0x2:0x2):0x2)|(AlwaysTip?0x1:0)|(ParseLinks?0x1000:0)|(CloseButton?0x80:0)|(Balloon?0x40:0) , "int",0x80000000,"int",0x80000000,"int",0x80000000,"int",0x80000000, "PTR",Parent?Parent:0,"PTR",0,"PTR",0,"PTR",0,"PTR") DllCall("SetWindowPos","PTR",T.HWND,"PTR",HWND_TOPMOST,"Int",0,"Int",0,"Int",0,"Int",0 ,"UInt",SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE) @.Insert(T) T.SETMAXTIPWIDTH(MAXWIDTH?MAXWIDTH:A_ScreenWidth) If !(AUTOPOP INITIAL RESHOW) T.SETDELAYTIME() else T.SETDELAYTIME(AUTOPOP?AUTOPOP*1000:-1),T.SETDELAYTIME(INITIAL?INITIAL*1000:-1),T.SETDELAYTIME(RESHOW?RESHOW*1000:-1) T.fulltext:=text,T.maintext:=RegExReplace(text,"",">") If ((T.OnClick:=OnClick)||(T.OnClose:=OnClose)||(T.OnShow:=OnShow)),T.OnClose:=OnClose,T.OnShow:=OnShow,T.ClickHide:=ClickHide OnMessage(0x4e,"TT_OnMessage") If OnClick ParseLinks:=1 T.rc:=Struct(_RECT) ;for TTM_SetMargin ;Tool for Main ToolTip T.P:=Struct(_TOOLINFO),P:=T.P,P.cbSize:=sizeof(_TOOLINFO) P.uFlags:=(HWND?0x1:0)|(Center?0x2:0)|(RTL?0x4:0)|(SUB?0x10:0)|(Track+1?(Track?0x20:0):0x20)|(Absolute?0x80:0)|(TRANSPARENT?0x100:0)|(ParseLinks?0x1000:0) P.hwnd:=Parent,P.uId:=Parent,P.lpszText[""]:=T.GetAddress("maintext")?T.GetAddress("maintext"):"",T.AddTool(P[]) If Color T.SETTIPTEXTCOLOR(Color) If Background T.SETTIPBKCOLOR(BackGround) T.SetTitle(T.maintitle:=title,icon) ; Sleep,100 Return T } TT_Delete(t=""){ ;delete all ToolTips (will be executed OnExit) TT_Remove(),TT_GetIcon() ;delete ToolTips and Destroy all icon handles } TT_Remove(T=""){ static @:=TT(-0x8000000000000000) ;Get main object that holds all ToolTips If !T Loop % @.MaxIndex() { T:=@[A_Index] @.Remove(A_Index) for id,tool in T.T T.DelTool(tool[]) T.DelTool(T.P[]) DllCall("DestroyWindow","PTR",T.HWND) } else for id,Tool in @ { If (T=Tool){ @[id]:=@[@.MaxIndex()],@.Remove(id) for id,tools in Tool.T Tool.DelTool(tools[]) Tool.DelTool(Tool.P[]) DllCall("DestroyWindow","PTR",Tool.HWND) break } } } TT_OnMessage(wParam,lParam,msg,hwnd){ global _NMTVGETINFOTIP static TTN_FIRST:=0xfffffdf8, @:=TT(-0x8000000000000000) ;Get main object that holds all ToolTips ,HDR:=Struct(_NMTVGETINFOTIP) HDR[]:=lParam If !InStr(".1.2.3.","." (m:= TTN_FIRST-HDR.code) ".") Return p:=HDR.hwndFrom for id,T in @ { If (p=T.hwnd) break } text:=T.fulltext If (m=1){ ;Show If IsFunc(T.OnShow) T.OnShow(T) } else If (m=2){ ;Close If IsFunc(T.OnClose) T.OnClose(T) T.TRACKACTIVATE(0,T.P[]) } else If InStr(text,"") action:=SubStr(text,InStr(text,">")+1,InStr(text,"")-InStr(text,">")-1) else action:=Trim(action:=SubStr(text,1,InStr(text,">")-1)) If IsFunc(T.OnClick) T.OnClick(T,action) } Return true } TT_ADD(T,Control,Text="",uFlags="",Parent=""){ ; uFlags http://msdn.microsoft.com/en-us/library/bb760256.aspx ; TTF_ABSOLUTE=0x80, TTF_CENTERTIP=0x0002, TTF_IDISHWND=0x1, TTF_PARSELINKS=0x1000 ,TTF_RTLREADING = 0x4 ; TTF_SUBCLASS=0x10, TTF_TRAMsgCK=0x20, TTF_TRANSPARENT=0x100 global _TOOLINFO DetectHiddenWindows:=A_DetectHiddenWindows DetectHiddenWindows,On if (Parent){ If (Parent && Parent<100 and !DllCall("IsWindow","PTR",Parent)){ Gui %Parent%:+LastFound Parent:=WinExist() } T["T",Abs(Parent)]:=Struct(_TOOLINFO),Tool:=T["T",Abs(Parent)] Tool.uId:=Parent,Tool.hwnd:=Parent,Tool.uFlags:=(0|16) DllCall("GetClientRect","PTR",T.HWND,"PTR", T[Abs(Parent)].rect[]) T.ADDTOOL(T["T",Abs(Parent)][]) } If text= ControlGetText,text,%Control%,% "ahk_id " (Parent?Parent:T.P.hwnd) If Control is not Xdigit If Control is not digit ControlGet,Control,Hwnd,,%Control%,% "ahk_id " (Parent?Parent:T.P.hwnd) If uFlags If uFlags is not digit { Loop,Parse,uflags,%A_Space%,%A_Space% If A_LoopField %A_LoopField% := 1 uFlags:=(HWND?0x1:HWND=""?0x1:0)|(Center?0x2:0)|(RTL?0x4:0)|(SUB?0x10:0)|(Track?0x20:0)|(Absolute?0x80:0)|(TRANSPARENT?0x100:0)|(ParseLinks?0x1000:0) } T["T",Abs(Control)]:=Tool:=Struct(_TOOLINFO) Tool.cbSize:=sizeof(_TOOLINFO) T[Abs(Control),"text"]:=RegExReplace(text,"",">") Tool.uId:=Control,Tool.hwnd:=Parent?Parent:T.P.hwnd,Tool.uFlags:=uFlags?(uFlags|16):(1|16) Tool.lpszText[""]:=T[Abs(Control)].GetAddress("text") DllCall("GetClientRect","PTR",T.HWND,"PTR",Tool.rect[]) T.ADDTOOL(Tool[]) DetectHiddenWindows,%DetectHiddenWindows% } TT_DEL(T,Control){ If !Control Return 0 If Control is not Xdigit If Control is not digit ControlGet,Control,Hwnd,,%Control%,% "ahk_id " t.P.hwnd T.DELTOOL(T.T[Abs(Control)][]),T.T.Remove(Abs(Control)) } TT_Color(T,Color="",Background=""){ static TTM_SETTIPBKCOLOR=0x413,TTM_SETTIPTEXTCOLOR=0x414 ,Black=0x000000,Green=0x008000,Silver=0xC0C0C0,Lime=0x00FF00,Gray=0x808080,Olive=0x808000 ,White=0xFFFFFF,Yellow=0xFFFF00,Maroon=0x800000,Navy=0x000080,Red=0xFF0000,Blue=0x0000FF ,Purple=0x800080,Teal=0x008080,Fuchsia=0xFF00FF,Aqua=0x00FFFF If (Color!="") T.SETTIPTEXTCOLOR(Color) If (BackGround!="") T.SETTIPBKCOLOR(BackGround) } TT_Text(T,text){ static TTM_UPDATETIPTEXT=0x400+(A_IsUnicode?57:12),TTM_UPDATE=0x400+29 T.fulltext:=text,T.maintext:=RegExReplace(text,"",">"),T.P.lpszText[""]:=text?T.GetAddress("maintext"):0 T.UPDATETIPTEXT() } TT_Icon(T,icon=0,icon#=1){ static TTM_SETTITLE = 0x400 + (A_IsUnicode ? 33 : 32) If icon If icon is not digit icon:=TT_GetIcon(icon,icon#) Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_SETTITLE,"PTR",icon,"PTR",T.GetAddress("maintitle"),"PTR"),T.UPDATE() } TT_GetIcon(File="",Icon#=1){ global _ICONINFO,_SHFILEINFO static hIcon:=Object(),AW:=A_IsUnicode?"W":"A",sfi:="",pToken:=0 ,temp1:=DllCall( "LoadLibrary", "Str","gdiplus","PTR"),temp2:=VarSetCapacity(si, 16, 0) (si := Chr(1)) If !sfi { sfi:=Struct(_SHFILEINFO),sfi_size:=sizeof(_SHFILEINFO) SysGet, SmallIconSize, 49 DllCall("gdiplus\GdiplusStartup", "PTR*",pToken, "PTR",&si, "PTR",0) } If !File { for file,obj in hIcon If IsObject(obj){ for icon,handle in obj DllCall("DestroyIcon","PTR",handle) } else DllCall("DestroyIcon","PTR",handle) DllCall("gdiplus\GdiplusShutdown", "PTR",pToken),sfi:="" Return } If (SubStr(file,-3)=".lnk") { FileGetShortcut,%File%,Fileto,,,,FileIcon,FileIcon# File :=FileIcon ?FileIcon :Fileto Icon#:=FileIcon#?FileIcon#:Icon# } If hIcon[File,Icon#] Return hIcon[file,Icon#] else if (hIcon[File] && !IsObject(hIcon[File])) return hIcon[File] SplitPath, File,,, Ext if (hIcon[Ext] && !IsObject(hIcon[Ext])) return hIcon[Ext] If (ext="cur") { Return hIcon[file,Icon#]:=DllCall("LoadImage", "PTR", 0, "str", File, "uint", ext="cur"?2:1, "int", 0, "int", 0, "uint", 0x10,"PTR") } else if InStr(",EXE,ICO,DLL,LNK,","," Ext ",") { DllCall("PrivateExtractIcons", "Str", File, "Int", Icon#-1, "Int", SmallIconSize, "Int", SmallIconSize, "PTR*", Icon, "PTR*", 0, "UInt", 1, "UInt", 0, "Int") Return hIcon[File,Icon#]:=Icon } else if (Icon#=""){ If !FileExist(File){ if File is xdigit ;assume Hex string { nSize := StrLen(File)//2 VarSetCapacity( Buffer,nSize ) Loop % nSize NumPut( "0x" . SubStr(File,2*A_Index-1,2), Buffer, A_Index-1, "Char" ) } else Return } else { FileGetSize,nSize,%file% FileRead,Buffer,*c %file% } hData := DllCall("GlobalAlloc", "UInt",2, "UInt", nSize,"PTR") ,pData := DllCall("GlobalLock", "PTR",hData,"PTR") ,DllCall( "RtlMoveMemory", "PTR",pData, "PTR",&Buffer, "UInt",nSize ) ,DllCall( "GlobalUnlock", "PTR",hData ) ,DllCall( "ole32\CreateStreamOnHGlobal", "PTR",hData, "Int",True, "PTR*",pStream ) ,DllCall( "gdiplus\GdipCreateBitmapFromStream", "UInt",pStream, "PTR*",pBitmap ) ,DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", "PTR",pBitmap, "PTR*",hBitmap, "UInt",0 ) ,DllCall( "gdiplus\GdipDisposeImage", "PTR",pBitmap ) ,ii:=Struct(_ICONINFO) ,ii.ficon:=1,ii.hbmMask:=hBitmap,ii.hbmColor:=hBitmap return hIcon[File]:=DllCall("CreateIconIndirect","PTR",ii[],"PTR") } else If DllCall("Shell32\SHGetFileInfo" AW, "str", File, "uint", 0, "PTR", sfi[], "uint", sfi_size, "uint", 0x101,"PTR") Return hIcon[Ext] := sfi.hIcon } TT_Close(T){ T.text("") } TT_Show(T,text="",x="",y="",title="",icon="",icon#=1){ global _TBBUTTON,_BITMAP,_ICONINFO,_CURSORINFO,_RECT static pcursor:= Struct(_CURSORINFO),init:=(pcursor.cbSize:=sizeof(_CURSORINFO)) ,picon:=Struct(_ICONINFO) ,pbitmap:=Struct(_BITMAP) ,TB:=Struct(_TBBUTTON) ,RC:=Struct(_RECT) xo:="",xs:="",yo:="",ys:="" If Text!= T.Text(text) If (title!="") T.SETTITLE(title,icon,icon#) If (x="TrayIcon" || y="TrayIcon"){ DetectHiddenWindows,% (DetectHiddenWindows:=A_DetectHiddenWindows ? "On" : "On") Process, Exist PID:=ErrorLevel hWndTray:=WinExist("ahk_class Shell_TrayWnd") ControlGet,hWndToolBar,Hwnd,,ToolbarWindow321,ahk_id %hWndTray% WinGet, procpid, PID,ahk_id %hWndToolBar% DataH := DllCall( "OpenProcess", "uint", 0x38, "int", 0, "uint", procpid,"PTR") ;0x38 = PROCESS_VM_OPERATION+READ+WRITE bufAdr := DllCall( "VirtualAllocEx", "PTR", DataH, "PTR", 0, "uint", sizeof(TB), "uint", MEM_COMMIT:=0x1000, "uint", PAGE_READWRITE:=0x4,"PTR") max:=DllCall("SendMessage","PTR",hWndToolBar,"UInt",0x418,"PTR",0,"PTR",0,"PTR") Loop % max { i:=max-A_Index DllCall("SendMessage","PTR",hWndToolBar,"UInt",0x417,"PTR",i,"PTR",bufAdr,"PTR") DllCall("ReadProcessMemory", "PTR", DataH, "PTR", bufAdr, "PTR", TB[""], "ptr", sizeof(TB), "ptr", 0) DllCall("ReadProcessMemory", "PTR", DataH, "PTR", TB.dwData, "PTR", RC[""], "PTR", 8, "PTR", 0) WinGet,BWPID,PID,% "ahk_id " NumGet(RC[""],0,"PTR") If (BWPID!=PID) continue If (TB.fsState>7){ ControlGetPos,xc,yc,xw,yw,Button2,ahk_id %hWndTray% xc+=xw/2, yc+=yw/4 } else { DllCall("SendMessage","PTR",hWndToolBar,"UInt",0x41d,"PTR",i,"PTR",bufAdr,"PTR") DllCall( "ReadProcessMemory", "PTR", DataH, "PTR", bufAdr, "PTR", RC[""], "PTR", sizeof(RC), "PTR", 0 ) ControlGetPos,xc,yc,,,ToolbarWindow321,ahk_id %hWndTray% halfsize:=RC.bottom/2 xc+=RC.left + halfsize yc+=RC.top + (halfsize/1.5) } WinGetPos,xw,yw,,,ahk_id %hWndTray% xc+=xw,yc+=yw break } If (!xc && !yc){ If A_OsVersion in Win_7,WIN_VISTA ControlGetPos,xc,yc,xw,yw,Button1,ahk_id %hWndTray% else ControlGetPos,xc,yc,xw,yw,Button2,ahk_id %hWndTray% xc+=xw/2, yc+=yw/4 WinGetPos,xw,yw,,,ahk_id %hWndTray% xc+=xw,yc+=yw } DllCall( "VirtualFreeEx", "PTR", DataH, "PTR", bufAdr, "PTR", 0, "uint", MEM_RELEASE:=0x8000) DllCall( "CloseHandle", "PTR", DataH ) DetectHiddenWindows % DetectHiddenWindows If x=TrayIcon x:=xc If y=TrayIcon y:=yc } If (x ""="" || y ""=""){ pCursor.cbSize:=sizeof(pCursor) DllCall("GetCursorInfo", "ptr", pCursor[""]) DllCall("GetIconInfo", "ptr", pCursor.hCursor, "ptr", pIcon[""]) If picon.hbmColor DllCall("DeleteObject", "ptr", pIcon.hbmColor) DllCall("GetObject", "ptr", pIcon.hbmMask, "uint", sizeof(_BITMAP), "ptr", pBitmap[""]) hbmo := DllCall("SelectObject", "ptr", cdc:=DllCall("CreateCompatibleDC", "ptr", sdc:=DllCall("GetDC","ptr"),"ptr"), "ptr", pIcon.hbmMask) w:=pBitmap.bmWidth,h:=pBitmap.bmHeight, h:= h=w*2 ? (h//2,c:=0xffffff,s:=32) : (h,c:=s:=0) Loop % w { xi := A_Index - 1 Loop % h { yi := A_Index - 1 + s if (DllCall("GetPixel", "ptr", cdc, "uint", xi, "uint", yi) = c) { if (xo < xi) xo := xi if (xs = "" || xs > xi) xs := xi if (yo < yi) yo := yi if (ys = "" || ys > yi) ys := yi } } } DllCall("ReleaseDC", "ptr", 0, "ptr", sdc) DllCall("DeleteDC", "ptr", cdc) DllCall("DeleteObject", "ptr", hbmo) DllCall("DeleteObject", "ptr", picon.hbmMask) If (y ""=""){ SysGet,yl,77 SysGet,yr,79 y:=pCursor.y-pIcon.yHotspot+ys+(yo-ys)-s+1 If y not between %yl% and %yr% y:=y yr - 20) y := yr - 20 } If (x ""=""){ SysGet,xr,78 SysGet,xl,76 x:=pCursor.x-pIcon.xHotspot+xs+(xo-xs)+1 If x not between %xl% and %xr% x:=x>8)&255)<<8)+(Color>>16) ; rgb -> bgr Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_SETTIPBKCOLOR,"PTR",color,"PTR",0,"PTR") } TTM_SETTIPTEXTCOLOR(T,color=0){ static TTM_SETTIPTEXTCOLOR = 0x414 ,Black:=0x000000, Green:=0x008000, Silver:=0xC0C0C0, Lime:=0x00FF00 ,Gray:=0x808080, Olive:=0x808000, White:=0xFFFFFF, Yellow:=0xFFFF00 ,Maroon:=0x800000, Navy:=0x000080, Red:=0xFF0000, Blue:=0x0000FF ,Purple:=0x800080, Teal:=0x008080, Fuchsia:=0xFF00FF, Aqua:=0x00FFFF If color is alpha If (%color%) Color:=%color% Color := (StrLen(Color) < 8 ? "0x" : "") . Color Color := ((Color&255)<<16)+(((Color>>8)&255)<<8)+(Color>>16) ; rgb -> bgr Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_SETTIPTEXTCOLOR,"PTR",color,"PTR",0,"PTR") } TTM_SETTITLE(T,title="",icon="",Icon#=1){ static TTM_SETTITLE = 0x400 + (A_IsUnicode ? 33 : 32) If icon If icon is not digit icon:=TT_GetIcon(icon,Icon#) T.maintitle := (StrLen(title) < 96) ? title : (Chr(A_IsUnicode ? 8230 : 133) SubStr(title, -97)) If Icon!= lastIcon:=Icon Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_SETTITLE,"PTR",icon,"PTR",T.GetAddress("maintitle"),"PTR"),T.UPDATE(),lastIcon:=Icon } TTM_SETTOOLINFO(T,pTOOLINFO=0){ static TTM_SETTOOLINFO = A_IsUnicode?0x436:0x409 Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_SETTOOLINFO,"PTR",0,"PTR",pTOOLINFO?pTOOLINFO:T.P[""],"PTR") } TTM_SETWINDOWTHEME(T,theme=""){ Return DllCall("SendMessage","PTR",T.HWND,"UInt",0x200b,"PTR",0,"PTR",&theme,"PTR") } TTM_TRACKACTIVATE(T,activate=0,pTOOLINFO=0){ Return DllCall("SendMessage","PTR",T.HWND,"UInt",0x411,"PTR",activate,"PTR",(pTOOLINFO)?(pTOOLINFO):(T.P[""]),"PTR") } TTM_TRACKPOSITION(T,x=0,y=0){ Return DllCall("SendMessage","PTR",T.HWND,"UInt",0x412,"PTR",0,"PTR",(x & 0xFFFF)|(y & 0xFFFF)<<16,"PTR") } TTM_UPDATE(T){ Return DllCall("SendMessage","PTR",T.HWND,"UInt",0x41D,"PTR",0,"PTR",0,"PTR") } TTM_UPDATETIPTEXT(T,pTOOLINFO=0){ static TTM_UPDATETIPTEXT = A_IsUnicode?0x439:0x40c Return DllCall("SendMessage","PTR",T.HWND,"UInt",TTM_UPDATETIPTEXT,"PTR",0,"PTR",pTOOLINFO?pTOOLINFO:T.P[""],"PTR") } TTM_WINDOWFROMPOINT(T,pPOINT){ Return DllCall("SendMessage","PTR",T.HWND,"UInt",0x410,"PTR",0,"PTR",pPOINT,"PTR") }