[LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

Post your working scripts, libraries and tools
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

26 Oct 2014, 06:24

Yeah I confirm that Remove is more reliable. A lot of times i ended up deleting the wrong icon with Delete, because the number of icons changed...
ABCza on the old forum.
My GitHub.
kidbit
Posts: 168
Joined: 02 Oct 2013, 16:05

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

27 Oct 2014, 12:10

Can I restore the icons after I deleted/removed them?

Hiding an icon works this way: the icon disappears, yet the space it occupied in tray remains still reserved for that icon, so it may look like this:
Image

Also, there seems to be a small issue with hiding/restoring: if you hide all icons and then try to restore them - only a portion of them (3 for me) will get restored, but if you try to restore them once again - the rest will get restored.
It also restores some system icons that got hidden by some checkboxes somewhere.
question := (2b) || !(2b) © Shakespeare.
FanaticGuru
Posts: 1231
Joined: 30 Sep 2013, 22:25

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

27 Oct 2014, 15:01

kidbit wrote:Can I restore the icons after I deleted/removed them?

Also, there seems to be a small issue with hiding/restoring: if you hide all icons and then try to restore them - only a portion of them (3 for me) will get restored, but if you try to restore them once again - the rest will get restored.
It also restores some system icons that got hidden by some checkboxes somewhere.
A lot of these functions are just sending Windows a message to execute built-in stuff. Here is the Microsoft help on the messages sent:
http://msdn.microsoft.com/en-us/library ... s.85).aspx

Delete and Remove both cause Windows to execute a command that I believe really deletes the tray icons with no means to restore them.

Hide again is just sending Windows a message and Windows is doing all the heavy lifting. Leaving the blank space for a hidden icon is just a feature of Windows.

As for the having to do it two times, I imagine this could have something to do with the two tray areas of the Tray window and the Overflow window. Sometimes Windows thinks a tray icon is in one area but it is really in the other. That is just a theory that could be totally wrong.

I have had problems before trying to Remove a tray icon and Windows being unable to do so because a tray icon is not where expected until Windows does an update of the tray icon areas and gets the tray icon in the area expected.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
hotkeyguy
Posts: 127
Joined: 11 Oct 2014, 12:22

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

21 Jan 2015, 13:35

Hello,

and first of all many thanks for that library.

Is it technically possible to trigger an menu item of an tray icon without showing the menu of the tray icon itself?
Any hints?


Many thanks and greetings
hotkeyguy
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

24 Jan 2015, 16:11

Yes, with Window Detective you can try to catch the message that is sent when you click on the menu item and use it with the Post/SendMessage AutoHotkey command. If you need help, open a dedicated thread in the Help section :)
ABCza on the old forum.
My GitHub.
Geob

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

17 Mar 2015, 06:14

Hi,

thank you for this library!

About the TrayIcon_Button function above, does it work for someone?
Geob

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

17 Mar 2015, 09:26

Strange, had to double click to make it works, maybe a bug? The application is Telegram Desktop, it's written in Qt, maybe the bug is in how the click event is managed by Qt?
-_+
Posts: 70
Joined: 06 Dec 2014, 12:43

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

10 Oct 2015, 21:02

There's something wrong with the TrayIcon_Hide() function:
1. It accepts idx (not idcmd) as 1st param.
2. seems like it has it's own list of icons' indexes, because they don't match the indexes returned by TrayIcon_GetInfo(). Some indexes hide a few icons at once: turns out it depends on the taskbar's position and size.
For example:
Vertical taskbar: 2, 3, 4, 5 and 6 columns + TrayIcon_Hide() result into 2, 3, 4, 1 and 6 icons (respectively) getting hidden.
Horizontal taskbar: 1, 2, 3, 4, and 5 rows + TrayIcon_Hide() result into 1, 1, 1, 1, and 6 icons (respectively) getting hidden.

A series of tests showed that this function always hides either 0 icons, 1 icon or 1 row of icons (irregardless of number of icons in the row).

Could anyone, please, confirm and/or fix this issue?
User avatar
SL5
Posts: 493
Joined: 12 May 2015, 02:10
GitHub: sl5net
Contact:

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Jan 2016, 04:01

hi i want set no no TrayIcon for all running scripts (noTrayIcon4AllRunningScripts.ahk)

is there a way to to this with trayicon.ahk ? TrayIcon_Hide(idn) ?

thanks
User avatar
jmeneses
Posts: 463
Joined: 28 Oct 2014, 11:09
Location: Catalan Republic

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Jan 2016, 04:29

Hi SL5
I have a similar script to hide/unhide my AHK scripts compiled using TrayIcon
This

Code: Select all


DetectHiddenWindows, On
TrayIcons(,"AutoHotkey","S", true)       ; Icon Hide Omit first parameter!!
Sleep 3000                                         
TrayIcons(,"AutoHotkey","S", false)      ; Icon UnHide 
                                         
TrayIcons(sExeName = "", sClassName = "", sOnlyOneClass = "", OnOFF = true)
{
	 DetectHiddenWindows,% DHW:=A_DetectHiddenWindows ? "On" : "On"
   WinGet,   pidTaskbar, PID, ahk_class Shell_TrayWnd
   hProc:=   DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
   pProc:=   DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
   idxTB:=   GetTrayBar()
   ControlGet,chWnd,HWND,,ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd
   ErrorLevel:=DllCall("SendMessage","UPTR",chWnd,"UInt", 0x418, "UPTR",0,"UPTR", 0,"UPTR")   ; TB_BUTTONCOUNT
   Loop,   %ErrorLevel%
   {
      DllCall("SendMessage","UPTR",chWnd,"UInt",0x417,"UPTR",A_Index-1,"UPTR",pProc) ; TB_GETBUTTON
      VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
      DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", pProc, "UPTR", &btn, "Uint", 32, "Uint", 0)
         iBitmap   := NumGet(btn, 0)
         idn   := NumGet(btn, 4)
         Statyle := NumGet(btn, 8)
      If   dwData   := NumGet(btn,12)
         iString   := NumGet(btn,16)
      Else   dwData   := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
      DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", dwData, "UPTR", &nfo, "Uint", 32, "Uint", 0)
      If   NumGet(btn,12)
         hWnd   := NumGet(nfo, 0)
      ,   uID   := NumGet(nfo, 4)
      ,   nMsg   := NumGet(nfo, 8)
      ,   hIcon   := NumGet(nfo,20)
      Else   hWnd   := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8), nMsg:=NumGet(nfo,12)
      If (!DllCall("IsWindow","UPTR",hwnd))
      {
      IconsToRemove.=hwnd "." uID "."
      Continue
      }
      WinGet, pid, PID,              ahk_id %hWnd%
      WinGet, sProcess, ProcessName, ahk_id %hWnd%
      WinGetClass, sClass,           ahk_id %hWnd%
      If (sClassName && (sClassName = sClass))
      or ((!sExeName && !sClassName) || (sExeName = sProcess) || (sExeName = pid)){
         VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
      ,   DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", iString, "UPTR", &wTooltip, "Uint", 128*2, "Uint", 0)
      ,   A_IsUnicode ? (sToolTip:=StrGet(&wToolTip)) : DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
      ,   sTrayIcons .= "idx: " . A_Index-1 . " | idn: " . idn . " | Pid: " . pid . " | uID: " . uID . " | MessageID: " . nMsg . " | hWnd: " . hWnd . " | Class: " . sClass . " | Process: " . sProcess . "`n" . "   | Tooltip: " . sTooltip . "`n"
          If (sClassName && sOnlyOneClass)
              HideTrayIcon(idn,OnOFF)
      
      }
   }
  Loop,Parse,IconsToRemove,.
    If !Mod(A_Index,2)
      RemoveTrayIcon(hwnd,A_LoopField)
    else hwnd:=A_LoopField
  DllCall("VirtualFreeEx", "UPTR", hProc, "UPTR", pProc, "Uint", 0, "Uint", 0x8000)
  DllCall("CloseHandle", "UPTR", hProc)
  DetectHiddenWindows,% DHW
  Return  sTrayIcons
}

RemoveTrayIcon(hWnd, uID, nMsg = 0, hIcon = 0, nRemove = 2)
{
   NumPut(VarSetCapacity(ni,444,0), ni)
   NumPut(hWnd , ni, 4)
   NumPut(uID  , ni, 8)
   NumPut(1|2|4, ni,12)
   NumPut(nMsg , ni,16)
   NumPut(hIcon, ni,20)
   Return   DllCall("shell32\Shell_NotifyIcon" (A_IsUnicode?"W":"A"), "Uint", nRemove, "UPTR", &ni)
}

HideTrayIcon(idn, bHide = True)
{
   idxTB := GetTrayBar()
   SendMessage, 0x404, idn, bHide, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_HIDEBUTTON
   SendMessage, 0x1A, 0, 0, , ahk_class Shell_TrayWnd
}

DeleteTrayIcon(idx)
{
   idxTB := GetTrayBar()
   SendMessage, 0x416, idx - 1, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_DELETEBUTTON
   SendMessage, 0x1A, 0, 0, , ahk_class Shell_TrayWnd
}

MoveTrayIcon(idxOld, idxNew)
{
   idxTB := GetTrayBar()
   SendMessage, 0x452, idxOld - 1, idxNew - 1, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_MOVEBUTTON
}

GetTrayBar()
{
   ControlGet, hParent, hWnd,, TrayNotifyWnd1  , ahk_class Shell_TrayWnd
   ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
   Loop
   {
      ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
      If  Not   hWnd
         Break
      Else If   hWnd = %hChild%
      {
         idxTB := A_Index
         Break
      }
   }
   Return   idxTB
}
Last edited by jmeneses on 19 Jan 2016, 05:35, edited 1 time in total.
Donec Perficiam
User avatar
SL5
Posts: 493
Joined: 12 May 2015, 02:10
GitHub: sl5net
Contact:

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Jan 2016, 05:15

jmeneses wrote:Hi SL5
I have a similar script to hide/unhide my AHK scripts compiled using TrayIcon
mine seems not completly working.
no success with mine or/and your script. may my exampleHideAllAutohotkey() is wrong written?

This (updated 16-01-19_11-21):

Code: Select all


 
;<<<<<<<<< its from <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;~ http://www.autohotkey.com/board/topic/63646-solved-running-ahk-process-list/
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;~ please use this ! as first line in every script before all includes! :)
isDevellopperMode=true ; enthällt auch update script.
bugIt := true ; 
;~ bugIt := false ; 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#Include *i init_global.init.inc.ahk


;~ exampleReloadAllAutohotkey()
MsgBox, start hide all HideAllAutohotkey tray icons?
exampleHideAllAutohotkey()
;~ MsgBox,16-01-19_10-48 script and examples are working `n examples hide alll ahk or run all ahk
;~ ExitApp
Reload
;~ exampleHideAllAutohotkey()
exampleHideAllAutohotkey(){
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
test := TrayIcon_GetInfo()
Loop, % test.MaxIndex()
{
	if(InStr(test[A_Index].process ,"Autohotkey"))
	{
		TrayIcon_Hide(test[A_Index].idx ) ; thats working sometimes ? not working :(
		;~ TrayIcon_Hide(test[A_Index].idcmd ) ; thats working
		;~ TrayIcon_Hide(test[A_Index].hwnd ) ; thats not working
		;~ TrayIcon_Hide(test[A_Index].idx, false ) 
		str .= test[A_Index].place " - " test[A_Index].idx " - " test[A_Index].process " - " test[A_Index].hwnd " - " test[A_Index].idcmd . "`n "
		;~ run, % test[A_Index].process
		;~ MsgBox,  % test[A_Index].process
	}
}
MsgBox, the following autohotkey script shold now Visible without trayIcon: `n `n TrayIcon_Hide = `n %str% `n '%test%' = test (line:%A_LineNumber%) `n [, '%A_Index%' = A_Index (line:%A_LineNumber%) `n ]., '%idx%' = idx (line:%A_LineNumber%) `n 
 ;~ Reload
 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
return
}


exampleReloadAllAutohotkey(){
DetectHiddenWindows,on
WinGet, id, list,,, Program Manager
Loop, %id%
{
  this_id := id%A_Index% 
  ;~ WinActivate, ahk_id %this_id%
  WinGetClass, this_class, ahk_id %this_id%
  WinGetTitle, this_title, ahk_id %this_id%
  WinGet, this_PName, ProcessName, ahk_id %this_id%
  ;~ If(This_class != "Shell_traywnd") && (This_class != "Button")  ; If class is not Shell_traywnd and not Button
  ;~ if(this_title == w)
  ;~ MsgBox, '%this_title%' = this_title  `n  '%A_ScriptName%' = A_ScriptName `n  '%scriptName%' = scriptName (line:%A_LineNumber%) `n 

if(!this_title || !InStr(this_title,".ahk") || InStr(this_title , A_ScriptName))
	continue
	
	scriptName := RegExReplace(this_title,"^.*?([\w_-\d\.]+\.ahk).*","$1")

  MsgBox, lets run `n `n ==> %scriptName% `n `n '%this_title%' = this_title  `n  '%A_ScriptName%' = A_ScriptName `n  '%scriptName%' = scriptName (line:%A_LineNumber%) `n 
  if(FileExist(scriptName))
	run, %scriptName%
  
  ;~ ToolTip,%this_title%
  ;~ Sleep,1000
}
MsgBox, return 16-01-19_11-01
return
}
;>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>


DetectHiddenWindows, On
tIcons := TrayIcons(), fr:=True
Gui, add, listview, w400 h500 AltSubmit Grid Checked glvHandler, % "Pid|Tooltip|Process"

Loop, Parse, tIcons,|
{


if a_loopfield contains pid:
pid:=RegexReplace(RegexReplace(a_loopfield, "Pid:\s"), "\s")

if a_loopfield contains process:
proc:=RegexReplace(RegexReplace(a_loopfield, "Process:\s"), "\s")

if a_loopfield contains tooltip:
{
tooltip:=RegexReplace(a_loopfield, "Tooltip:\s")
if pid in %proclist%
continue
LV_Add("check", pid, tooltip, proc), LV_ModifyCol(), LV_ModifyCol(3, "AutoHdr") proclist.=pid ","
}
}
Gui, Show
Return

lvHandler:
Critical
LV_GetText(pid, A_EventInfo)
if (a_guievent = "I" && !fr)
{
stat:=inStr(ErrorLevel, "c", True)
HideTrayIcon(RegexReplace(TrayIcons(pid), ".*idn:\s(\d+).*", "$1"),stat)
}
fr:=False
return

TrayIcons(sExeName = "")
{
WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd
hProc:= DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
pProc:= DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
idxTB:= GetTrayBar()
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_BUTTONCOUNT
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETBUTTON
VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)
iBitmap := NumGet(btn, 0)
idn := NumGet(btn, 4)
Statyle := NumGet(btn, 8)
If dwData := NumGet(btn,12)
iString := NumGet(btn,16)
Else dwData := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 32, "Uint", 0)
If NumGet(btn,12)
hWnd := NumGet(nfo, 0)
, uID := NumGet(nfo, 4)
, nMsg := NumGet(nfo, 8)
, hIcon := NumGet(nfo,20)
Else hWnd := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8), nMsg:=NumGet(nfo,12)
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
, DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString, "Uint", &wTooltip, "Uint", 128*2, "Uint", 0)
, DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
, sTrayIcons .= "idx: " . A_Index-1 . " | idn: " . idn . " | Pid: " . pid . " | uID: " . uID . " | MessageID: " . nMsg . " | hWnd: " . hWnd . " | Class: " . sClass . " | Process: " . sProcess . " | Tooltip: " . sTooltip . "|`n"
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
Return sTrayIcons
}

HideTrayIcon(idn, bHide = True)
{
idxTB := GetTrayBar()
SendMessage, 0x404, idn, bHide, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_HIDEBUTTON
SendMessage, 0x1A, 0, 0, , ahk_class Shell_TrayWnd
}

GetTrayBar()
{
ControlGet, hParent, hWnd,, TrayNotifyWnd1 , ahk_class Shell_TrayWnd
ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
Loop
{
ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
If Not hWnd
Break
Else If hWnd = %hChild%
{
idxTB := A_Index
Break
}
}
Return idxTB
}
------------------------------------------------------- 


#Include TrayIcon.ahk

#Include *i functions_global.inc.ahk
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;~ subroutinen beispielsweise müsen ans Dateiende
#Include *i functions_global_dateiende.inc.ahk
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#Include *i UPDATEDSCRIPT_global.inc.ahk
return 

User avatar
jmeneses
Posts: 463
Joined: 28 Oct 2014, 11:09
Location: Catalan Republic

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Jan 2016, 05:37

My example uses a copy of this post
Donec Perficiam
User avatar
SL5
Posts: 493
Joined: 12 May 2015, 02:10
GitHub: sl5net
Contact:

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Jan 2016, 05:41

jmeneses wrote:My example uses a copy of this post
was i tring to do with exampleHideAllAutohotkey() is to hide all tray icons if i working with laptop.
in other situations i will unHide trayIcons again. is that possivle with this functtons?

my problem is that my Tray is to full. so i searching solutions for it. see how full:
2016-01-19 11_40_30-.png
highend
Posts: 43
Joined: 24 Nov 2014, 16:57

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

22 Jul 2016, 16:34

Is there any way to get the info about a tray icon if it is currently hidden / visible?
Leito

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

20 Oct 2017, 04:39

The library with the TrayIcon_Button function doesn't work on Windows 10 1709. Any idea how to fix this?

For reference, this is the code I use (I hope I have the latest):

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------
; Name ..........: TrayIcon library
; Description ...: Provide some useful functions to deal with Tray icons.
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode
; Original Author: Sean (http://goo.gl/dh0xIX) (http://www.autohotkey.com/forum/viewtopic.php?t=17314)
; Update Author .: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229)
; Mod Author ....: Fanatic Guru
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/
; Version Date...: 2016 - 03 - 08
; Note ..........: Many people have updated Sean's original work including me but Cyruz's version seemed the most straight
; ...............: forward update for 64 bit so I adapted it with some of the features from my Fanatic Guru version.
; Update 20160120: Went through all the data types in the DLL and NumGet and matched them up to MSDN which fixed IDcmd.
; Update 20160308: Fix for Windows 10 NotifyIconOverflowWindow
; ----------------------------------------------------------------------------------------------------------------------

; ----------------------------------------------------------------------------------------------------------------------
; Function ......: TrayIcon_GetInfo
; Description ...: Get a series of useful information about tray icons.
; Parameters ....: sExeName  - The exe for which we are searching the tray icon data. Leave it empty to receive data for 
; ...............:             all tray icons.
; Return ........: oTrayIcon_GetInfo - An array of objects containing tray icons data. Any entry is structured like this:
; ...............:             oTrayIcon_GetInfo[A_Index].idx     - 0 based tray icon index.
; ...............:             oTrayIcon_GetInfo[A_Index].IDcmd   - Command identifier associated with the button.
; ...............:             oTrayIcon_GetInfo[A_Index].pID     - Process ID.
; ...............:             oTrayIcon_GetInfo[A_Index].uID     - Application defined identifier for the icon.
; ...............:             oTrayIcon_GetInfo[A_Index].msgID   - Application defined callback message.
; ...............:             oTrayIcon_GetInfo[A_Index].hIcon   - Handle to the tray icon.
; ...............:             oTrayIcon_GetInfo[A_Index].hWnd    - Window handle.
; ...............:             oTrayIcon_GetInfo[A_Index].Class   - Window class.
; ...............:             oTrayIcon_GetInfo[A_Index].Process - Process executable.
; ...............:             oTrayIcon_GetInfo[A_Index].Tray    - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow).
; ...............:             oTrayIcon_GetInfo[A_Index].tooltip - Tray icon tooltip.
; Info ..........: TB_BUTTONCOUNT message - http://goo.gl/DVxpsg
; ...............: TB_GETBUTTON message   - http://goo.gl/2oiOsl
; ...............: TBBUTTON structure     - http://goo.gl/EIE21Z
; ----------------------------------------------------------------------------------------------------------------------

TrayIcon_GetInfo(sExeName := "")
{
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	oTrayIcon_GetInfo := {}
	For key, sTray in ["NotifyIconOverflowWindow", "Shell_TrayWnd"]
	{
		idxTB := TrayIcon_GetTrayBar()
		WinGet, pidTaskbar, PID, ahk_class %sTray%
		
		hProc := DllCall("OpenProcess", UInt, 0x38, Int, 0, UInt, pidTaskbar)
		pRB   := DllCall("VirtualAllocEx", Ptr, hProc, Ptr, 0, UPtr, 20, UInt, 0x1000, UInt, 0x4)

		if (SubStr(A_OSVersion,1,2)=10)
			SendMessage, 0x418, 0, 0, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_BUTTONCOUNT
		else	
			SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_BUTTONCOUNT
		
		szBtn := VarSetCapacity(btn, (A_Is64bitOS ? 32 : 20), 0)
		szNfo := VarSetCapacity(nfo, (A_Is64bitOS ? 32 : 24), 0)
		szTip := VarSetCapacity(tip, 128 * 2, 0)
		
		Loop, %ErrorLevel%
		{
			if (SubStr(A_OSVersion,1,2)=10)
				SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_GETBUTTON
			else
				SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_GETBUTTON
			DllCall("ReadProcessMemory", Ptr, hProc, Ptr, pRB, Ptr, &btn, UPtr, szBtn, UPtr, 0)

			iBitmap := NumGet(btn, 0, "Int")
			IDcmd   := NumGet(btn, 4, "Int")
			statyle := NumGet(btn, 8)
			dwData  := NumGet(btn, (A_Is64bitOS ? 16 : 12))
			iString := NumGet(btn, (A_Is64bitOS ? 24 : 16), "Ptr")

			DllCall("ReadProcessMemory", Ptr, hProc, Ptr, dwData, Ptr, &nfo, UPtr, szNfo, UPtr, 0)

			hWnd  := NumGet(nfo, 0, "Ptr")
			uID   := NumGet(nfo, (A_Is64bitOS ? 8 : 4), "UInt")
			msgID := NumGet(nfo, (A_Is64bitOS ? 12 : 8))
			hIcon := NumGet(nfo, (A_Is64bitOS ? 24 : 20), "Ptr")

			WinGet, pID, PID, ahk_id %hWnd%
			WinGet, sProcess, ProcessName, ahk_id %hWnd%
			WinGetClass, sClass, ahk_id %hWnd%

			If !sExeName || (sExeName = sProcess) || (sExeName = pID)
			{
				DllCall("ReadProcessMemory", Ptr, hProc, Ptr, iString, Ptr, &tip, UPtr, szTip, UPtr, 0)
				Index := (oTrayIcon_GetInfo.MaxIndex()>0 ? oTrayIcon_GetInfo.MaxIndex()+1 : 1)
				oTrayIcon_GetInfo[Index,"idx"]     := A_Index - 1
				oTrayIcon_GetInfo[Index,"IDcmd"]   := IDcmd
				oTrayIcon_GetInfo[Index,"pID"]     := pID
				oTrayIcon_GetInfo[Index,"uID"]     := uID
				oTrayIcon_GetInfo[Index,"msgID"]   := msgID
				oTrayIcon_GetInfo[Index,"hIcon"]   := hIcon
				oTrayIcon_GetInfo[Index,"hWnd"]    := hWnd
				oTrayIcon_GetInfo[Index,"Class"]   := sClass
				oTrayIcon_GetInfo[Index,"Process"] := sProcess
				oTrayIcon_GetInfo[Index,"Tooltip"] := StrGet(&tip, "UTF-16")
				oTrayIcon_GetInfo[Index,"Tray"]    := sTray
			}
		}
		DllCall("VirtualFreeEx", Ptr, hProc, Ptr, pProc, UPtr, 0, Uint, 0x8000)
		DllCall("CloseHandle", Ptr, hProc)
	}
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
	Return oTrayIcon_GetInfo
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Hide
; Description ..: Hide or unhide a tray icon.
; Parameters ...: IDcmd - Command identifier associated with the button.
; ..............: bHide - True for hide, False for unhide.
; ..............: sTray - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow.
; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Hide(IDcmd, sTray := "Shell_TrayWnd", bHide:=True)
{
	(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : )
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	idxTB := TrayIcon_GetTrayBar()
	SendMessage, 0x404, IDcmd, bHide, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_HIDEBUTTON
	SendMessage, 0x1A, 0, 0, , ahk_class %sTray%
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Delete
; Description ..: Delete a tray icon.
; Parameters ...: idx - 0 based tray icon index.
; ..............: sTray - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow.
; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Delete(idx, sTray := "Shell_TrayWnd")
{
	(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : )
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	idxTB := TrayIcon_GetTrayBar()
	SendMessage, 0x416, idx, 0, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_DELETEBUTTON
	SendMessage, 0x1A, 0, 0, , ahk_class %sTray%
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Remove
; Description ..: Remove a tray icon.
; Parameters ...: hWnd, uID.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Remove(hWnd, uID)
{
		NumPut(VarSetCapacity(NID,(A_IsUnicode ? 2 : 1) * 384 + A_PtrSize * 5 + 40,0), NID)
		NumPut(hWnd , NID, (A_PtrSize == 4 ? 4 : 8 ))
		NumPut(uID  , NID, (A_PtrSize == 4 ? 8  : 16 ))
		Return DllCall("shell32\Shell_NotifyIcon", "Uint", 0x2, "Uint", &NID)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Move
; Description ..: Move a tray icon.
; Parameters ...: idxOld - 0 based index of the tray icon to move.
; ..............: idxNew - 0 based index where to move the tray icon.
; ..............: sTray - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow.
; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd")
{
	(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : )
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	idxTB := TrayIcon_GetTrayBar()
	SendMessage, 0x452, idxOld, idxNew, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_MOVEBUTTON
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetTrayBar
; Description ..: Get the tray icon handle.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetTrayBar()
{
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	WinGet, ControlList, ControlList, ahk_class Shell_TrayWnd
	RegExMatch(ControlList, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", nTB)
	Loop, %nTB%
	{
		ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
		hParent := DllCall( "GetParent", Ptr, hWnd )
		WinGetClass, sClass, ahk_id %hParent%
		If (sClass <> "SysPager")
			Continue
		idxTB := A_Index
		Break
	}
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
	Return  idxTB
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetHotItem
; Description ..: Get the index of tray's hot item.
; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetHotItem()
{
	idxTB := TrayIcon_GetTrayBar()
	SendMessage, 0x447, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETHOTITEM
	Return ErrorLevel << 32 >> 32
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Button
; Description ..: Simulate mouse button click on a tray icon.
; Parameters ...: sExeName - Executable Process Name of tray icon.
; ..............: sButton  - Mouse button to simulate (L, M, R).
; ..............: bDouble  - True to double click, false to single click.
; ..............: index    - Index of tray icon to click if more than one match.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Button(sExeName, sButton := "L", bDouble := false, index := 1)
{
	DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" :
	WM_MOUSEMOVE	  = 0x0200
	WM_LBUTTONDOWN	  = 0x0201
	WM_LBUTTONUP	  = 0x0202
	WM_LBUTTONDBLCLK = 0x0203
	WM_RBUTTONDOWN	  = 0x0204
	WM_RBUTTONUP	  = 0x0205
	WM_RBUTTONDBLCLK = 0x0206
	WM_MBUTTONDOWN	  = 0x0207
	WM_MBUTTONUP	  = 0x0208
	WM_MBUTTONDBLCLK = 0x0209
	sButton := "WM_" sButton "BUTTON"
	oIcons := {}
	oIcons := TrayIcon_GetInfo(sExeName)
	msgID  := oIcons[index].msgID
	uID    := oIcons[index].uID
	hWnd   := oIcons[index].hWnd
	if bDouble
		PostMessage, msgID, uID, %sButton%DBLCLK, , ahk_id %hWnd%
	else
	{
		PostMessage, msgID, uID, %sButton%DOWN, , ahk_id %hWnd%
		PostMessage, msgID, uID, %sButton%UP, , ahk_id %hWnd%
	}
	DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
	return
}
User avatar
SL5
Posts: 493
Joined: 12 May 2015, 02:10
GitHub: sl5net
Contact:

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

21 Oct 2017, 09:28

thanks works for me (Win7 64bit):

test := TrayIcon_GetInfo() Loop, % test.MaxIndex() ... TrayIcon_Delete(test[A_Index].idx)

frees may tray comletly :) great :) :bravo:
Vince42
Posts: 6
Joined: 05 Feb 2016, 14:41

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

18 Nov 2017, 19:32

Hi,
Leito wrote:The library with the TrayIcon_Button function doesn't work on Windows 10 1709. Any idea how to fix this?
For reference, this is the code I use (I hope I have the latest):

Code: Select all

...
Same problem here. I also tried IRC and read some posts about problems on StackOverflow, but did not succeed in getting it running.
Any ideas? Any news on this?

Cheers
Vince
RiseUp
Posts: 26
Joined: 01 Oct 2013, 21:27

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

19 Nov 2017, 23:31

Vince42 wrote:Same problem here. I also tried IRC and read some posts about problems on StackOverflow, but did not succeed in getting it running.
Any ideas? Any news on this?

Cheers
Vince
Can you share the code you have that isn't working?
Vince42
Posts: 6
Joined: 05 Feb 2016, 14:41

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

20 Nov 2017, 05:27

Hi,
RiseUp wrote:
Vince42 wrote:Same problem here. I also tried IRC and read some posts about problems on StackOverflow, but did not succeed in getting it running.
Any ideas? Any news on this?

Cheers
Vince
Can you share the code you have that isn't working?
Sure, no problem. I am using the current official version of SysTray.ahk and the code snippet that is not working currently reads like this:

Code: Select all

;================================================================================
; TV-Browser
;--------------------------------------------------------------------------------
; Win+F4 Toggle TV-Browser window
#Include q:\utility\autohotkey\TrayIcon.ahk
#F4::
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe", "L", false, 1)
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe")
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe", "L", false, 1)
    TrayIcon_Button("tvbrowser.exe")
    return
One thing came to my mind: The executable is called "tvbrowser.exe" but as this is a Java executable it is - according to the task manager - invoking "java.exe". I already unsuccessfully tried the function call with "java.exe". Maybe I should first try to read all tray icon information with TrayIcon_GetInfo()?

Cheers
Vince
RiseUp
Posts: 26
Joined: 01 Oct 2013, 21:27

Re: [LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit

20 Nov 2017, 20:17

Vince42 wrote:I am using the current official version of SysTray.ahk and the code snippet that is not working currently reads like this:

Code: Select all

;================================================================================
; TV-Browser
;--------------------------------------------------------------------------------
; Win+F4 Toggle TV-Browser window
#Include q:\utility\autohotkey\TrayIcon.ahk
#F4::
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe", "L", false, 1)
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe")
    ;TrayIcon_Button("p:\information\tvbrowser\tvbrowser.exe", "L", false, 1)
    TrayIcon_Button("tvbrowser.exe")
    return
One thing came to my mind: The executable is called "tvbrowser.exe" but as this is a Java executable it is - according to the task manager - invoking "java.exe". I already unsuccessfully tried the function call with "java.exe". Maybe I should first try to read all tray icon information with TrayIcon_GetInfo()?

Cheers
Vince
If it appears in Task Manager as java.exe, then surely that could be the issue. Also, the uncommented call to the library function in your code simulates a single-click with the left mouse button. Is that what you're trying for?

Using TrayIcon_GetInfo() would definitely help to debug your issue, but it isn't necessary to get it working once you have the right parameter(s) figured out for TrayIcon_Button().

Return to “Scripts and Functions”

Who is online

Users browsing this forum: dice4321, EvetsNalon and 19 guests