Jump to content



Photo

_SysTray UDF


48 replies to this topic

#1 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 13 October 2009 - 05:58 AM

Here is my highly modified version of Tuape's UDF. The example shows how to get different info and how to remove dead icons (no mouse move required). I've included support for the Windows 7 NotifyIconOverflowWindow icons as well, however I recommend using my _OsVersionInfo UDF to determine the OS instead of @OSVersion. This should work on Win2000+, but some testers on XP and Vista would be appreciated.

_SysTray

AutoIt         
#include-once ; ---------------------------------------------------------------------------- ; ; Author:         Tuape ; Modified:       Erik Pilsits ; ; Script Function: ;   Systray UDF - Functions for reading icon info from system tray / removing ;   any icon. ; ; Last Update: 5/13/2013 ; ; ---------------------------------------------------------------------------- ;=============================================================================== ; ; Function Name:    _SysTrayIconCount($iWin = 1) ; Description:      Returns number of icons on systray ;                   Note: Hidden icons are also reported ; Parameter(s):     $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns number of icons found ;                   On Failure - Returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconCount($iWin = 1)     Local Const $TB_BUTTONCOUNT = 1048     Local $hWnd = _FindTrayToolbarWindow($iWin)     If $hWnd = -1 Then Return -1     Local $count = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $TB_BUTTONCOUNT, "wparam", 0, "lparam", 0)     If @error Then Return -1     Return $count[0] EndFunc   ;==>_SysTrayIconCount ;=============================================================================== ; ; Function Name:    _SysTrayIconTitles($iWin = 1) ; Description:      Get list of all window titles that have systray icon ; Parameter(s):     $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; Requirement(s): ; Return Value(s):  On Success - Returns an array with all window titles ;                   On Failure - Returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconTitles($iWin = 1)     Local $count = _SysTrayIconCount($iWin)     If $count <= 0 Then Return -1     Local $titles[$count]     ; Get icon owner window"s title     For $i = 0 To $count - 1         $titles[$i] = WinGetTitle(_SysTrayIconHandle($i, $iWin))     Next     Return $titles EndFunc   ;==>_SysTrayIconTitles ;=============================================================================== ; ; Function Name:    _SysTrayIconPids($iWin = 1) ; Description:      Get list of all processes id's that have systray icon ; Parameter(s):     $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; Requirement(s): ; Return Value(s):  On Success - Returns an array with all process id's ;                   On Failure - Returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconPids($iWin = 1)     Local $count = _SysTrayIconCount($iWin)     If $count <= 0 Then Return -1     Local $processes[$count]     For $i = 0 To $count - 1         $processes[$i] = WinGetProcess(_SysTrayIconHandle($i, $iWin))     Next     Return $processes EndFunc   ;==>_SysTrayIconPids ;=============================================================================== ; ; Function Name:    _SysTrayIconProcesses($iWin = 1) ; Description:      Get list of all processes that have systray icon ; Parameter(s):     $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; Requirement(s): ; Return Value(s):  On Success - Returns an array with all process names ;                   On Failure - Returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconProcesses($iWin = 1)     Local $pids = _SysTrayIconPids($iWin)     If Not IsArray($pids) Then Return -1     Local $processes[UBound($pids)]     ; List all processes     Local $list = ProcessList()     For $i = 0 To UBound($pids) - 1         For $j = 1 To $list[0][0]             If $pids[$i] = $list[$j][1] Then                 $processes[$i] = $list[$j][0]                 ExitLoop             EndIf         Next     Next     Return $processes EndFunc   ;==>_SysTrayIconProcesses ;=============================================================================== ; ; Function Name:    _SysTrayIconIndex($test, $mode = 0, $iWin = 1) ; Description:      Get list of all processes id"s that have systray icon ; Parameter(s):     $test       - process name / window title text / process PID ;                   $mode ;                   | 0         - get index by process name (default) ;                   | 1         - get index by window title ;                   | 2         - get index by process PID ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; Requirement(s): ; Return Value(s):  On Success - Returns index of found icon ;                   On Failure - Returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconIndex($test, $mode = 0, $iWin = 1)     Local $ret = -1, $compare = -1     If $mode < 0 Or $mode > 2 Or Not IsInt($mode) Then Return -1     Switch $mode         Case 0             $compare = _SysTrayIconProcesses($iWin)         Case 1             $compare = _SysTrayIconTitles($iWin)         Case 2             $compare = _SysTrayIconPids($iWin)     EndSwitch     If Not IsArray($compare) Then Return -1     For $i = 0 To UBound($compare) - 1         If $compare[$i] = $test Then             $ret = $i             ExitLoop         EndIf     Next     Return $ret EndFunc   ;==>_SysTrayIconIndex ; INTERNAL ===================================================================== ; ; Function Name:    _SysTrayGetButtonInfo($iIndex, $iWin = 1, $iInfo = 0) ; Description:      Gets Tray Button Info ; Parameter(s):     $iIndex     - icon index (Note: starting from 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ;                   $iInfo      - Info to return ;                   | 1         - TBBUTTON structure ;                   | 2         - TRAYDATA structure ;                   | 3         - tooltip ;                   | 4         - icon position ; Requirement(s): ; Return Value(s):  On Success - Returns requested info ;                   On Failure - Sets @error and returns -1 ;                   | 1        - Failed to find tray window ;                   | 2        - Failed to get tray window PID ;                   | 3        - Failed to open process ;                   | 4        - Failed to allocate memory ;                   | 5        - Failed to get TBBUTTON info ; ; Author(s):        Erik Pilsits, Tuape ; ;=============================================================================== Func _SysTrayGetButtonInfo($iIndex, $iWin = 1, $iInfo = 1)     Local Const $TB_GETBUTTON = 1047 ;~  Local Const $TB_GETBUTTONTEXT = 1099 ;~  Local Const $TB_GETBUTTONINFO = 1089     Local Const $TB_GETITEMRECT = 1053     Local Const $ACCESS = BitOR(0x0008, 0x0010, 0x0400) ; VM_OPERATION, VM_READ, QUERY_INFORMATION     Local $TBBUTTON     If @OSArch = "X86" Then         $TBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[2];dword dwData;int iString")     Else ; X64         $TBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[6];uint64 dwData;int64 iString")     EndIf     Local $TRAYDATA     If @OSArch = "X86" Then         $TRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];handle hIcon")     Else         $TRAYDATA = DllStructCreate("uint64 hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];uint64 hIcon")     EndIf     Local $trayHwnd = _FindTrayToolbarWindow($iWin)     If $trayHwnd = -1 Then Return SetError(1, 0, -1)     Local $return, $err = 0     Local $ret = DllCall("user32.dll", "dword", "GetWindowThreadProcessId", "hwnd", $trayHwnd, "dword*", 0)     If @error Or Not $ret[2] Then SetError(2, 0, -1)     Local $pId = $ret[2]     Local $procHandle = DllCall("kernel32.dll", "handle", "OpenProcess", "dword", $ACCESS, "bool", False, "dword", $pId)     If @error Or Not $procHandle[0] Then Return SetError(3, 0, -1)     Local $lpData = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "handle", $procHandle[0], "ptr", 0, "ulong", DllStructGetSize($TBBUTTON), "dword", 0x1000, "dword", 0x04)     If Not @error And $lpData[0] Then         $ret = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $trayHwnd, "uint", $TB_GETBUTTON, "wparam", $iIndex, "lparam", $lpData[0])         If Not @error And $ret[0] Then             DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $procHandle[0], "ptr", $lpData[0], "struct*", $TBBUTTON, "ulong", DllStructGetSize($TBBUTTON), "ulong*", 0)             Switch $iInfo                 Case 2                     ; TRAYDATA structure                     DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $procHandle[0], "ptr", DllStructGetData($TBBUTTON, 6), "struct*", $TRAYDATA, "ulong", DllStructGetSize($TRAYDATA), "ulong*", 0)                     $return = $TRAYDATA                 Case 3                     ; tooltip                     $return = ""                     If BitShift(DllStructGetData($TBBUTTON, 7), 16) <> 0 Then                         Local $intTip = DllStructCreate("wchar[1024]")                         ; we have a pointer to a string, otherwise it is an internal resource identifier                         DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $procHandle[0], "ptr", DllStructGetData($TBBUTTON, 7), "struct*", $intTip, "ulong", DllStructGetSize($intTip), "ulong*", 0)                         $return = DllStructGetData($intTip, 1)                     ;else internal resource                     EndIf                 Case 4                     ; icon position                     If Not BitAND(DllStructGetData($TBBUTTON, 3), 8) Then ; 8 = TBSTATE_HIDDEN                         Local $pos[2], $RECT = DllStructCreate("int;int;int;int")                         DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $trayHwnd, "uint", $TB_GETITEMRECT, "wparam", $iIndex, "lparam", $lpData[0])                         DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $procHandle[0], "ptr", $lpData[0], "struct*", $RECT, "ulong", DllStructGetSize($RECT), "ulong*", 0)                         $ret = DllCall("user32.dll", "int", "MapWindowPoints", "hwnd", $trayHwnd, "ptr", 0, "struct*", $RECT, "uint", 2)                         $pos[0] = DllStructGetData($RECT, 1)                         $pos[1] = DllStructGetData($RECT, 2)                         $return = $pos                     Else                         $return = -1                     EndIf                 Case Else                     ; TBBUTTON                     $return = $TBBUTTON             EndSwitch         Else             $err = 5         EndIf         DllCall("kernel32.dll", "bool", "VirtualFreeEx", "handle", $procHandle[0], "ptr", $lpData[0], "ulong", 0, "dword", 0x8000)     Else         $err = 4     EndIf     DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $procHandle[0])     If $err Then         Return SetError($err, 0, -1)     Else         Return $return     EndIf EndFunc   ;==>_SysTrayGetButtonInfo ;=============================================================================== ; ; Function Name:    _SysTrayIconHandle($iIndex, $iWin = 1) ; Description:      Gets hwnd of window associated with systray icon of given index ; Parameter(s):     $iIndex     - icon index (Note: starting from 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns hwnd of found icon ;                   On Failure - Sets @error and returns -1 ;                   | See _SysTrayGetButtonInfo for @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconHandle($iIndex, $iWin = 1)     Local $TRAYDATA = _SysTrayGetButtonInfo($iIndex, $iWin, 2)     If @error Then         Return SetError(@error, 0, -1)     Else         Return Ptr(DllStructGetData($TRAYDATA, 1))     EndIf EndFunc   ;==>_SysTrayIconHandle ;=============================================================================== ; ; Function Name:    _SysTrayIconTooltip($iIndex, $iWin = 1) ; Description:      Gets the tooltip text of systray icon of given index ; Parameter(s):     $iIndex     - icon index (Note: starting from 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns tooltip text of icon ;                   On Failure - Sets @error and returns -1 ;                   | See _SysTrayGetButtonInfo for @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconTooltip($iIndex, $iWin = 1)     Local $ret = _SysTrayGetButtonInfo($iIndex, $iWin, 3)     If @error Then         Return SetError(@error, 0, -1)     Else         Return $ret     EndIf EndFunc   ;==>_SysTrayIconTooltip ;=============================================================================== ; ; Function Name:    _SysTrayIconPos($iIndex, $iWin = 1) ; Description:      Gets x & y position of systray icon ; Parameter(s):     $iIndex     - icon index (Note: starting from 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns array, x [0] and y [1] position of icon ;                   On Failure - Sets @error and returns -1 ;                   | -1       - Icon is hidden (Autohide on XP, etc) ;                   | See _SysTrayGetButtonInfo for additional @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconPos($iIndex, $iWin = 1)     Local $ret = _SysTrayGetButtonInfo($iIndex, $iWin, 4)     If @error Then         Return SetError(@error, 0, -1)     Else         If $ret = -1 Then             Return SetError(-1, 0, -1)         Else             Return $ret         EndIf     EndIf EndFunc   ;==>_SysTrayIconPos ;=============================================================================== ; ; Function Name:    _SysTrayIconVisible($iIndex, $iWin = 1) ; Description:      Gets the visibility of a systray icon ; Parameter(s):     $iIndex     - icon index (Note: starting from 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns True (visible) or False (hidden) ;                   On Failure - Sets @error and returns -1 ;                   | See _SysTrayGetButtonInfo for @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconVisible($iIndex, $iWin = 1)     Local $TBBUTTON = _SysTrayGetButtonInfo($iIndex, $iWin, 1)     If @error Then         Return SetError(@error, 0, -1)     Else         Return Not BitAND(DllStructGetData($TBBUTTON, 3), 8) ;TBSTATE_HIDDEN     EndIf EndFunc   ;==>_SysTrayIconVisible ;=============================================================================== ; ; Function Name:    _SysTrayIconHide($index, $iFlag, $iWin = 1) ; Description:      Hides / unhides any icon on systray ; ; Parameter(s):     $index      - icon index. Can be queried with _SysTrayIconIndex() ;                   $iFlag      - hide (1) or show (0) icon ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns 1 if operation was successfull or 0 if ;                   icon was already hidden/unhidden ;                   On Failure - Sets @error and returns -1 ;                   | See _SysTrayGetButtonInfo for @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconHide($index, $iFlag, $iWin = 1) ;~     Local Const $TB_HIDEBUTTON = 0x0404 ; WM_USER + 4     Local $TBBUTTON = _SysTrayGetButtonInfo($index, $iWin, 1)     If @error Then Return SetError(@error, 0, -1)     Local $visible = Not BitAND(DllStructGetData($TBBUTTON, 3), 8) ;TBSTATE_HIDDEN     If ($iFlag And Not $visible) Or (Not $iFlag And $visible) Then         Return 0     Else         Local $TRAYDATA = _SysTrayGetButtonInfo($index, $iWin, 2)         If @error Then Return SetError(@error, 0, -1)         Local $NOTIFYICONDATA = DllStructCreate("dword cbSize;hwnd hWnd;uint uID;uint uFlags;uint uCallbackMessage;handle hIcon;wchar szTip[128];" _             & "dword dwState;dword dwStateMask;wchar szInfo[256];uint uVersion;wchar szInfoTitle[64];dword dwInfoFlags;" _             & "STRUCT;ulong;ushort;ushort;byte[8];ENDSTRUCT;handle hBalloonIcon")         DllStructSetData($NOTIFYICONDATA, 1, DllStructGetSize($NOTIFYICONDATA))         DllStructSetData($NOTIFYICONDATA, 2, Ptr(DllStructGetData($TRAYDATA, 1)))         DllStructSetData($NOTIFYICONDATA, 3, DllStructGetData($TRAYDATA, 2))         DllStructSetData($NOTIFYICONDATA, 4, 8) ; NIF_STATE         DllStructSetData($NOTIFYICONDATA, 8, $iFlag) ; dw_State, 0 or 1 = NIS_HIDDEN         DllStructSetData($NOTIFYICONDATA, 9, 1) ; dwStateMask         Local $ret = DllCall("shell32.dll", "bool", "Shell_NotifyIconW", "dword", 0x1, "struct*", $NOTIFYICONDATA) ; NIM_MODIFY         DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", WinGetHandle("[CLASS:Shell_TrayWnd]"), "uint", 0x001A, "wparam", 0, "lparam", 0) ; WM_SETTINGCHANGE         If IsArray($ret) And $ret[0] Then             Return 1         Else             Return 0         EndIf ;~      $ret = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $trayHwnd, "uint", $TB_HIDEBUTTON, "wparam", DllStructGetData($TBBUTTON, 2), "lparam", $iHide) ;~      If @error Or Not $ret[0] Then ;~          $return = -1 ;~      Else ;~          $return = $ret[0] ;~      EndIf     EndIf EndFunc   ;==>_SysTrayIconHide ;=============================================================================== ; ; Function Name:    _SysTrayIconMove($curPos, $newPos, $iWin = 1) ; Description:      Moves systray icon ; ; Parameter(s):     $curPos     - icon's current index (0 based) ;                   $newPos     - icon's new position ;                                 ($curPos+1 = one step to right, $curPos-1 = one step to left) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s):   AutoIt3 Beta ; Return Value(s):  On Success - Returns 1 if operation was successfull, 0 if not ;                   On Failure - Sets @error and returns -1 ;                   | 1        - Bad parameters ;                   | 2        - Failed to find tray window ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconMove($curPos, $newPos, $iWin = 1)     Local Const $TB_MOVEBUTTON = 0x0452 ; WM_USER + 82     Local $iconCount = _SysTrayIconCount($iWin)     If $curPos < 0 Or $newPos < 0 Or $curPos > $iconCount - 1 Or $newPos > $iconCount - 1 Or Not IsInt($curPos) Or Not IsInt($newPos) Then Return SetError(1, 0, -1)     Local $hWnd = _FindTrayToolbarWindow($iWin)     If $hWnd = -1 Then Return SetError(2, 0, -1)     Local $ret = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $TB_MOVEBUTTON, "wparam", $curPos, "lparam", $newPos)     If @error Or Not $ret[0] Then         Return 0     Else         Return 1     EndIf EndFunc   ;==>_SysTrayIconMove ;=============================================================================== ; ; Function Name:    _SysTrayIconRemove($index, $iWin = 1) ; Description:      Removes systray icon completely. ; ; Parameter(s):     $index      - Icon index (first icon is 0) ;                   $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Return Value(s):  On Success - Returns 1 if icon successfully removed, 0 if not ;                   On Failure - Sets @error and returns -1 ;                   | See _SysTrayGetButtonInfo for @error returns ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _SysTrayIconRemove($index, $iWin = 1)     Local Const $TB_DELETEBUTTON = 1046     Local $TRAYDATA = _SysTrayGetButtonInfo($index, $iWin, 2)     If @error Then Return SetError(@error, 0, -1)     Local $NOTIFYICONDATA = DllStructCreate("dword cbSize;hwnd hWnd;uint uID;uint uFlags;uint uCallbackMessage;handle hIcon;wchar szTip[128];" _         & "dword dwState;dword dwStateMask;wchar szInfo[256];uint uVersion;wchar szInfoTitle[64];dword dwInfoFlags;" _         & "STRUCT;ulong;ushort;ushort;byte[8];ENDSTRUCT;handle hBalloonIcon")     DllStructSetData($NOTIFYICONDATA, 1, DllStructGetSize($NOTIFYICONDATA))     DllStructSetData($NOTIFYICONDATA, 2, Ptr(DllStructGetData($TRAYDATA, 1)))     DllStructSetData($NOTIFYICONDATA, 3, DllStructGetData($TRAYDATA, 2))     Local $ret = DllCall("shell32.dll", "bool", "Shell_NotifyIconW", "dword", 0x2, "struct*", $NOTIFYICONDATA) ; NIM_DELETE     DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", WinGetHandle("[CLASS:Shell_TrayWnd]"), "uint", 0x001A, "wparam", 0, "lparam", 0) ; WM_SETTINGCHANGE     If IsArray($ret) And $ret[0] Then         Return 1     Else         Return 0     EndIf ;~  Local $hWnd = _FindTrayToolbarWindow($iWin) ;~  If $hwnd = -1 Then Return -1 ;~  Local $ret = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $TB_DELETEBUTTON, "wparam", $index, "lparam", 0) ;~  If @error Or Not $ret[0] Then Return -1 ;~  Return $ret[0] EndFunc   ;==>_SysTrayIconRemove ;=============================================================================== ; ; Function Name:    _FindTrayToolbarWindow($iWin = 1) ; Description:      Utility function for finding Toolbar window hwnd ; Parameter(s):     $iWin ;                   | 1         - ToolbarWindow32, Win2000+ ;                   | 2         - NotifyIconOverflowWindow, Win7+ ; ; Requirement(s): ; Return Value(s):  On Success - Returns Toolbar window hwnd ;                   On Failure - returns -1 ; ; Author(s):        Tuape, Erik Pilsits ; ;=============================================================================== Func _FindTrayToolbarWindow($iWin = 1)     Local $hwnd, $ret = -1     If $iWin = 1 Then         $hWnd = DllCall("user32.dll", "hwnd", "FindWindow", "str", "Shell_TrayWnd", "ptr", 0)         If @error Then Return -1         $hWnd = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "TrayNotifyWnd", "ptr", 0)         If @error Then Return -1         If @OSVersion <> "WIN_2000" Then             $hWnd = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "SysPager", "ptr", 0)             If @error Then Return -1         EndIf         $hWnd = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "ToolbarWindow32", "ptr", 0)         If @error Then Return -1         $ret = $hwnd[0]     ElseIf $iWin = 2 Then         ; NotifyIconOverflowWindow for Windows 7         $hWnd = DllCall("user32.dll", "hwnd", "FindWindow", "str", "NotifyIconOverflowWindow", "ptr", 0)         If @error Then Return -1         $hWnd = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "ToolbarWindow32", "ptr", 0)         If @error Then Return -1         $ret = $hwnd[0]     EndIf     Return $ret EndFunc   ;==>_FindTrayToolbarWindow

 
 
Example

AutoIt         
#NoTrayIcon #include <_SysTray.au3> #include <Process.au3> $count = _SysTrayIconCount() ConsoleWrite("Count visible tray:  " & $count & @CRLF) For $i = $count - 1 To 0 Step -1     $handle = _SysTrayIconHandle($i)     $visible = _SysTrayIconVisible($i)     $pid = WinGetProcess($handle)     $name = _ProcessGetName($pid)     $title = WinGetTitle($handle)     $tooltip = _SysTrayIconTooltip($i)     ConsoleWrite("index:  " & $i & @TAB & "visible:  " & $visible & @TAB & "handle:  " & $handle & @TAB & "pid:  " & _                     $pid & @TAB & "proc:  " & $name & @TAB & @TAB & "title:  " & $title & @TAB & @TAB & "tooltip:  " & $tooltip & @CRLF)     If $pid = -1 Then _SysTrayIconRemove($i) Next If _FindTrayToolbarWindow(2) <> -1 Then     ConsoleWrite("-====================-" & @CRLF)     $countwin7 = _SysTrayIconCount(2)     ConsoleWrite("Count overflow area:  " & $countwin7 & @CRLF)     For $i = $countwin7 - 1 To 0 Step -1         $handle = _SysTrayIconHandle($i, 2)         $visible = _SysTrayIconVisible($i, 2)         $pid = WinGetProcess($handle)         $name = _ProcessGetName($pid)         $title = WinGetTitle($handle)         $tooltip = _SysTrayIconTooltip($i, 2)         ConsoleWrite("index:  " & $i & @TAB & "visible:  " & $visible & @TAB & "handle:  " & $handle & @TAB & "pid:  " & _                         $pid & @TAB & "proc:  " & $name & @TAB & @TAB & "title:  " & $title & @TAB & @TAB & "tooltip:  " & $tooltip & @CRLF)         If $pid = -1 Then _SysTrayIconRemove($i, 2)     Next EndIf

Edited by wraithdu, 13 May 2013 - 10:14 PM.

  • MKANET likes this





#2 Melba23

Melba23

    Yes, me!

  • Moderators
  • 15,343 posts

Posted 13 October 2009 - 09:47 AM

wraithdu,

Works fine on Vista with taskbar showing and auto-hidden.

In return, could I ask you a follow-on question?

Do you know of any way to display an auto-hidden taskbar so that the icons are available for clicking, other than by this rather crude method?
Send("{CTRLDOWN}") ; send <ctrl>-<esc> to bring up the Taskbar if hidden Send("{ESC}") Send("{CTRLUP}") Send("{ESC}") ; get rid of the Start Menu to avoid confusion

It came up in a recent topic and I could not find a "programmatic" way of doing it.

M23
StringSize - Automatically size controls to fit text - ExtMsgBox - A user customisable replacement for MsgBox

Toast - Small GUIs which pop out of the Systray - Marquee - Scrolling tickertape GUIs

Scrollbars - Automatically sized scrollbars with a single command - GUIFrame - Subdivide GUIs into many adjustable frames

GUIExtender - Extend and retract multiple sections within a GUI - NoFocusLines - Remove the dotted focus lines from buttons, sliders, radios and checkboxes

ChooseFileFolder - Single and multiple selections from specified path tree structure - - Notify - Small notifications on the edge of the display

RecFileListToArray - An alternative to _FileListToArray with user-defined include/exclude masks, maximum recursion level, sorting and displayed path options

GUIListViewEx - Insert, delete, move, drag and sort ListView items


#3 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 13 October 2009 - 03:19 PM

Hmm, no. You could move the mouse to the bottom of the screen momentarily, or maybe ControlSend() a click to the taskbar window?

#4 ResNullius

ResNullius

    Drink Deep, or Taste Not the Pierian Spring

  • Active Members
  • PipPipPipPipPipPip
  • 1,031 posts

Posted 15 October 2009 - 07:05 AM

This should work on Win2000+, but some testers on XP and Vista would be appreciated.

Example works on XP; haven't tested other functions yet.

#5 jadeiceman

jadeiceman

    Seeker

  • New Members
  • 1 posts

Posted 22 October 2009 - 03:51 PM

Hi, I used your script in Windows 7 x64 Professional, and it clears all the visible system tray icons instead of the dead ones. Do you know what might be happening? I'm new to AutoIt, so maybe I did something wrong with your code? I saved the first one as _SysTray.au3 and the second set of code as Example.au3 and ran Example.au3.

#6 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 23 October 2009 - 07:00 PM

This is not tested or coded for X64. It reads directly from explorer.exe's memory which is going to be different on X64. No big surprise it didn't work correctly.

Edited by wraithdu, 23 October 2009 - 07:39 PM.


#7 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 23 October 2009 - 07:39 PM

Ok, I've updated the UDF for possible X64 compatibility. Someone's gonna have to test that for me though.

#8 JavaAutomater

JavaAutomater

    Seeker

  • Active Members
  • 21 posts

Posted 19 November 2009 - 06:02 AM

A quick update : I just ran the example script in the post and it deleted ALL the notification area icons!

I have 9 icons in the area, all of which are visible and the example script gives me this output:

Count visible tray:  9 index:  8   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  7   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  6   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  5   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  4   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  3   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  2   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  1   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 index:  0   visible:  -3    handle:  -3 pid:  -1    proc:       title:  0       tooltip:  -3 >Exit code: 0    Time: 0.312


This means that _SysTrayIconHandle fails, and I think that _SysTrayGetButtonInfo is failing.

Right away, off the top of my head, I think that ReadProcessMemory etc is failing as I don't have Admin privileges/debug rights.

Any clues?

#9 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 19 November 2009 - 08:25 AM

A quick update : I just ran the example script in the post and it deleted ALL the notification area icons!

Same happened here :), though I have admin rights.

#10 JavaAutomater

JavaAutomater

    Seeker

  • Active Members
  • 21 posts

Posted 19 November 2009 - 09:15 AM

Same happened here :), though I have admin rights.

Hmmm.. thanks for the feedback.

Can you confirm if you have the SeDebugPrivilige ?

I believe this is required for the functions to succeed.

Can the author(s) of this script please have a look into this?

#11 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 19 November 2009 - 09:47 AM

Can you confirm if you have the SeDebugPrivilige ?

Confirmed, all tray-icons deleted, still happens with the example below.

AutoIt         
#NoTrayIcon #include <_SysTray.au3> #include <Process.au3> #include <WinAPI.au3> _GetPrivilege_SEDEBUG() $count = _SysTrayIconCount() ConsoleWrite("Count visible tray:  " & $count & @CRLF) For $i = $count - 1 To 0 Step -1     $handle = _SysTrayIconHandle($i)     $visible = _SysTrayIconVisible($i)     $pid = WinGetProcess($handle)     $name = _ProcessGetName($pid)     $title = WinGetTitle($handle)     $tooltip = _SysTrayIconTooltip($i)     ConsoleWrite("index:  " & $i & @TAB & "visible:  " & $visible & @TAB & "handle:  " & $handle & @TAB & "pid:  " & _                     $pid & @TAB & "proc:  " & $name & @TAB & @TAB & "title:  " & $title & @TAB & @TAB & "tooltip:  " & $tooltip & @CRLF)     If $pid = -1 Then _SysTrayIconRemove($i) Next If @OSVersion = "WIN_7" Then     ConsoleWrite("-====================-" & @CRLF)     $countwin7 = _SysTrayIconCount(2)     ConsoleWrite("Count Win7 overflow area:  " & $countwin7 & @CRLF)     For $i = $countwin7 - 1 To 0 Step -1         $handle = _SysTrayIconHandle($i, 2)         $visible = _SysTrayIconVisible($i, 2)         $pid = WinGetProcess($handle)         $name = _ProcessGetName($pid)         $title = WinGetTitle($handle)         $tooltip = _SysTrayIconTooltip($i, 2)         ConsoleWrite("index:  " & $i & @TAB & "visible:  " & $visible & @TAB & "handle:  " & $handle & @TAB & "pid:  " & _                         $pid & @TAB & "proc:  " & $name & @TAB & @TAB & "title:  " & $title & @TAB & @TAB & "tooltip:  " & $tooltip & @CRLF)         If $pid = -1 Then _SysTrayIconRemove($i, 2)     Next EndIf ; By wraithdu ; http://www.autoitscript.com/forum/index.php?showtopic=88214&view=findpost&p=634408 ; ####################### Below Func is Part of example - Needed to get commandline from more processes. ############ ; ####################### Thanks for this function, wraithdu! (Didn't know it was your.) smile.gif ######################### Func _GetPrivilege_SEDEBUG()     Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes"     Local $count = 1     Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct     Local $TOKEN_ADJUST_PRIVILEGES = 0x20     Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", _WinAPI_GetCurrentProcess(), "dword", $TOKEN_ADJUST_PRIVILEGES, "ptr*", "")     Local $hToken = $call[3]     $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "str", Chr(0), "str", "SeDebugPrivilege", "int64*", "")     ;msgbox(262144,"",$call[3] & " " & _WinAPI_GetLastErrorMessage())     Local $iLuid = $call[3]     Local $TP = DllStructCreate($tagTOKENPRIVILEGES)     Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB"))     DllStructSetData($TP, "PrivilegeCount", $count)     DllStructSetData($LUID, "Luid", $iLuid)     DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED)     $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", Chr(0), "ptr", Chr(0))     Return ($call[0] <> 0) ; $call[0] <> 0 is success EndFunc   ;==>_GetPrivilege_SEDEBUG


#12 JavaAutomater

JavaAutomater

    Seeker

  • Active Members
  • 21 posts

Posted 19 November 2009 - 11:53 AM

KaFu, It now works with a little patch:

http://www.autoitscript.com/forum/index.php?showtopic=105650&view=findpost&p=746750

:)

#13 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 19 November 2009 - 02:17 PM

What version of AutoIt are you using? I guess 'dword_ptr' was introduced in a beta somewhere that you don't have. Good catch Authenticity. I'll change the UDF for safety.

Edited by wraithdu, 19 November 2009 - 02:21 PM.


#14 idbirch

idbirch

    Seeker

  • Active Members
  • 44 posts

Posted 24 November 2009 - 08:14 PM

Ok, I've updated the UDF for possible X64 compatibility. Someone's gonna have to test that for me though.

Thanks for taking the time to update this UDF wraithd, it's extremely useful. I'm running Win7 x64 and some of the functions are't working for me.

_SysTrayIconCount() works OK and returns the correct number of tray icons but when I try to get down to the interesting stuff, nothing works. For example, _SysTrayIconProcesses() returns an array of blank elements and _SysTrayIconTitles() returns 3 zeroes.

#15 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 25 November 2009 - 07:20 AM

I'm not sure what to tell you. What version of AutoIt are you using?

I just tested on my Win7 Pro x64 system with beta 3.3.1.5 and both of those functions work correctly. I tried running from Scite (runs as an x64 process), and compiled as both 32-bit and 64-bit. All 3 return the correct information, both titles and process names. Very simple script to test:
#include <_SysTray.au3> #include <Array.au3> $a = _SysTrayIconTitles() _ArrayDisplay($a) $a = _SysTrayIconProcesses() _ArrayDisplay($a)

Edited by wraithdu, 25 November 2009 - 07:20 AM.


#16 idbirch

idbirch

    Seeker

  • Active Members
  • 44 posts

Posted 25 November 2009 - 10:02 AM

Resolved the problem - I had to copy the UDF from a cached copy of the page yesterday as I was unable to reach autoitscript.com, now that I've re-copied it from the proper page, it's working correctly.

#17 idbirch

idbirch

    Seeker

  • Active Members
  • 44 posts

Posted 25 November 2009 - 10:11 AM

One more question - the reason for using this was to retrieve the tooltip text from the network icon but instead of getting "Network - Internet Access", I'm getting "Network System Icon".

When I hover the mouse over the tray icon, I see "Network - Internet Access" - is there any way to retrieve this text?

Edited by idbirch, 25 November 2009 - 10:12 AM.


#18 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 25 November 2009 - 02:12 PM

You're probably just using the wrong function. See the example I posted. It shows how to get both the icon title and the tooltip.

#19 idbirch

idbirch

    Seeker

  • Active Members
  • 44 posts

Posted 25 November 2009 - 03:55 PM

No, I'm definitely using the right function. Here's the console output for the Win7 x64 network tray icon using your example script:

index: 2 visible: True handle: 0x00000000000101B4 pid: 1796 proc: explorer.exe title: Network Flyout tooltip: Network System Icon

I have no idea where it's getting that Tooltip text from as that's not what appears when I hover over it.

EDIT: Ugh, turns out the Win7 network icon is a bit temperamental at best, the icon's status was no longer updating in my systray when the connection status changed. I rebooted and now the tips are being read correctly.

Edited by idbirch, 25 November 2009 - 04:20 PM.


#20 rogdog

rogdog

    Wayfarer

  • Active Members
  • Pip
  • 59 posts

Posted 24 September 2010 - 03:07 PM

Do you know of any way to display an auto-hidden taskbar so that the icons are available for clicking, other than by this rather crude method?

Send("{CTRLDOWN}") ; send <ctrl>-<esc> to bring up the Taskbar if hidden Send("{ESC}") Send("{CTRLUP}") Send("{ESC}") ; get rid of the Start Menu to avoid confusion
It came up in a recent topic and I could not find a "programmatic" way of doing it.

M23

; locates and right clicks the Icon for this script #include <GuiToolbar.au3> #include <_SysTray.au3> $ToolTipString = 'Autoit - '&@ScriptName $count = _SysTrayIconCount() For $i = 0 to $count - 1     $tooltip = _SysTrayIconTooltip($i)     ConsoleWrite("index:  " & $i & @TAB & "tooltip:  " & $tooltip & @CRLF)     If $tooltip = $ToolTipString then $Index = $i Next $hWnd = ControlGetHandle('[Class:Shell_TrayWnd]', '', '[Class:ToolbarWindow32;Instance:1]') $iCommandID = _GUICtrlToolbar_IndexToCommand($hWnd, $Index) $aRect = _GUICtrlToolbar_GetButtonRect ($hWnd, $iCommandID) ControlClick($hWnd, '', '','Secondary',1,$aRect[0],$aRect[1])

Example code to locate and right click a notification(systray) icon even if the taskbar is hidden.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users