Jump to content

Recommended Posts

  • Moderators
Posted (edited)

Any way to refresh all trayicons to remove dead once form the tryiconarea ?

I didn't use the findtraybarwindow function wraithdu provides, to be honest, I didn't see it until I had already written this out.

This is similar to something I used in the past.

#include <WinAPI.au3>
#include <WindowsConstants.au3>

#cs
; un-comment to see example run and clear systray
_systray_clearDead()
#ce

Func _systray_clearDead($v_tray = "", $v_title = "")

    Local $h_systray = $v_tray

    If Not IsHWnd($h_systray) Then
        If StringLen($v_tray) = 0 Then
            $h_systray = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", _
                "[CLASS:ToolbarWindow32; INSTANCE:1]")
        ElseIf IsString($v_tray) Then
            If $v_title Then
                $h_systray = ControlGetHandle($v_title, "", $v_tray)
            Else
                $h_systray = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", $v_tray)
            EndIf
        EndIf
        If Not IsHWnd($h_systray) Then Return SetError(1, 0, 0)
    EndIf

    Local $a_pos = WinGetPos($h_systray)
    If Not IsArray($a_pos) Then Return SetError(2, 0, 0)

    Local $i_midy = ($a_pos[1] - $a_pos[3]) / 2
    Local $i_width = ($a_pos[0] - $a_pos[2])
    Local $i_word

    For $i = $i_width To 0 Step -4
        $i_word = _WinAPI_MakeQWord($i, $i_midy)
        _WinAPI_PostMessage($h_systray, $WM_MOUSEMOVE, 0, $i_word)
    Next
    
    Return 1
EndFunc
Edited by SmOke_N
reversed for/next array

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Posted

I've used this...but I will check out your version SmOke_N.

Func _Taskbar_Refresh() ; By rasim - http://www.autoitscript.com/forum/topic/66629-systemtray-refresh/
    Local Const $hTaskBar = _WinAPI_FindWindow('Shell_TrayWnd', '')
    Local Const $hParent = ControlGetHandle($hTaskBar, '', 'TrayNotifyWnd1')
    Local Const $hWnd = ControlGetHandle($hParent, '', 'ToolbarWindow321')
    Local Const $tWinRect = _WinAPI_GetWindowRect($hWnd)
    Local Const $aMouseGetPos = MouseGetPos()
    Local Const $iLeft = DllStructGetData($tWinRect, 'Left')
    Local Const $iRight = DllStructGetData($tWinRect, 'Right')
    Local Const $iTop = DllStructGetData($tWinRect, 'Top')
    For $i = $iLeft To $iRight
        MouseMove($i, $iTop, 0)
    Next
    MouseMove($aMouseGetPos[0], $aMouseGetPos[1], 0)
EndFunc   ;==>_Taskbar_Refresh

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

  • Moderators
Posted (edited)

I've used this...but I will check out your version SmOke_N.

Valik did something similar years ago like what you provided. I used to use mine in a ,maintenance program I had on a scheduler. This made a "mousemove" too obtrusive in case I was trying to use it for my own benefit, even if it tried to go back to the original position.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Posted

Any way to refresh all trayicons to remove dead once form the tryiconarea ?

My example in the 1st post already does this, see the lines

If $pid = -1 Then _SysTrayIconRemove()

However I've noticed even though it works in Win7, it may create an empty space at the right edge of the sys tray until you expand the overflow window. I have no idea why.

Posted (edited)

However I've noticed even though it works in Win7, it may create an empty space at the right edge of the sys tray until you expand the overflow window. I have no idea why.

for the removal of icons :)... two post above that I've also posted a function to hide / unhide systray icons.

Edited by KaFu
Posted

I didn't use the findtraybarwindow function wraithdu provides, to be honest, I didn't see it until I had already written this out.

This is similar to something I used in the past.

#include <WinAPI.au3>
#include <WindowsConstants.au3>

#cs
; un-comment to see example run and clear systray
_systray_clearDead()
#ce

Func _systray_clearDead($v_tray = "", $v_title = "")

    Local $h_systray = $v_tray

    If Not IsHWnd($h_systray) Then
        If StringLen($v_tray) = 0 Then
            $h_systray = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", _
                "[CLASS:ToolbarWindow32; INSTANCE:1]")
        ElseIf IsString($v_tray) Then
            If $v_title Then
                $h_systray = ControlGetHandle($v_title, "", $v_tray)
            Else
                $h_systray = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", $v_tray)
            EndIf
        EndIf
        If Not IsHWnd($h_systray) Then Return SetError(1, 0, 0)
    EndIf

    Local $a_pos = WinGetPos($h_systray)
    If Not IsArray($a_pos) Then Return SetError(2, 0, 0)

    Local $i_midy = ($a_pos[1] - $a_pos[3]) / 2
    Local $i_width = ($a_pos[0] - $a_pos[2])
    Local $i_word

    For $i = $i_width To 0 Step -4
        $i_word = _WinAPI_MakeQWord($i, $i_midy)
        _WinAPI_PostMessage($h_systray, $WM_MOUSEMOVE, 0, $i_word)
    Next
    
    Return 1
EndFunc

I've used this...but I will check out your version SmOke_N.

Func _Taskbar_Refresh() ; By rasim - http://www.autoitscript.com/forum/topic/66629-systemtray-refresh/
    Local Const $hTaskBar = _WinAPI_FindWindow('Shell_TrayWnd', '')
    Local Const $hParent = ControlGetHandle($hTaskBar, '', 'TrayNotifyWnd1')
    Local Const $hWnd = ControlGetHandle($hParent, '', 'ToolbarWindow321')
    Local Const $tWinRect = _WinAPI_GetWindowRect($hWnd)
    Local Const $aMouseGetPos = MouseGetPos()
    Local Const $iLeft = DllStructGetData($tWinRect, 'Left')
    Local Const $iRight = DllStructGetData($tWinRect, 'Right')
    Local Const $iTop = DllStructGetData($tWinRect, 'Top')
    For $i = $iLeft To $iRight
        MouseMove($i, $iTop, 0)
    Next
    MouseMove($aMouseGetPos[0], $aMouseGetPos[1], 0)
EndFunc ;==>_Taskbar_Refresh

I tried both scripts (used as they where posted above on Win 7 x64) but non of them removed the dead trayicons.

(to make it clear: I am talking about the trayicons which are in the "out faded area" (what ever its called in english))

btw should I give special parameters to the function "_systray_clearDead" !? - Which ?

  • 1 month later...
Posted (edited)

Hey KaFu, Can you be more specific on how your "fix" applies to wraithdu's script? Thanks!

By the way, there are still some missing information as WhiteLion has mentioned in previous post ...

Edited by power1power1
Posted (edited)

A big thanks to KaFu for the Shell_NotifyIcon functions. I've integrated that method into my UDF for the Hide/Remove functions. It works well on Win7 for the dead icons as well. I've been meaning to revisit those functions to implement that method for quite some time, but I've been really lazy about it.

I've done some general code cleanup and better error reporting as well. Beware there are some probably script breaking changes if you directly used the _SysTrayGetButtonInfo function. Try the example for the dead icons issue.

Edited by wraithdu
Posted (edited)

Hi wraithdu, Thanks a lot for updating the scripts. It seems the issue of dead icons has gone away for me as well and I have Windows 8. Thanks again!

Edited by power1power1
  • 4 months later...
Posted

I consider myself a relative beginner. I've written a few scripts here and there to help with a few things, but that's about it. So this may be a really stupid suggestion on my part, but couldn't you "OS-proof" the UDF by doing something like this for the default function arguments:

If @OSVersion = "WIN_VISTA" Or @OSVersion = "WIN_2003" Or @OSVersion = "WIN_XP" Or @OSVersion = "WIN_XPe" Or @OSVersion = "WIN_2000" Then
    $myos = 1
Else
    $myos = 2
EndIf

I have a utility script that I wrote that runs on various machines, so I ended up doing that in my script and then using your UDF like so:

If @OSVersion = "WIN_VISTA" Or @OSVersion = "WIN_2003" Or @OSVersion = "WIN_XP" Or @OSVersion = "WIN_XPe" Or @OSVersion = "WIN_2000" Then
    $myos = 1
Else
    $myos = 2
EndIf

$count = _SysTrayIconCount($myos)
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($myos) <> -1 Then
    ConsoleWrite("-====================-" & @CRLF)
    $countwin7 = _SysTrayIconCount($myos)
    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

It works like a peach on both WinXP and Win7.

I would think you could basically do the same thing in the UDF to set the default, but still allow the user to override the value if they choose.

Like I said, sorry if I'm way off-base here.

Thanks for this great UDF regardless. I have a script that runs in a constant loop (it's polling for data regularly) and another script that needs to kill that process once a day before it can run, so I get stuck with multiple tray icons for the first script since it's not exiting gracefully. This UDF has eliminated that problem for me.

  • 1 year later...
  • 1 year later...
  • 4 months later...
Posted

I need some help. First is it possible to do a right click on an hidden overflow icon?

I searched but can't confirm it or a thread to show how. My PC is a win7 x64.

My current workaround is unhide tray icons by registry, reload explorer.exe to show all icons, match the tooltips, right clicks and do my task, update registry to hide it, and reload explorer. 

 

 

 

 

  • 10 months later...
Posted

This isn't working on 64-bit Windows 10.  For example, when I call _SysTrayIconCount( 2 ) [2 = Win 7+], I always get zero, whereas there are 10 of them showing.  I also tried using the functions provided in this thread: Manipulate system tray program? from 2014, but it was hardly better. It reported only 1 icon.

What I want to do is to bring up the GUI window for something running in the system tray that doesn't have a GUI until the tray icon is clicked.  Curiously, a call to WinExists() always reports the GUI window does exist, even though it actually doesn't. Thus when I try to activate that window with WinActivate(), the GUI never appears!

How can this be done under 64-bit Windows 10, please?

Thanks!

 

 

Posted
On 2/23/2018 at 11:51 AM, Deye said:

Probably getting the wrong handle on win10  ( wrong instance number )

$hSysTray = ControlGetHandle("[Class:Shell_TrayWnd]", "", "[Class:ToolbarWindow32;Instance:" & (@OSVersion = "WIN_10" ? 3 : 1) & "]")

 

Many thanks indeed, kind Deye!  I changed this UDF as per your code and modified it to accept an iWin value of 3 to represent Windows 10 ("2" for 7+ simply won't work under Win 10).  After doing so, the icon count and icon title lists and so forth are working correctly, thanks to you!

I'm continuing to try to modify the UDF to fully support Windows 10 and it's new NOTIFYICONDATA struct and all the other "system tray"-related changes made after Windows 7 (though I don't have any Windows 8 machines, so I don't know if that OS included these changes).  This is certainly stretching my AutoIt / Windows knowledge!  Perhaps you might be willing to examine the resulting code when I'm finished (which won't be very soon, I'm afraid...)

 

  • 7 months later...
Posted

 

On 2/25/2018 at 7:00 AM, Mbee said:

I'm continuing to try to modify the UDF to fully support Windows 10

@Mbee can you please share your update version? I hope @wraithdu will update the original UDF soon or later.

Posted (edited)

The following example should be "universal"  because it checks ALL existing/valid instances on both hidden and visible icons. So it should be working on all past and future Windows vers unless the class(es) name will change. Note: there are some programs using a no-standard instance, but with my method you can catch those icons as well.
 

#NoTrayIcon
#include <GuiToolBar.au3>

Local $VisibleIcons
Local $HiddenIcons
Local $Instance

; Find systray handle for "User Promoted Notification Area"
$Instance = 0
While 1
    $Instance = $Instance + 1
    Local $hSysTray_Handle = ControlGetHandle("[Class:Shell_TrayWnd]", "", "[Class:ToolbarWindow32;Instance:" & $Instance & "]")
    If @error Then ExitLoop

    If Not @Compiled Then ConsoleWrite("VISIBLE at Istance #" & $Instance & ":" & @CRLF)

    Local $iSysTray_ButCount = _GUICtrlToolbar_ButtonCount($hSysTray_Handle) ; Get vidible systray icon count

    For $iSystray_ButtonNumber = 0 To $iSysTray_ButCount - 1
        $text = _GUICtrlToolbar_GetButtonText($hSysTray_Handle, $iSystray_ButtonNumber)
        If Not @Compiled Then ConsoleWrite($text & @CRLF)
    Next
    If Not @Compiled Then ConsoleWrite(@CRLF)
WEnd

; Find systray handle for "Overflow Notification Area" i.e. hidden icons
$Instance = 0
While 1
    $Instance = $Instance + 1
    Local $hSysTray_Handle_Hidden = ControlGetHandle("[Class:NotifyIconOverflowWindow]", "", "[Class:ToolbarWindow32;Instance:" & $Instance & "]")
    If @error Then ExitLoop

    If Not @Compiled Then ConsoleWrite("HIDDEN at Istance #" & $Instance & ":" & @CRLF)

    $iSysTray_ButCount = _GUICtrlToolbar_ButtonCount($hSysTray_Handle_Hidden) ; Get hidden systray icon count

    For $iSystray_ButtonNumber = 0 To $iSysTray_ButCount - 1
        $text = _GUICtrlToolbar_GetButtonText($hSysTray_Handle_Hidden, $iSystray_ButtonNumber)
        If Not @Compiled Then ConsoleWrite($text & @CRLF)
    Next
WEnd

Exit

 

Edited by masvil
  • 8 months later...
Posted (edited)

Just adding example for removing systray icon after explorer restart:

;www.autoitscript.com/forum/topic/134538-get-systray-icons-solved

#NoTrayIcon
#RequireAdmin
#include <Constants.au3>
#include <GUIConstants.au3>
#include <ScrollBarsConstants.au3>
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIMem.au3>
#include <WinAPIHObj.au3>
#include <WinAPIShellEx.au3>
#include <WinAPISysWin.au3>
#include <GuiToolbar.au3>
#include <Process.au3>
#include <Array.au3>

Opt('SendKeyDelay', 0)
Opt('MouseClickDelay', 0)
Opt('SendKeyDownDelay', 0)
Opt('MouseClickDownDelay', 0)
Opt('MouseClickDragDelay', 0)
Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)

$SystrayIconsInfo = _GetAllSystrayIconsInfo()
If IsArray($SystrayIconsInfo) Then _ArrayDisplay($SystrayIconsInfo)

_RemoveSystrayIcon('process', 0, '', 'explorer.exe', 1225)
_RegisterWinEventHook($EVENT_OBJECT_CREATE, $EVENT_OBJECT_LOCATIONCHANGE)
If @error Then
   MsgBox($MB_OK, 'Info', 'Failed to register event hook.')
   Exit
EndIf

While 1
   Sleep(1000)
WEnd

Func _RegisterWinEventHook($sEventMin, $sEventMax, $sProcessPid = 0, $sCallbackFunc = '_WinEventProc')
   $sWinEventProc = DllCallbackRegister($sCallbackFunc, 'none', 'ptr;dword;hwnd;long;long;dword;dword')
   $sWinEventHook = _WinAPI_SetWinEventHook($sEventMin, $sEventMax, DllCallbackGetPtr($sWinEventProc), $sProcessPid)
   Switch $sWinEventHook
   Case 0
      Return SetError(1, 0, 0)
   Case Else
      Return SetExtended($sWinEventProc, $sWinEventHook)
   EndSwitch
EndFunc

Func _WinEventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
   If not IsDeclared('__SystrayIconsCountList') Then Global $__SystrayIconsCountList[3][2] = [['Shell_TrayWnd', 'NotifyIconOverflowWindow'], [0, 0], [False, False]]
   Switch $iEvent
   Case $EVENT_OBJECT_CREATE, $EVENT_OBJECT_LOCATIONCHANGE
      If ($iEvent = $EVENT_OBJECT_CREATE and $iObjectID = $OBJID_CLIENT) or ($iEvent = $EVENT_OBJECT_LOCATIONCHANGE and $iObjectID = $OBJID_WINDOW) Then
         If _WinAPI_GetClassName($hWnd) = 'ToolbarWindow32' Then
            $sParentWndClass = _WinAPI_GetClassName(_WinAPI_GetAncestor($hWnd, $GA_ROOT))
            Switch $sParentWndClass
            Case 'Shell_TrayWnd', 'NotifyIconOverflowWindow'
               $sParentWndIndex = 0
               If $sParentWndClass = 'NotifyIconOverflowWindow' Then $sParentWndIndex = 1
               $sSystrayIconsCount = _GUICtrlToolbar_ButtonCount($hWnd)
               If $sSystrayIconsCount < $__SystrayIconsCountList[1][$sParentWndIndex] Then $__SystrayIconsCountList[1][$sParentWndIndex] = 0
               If $sSystrayIconsCount <> $__SystrayIconsCountList[1][$sParentWndIndex] Then
                  $__SystrayIconsCountList[1][$sParentWndIndex] = $sSystrayIconsCount
                  $__SystrayIconsCountList[2][$sParentWndIndex] = False
               Else
                  If $iEvent = $EVENT_OBJECT_LOCATIONCHANGE and $__SystrayIconsCountList[1][$sParentWndIndex] > 0 and $__SystrayIconsCountList[2][$sParentWndIndex] = False Then
                     $__SystrayIconsCountList[2][$sParentWndIndex] = True
                     _RemoveSystrayIcon('process', 0, '', 'explorer.exe', 1225)
                  EndIf
               EndIf
            EndSwitch
         EndIf
      EndIf
   EndSwitch
EndFunc

Func _GetAllSystrayIconsInfo($sSystrayWndHandle = 0)
   $sSystrayIconsTrayDataDllStructList = _GetSystrayIconsTrayDataDllStructList($sSystrayWndHandle)
   If @error Then Return SetError(1, @error, '')
   Local $sSystrayIconsInfoList[UBound($sSystrayIconsTrayDataDllStructList)][3] = [['Icon Text', 'Process Name', 'Icon Uid']]
   For $i = 1 to UBound($sSystrayIconsTrayDataDllStructList) - 1
      $tTrayData = $sSystrayIconsTrayDataDllStructList[$i][2]
      $sSystrayIconsInfoList[$i][0] = _GUICtrlToolbar_GetButtonText($sSystrayIconsTrayDataDllStructList[$i][0], $sSystrayIconsTrayDataDllStructList[$i][1])
      $sSystrayIconsInfoList[$i][1] = _ProcessGetName(WinGetProcess(DllStructGetData($tTrayData, 'hWnd')))
      $sSystrayIconsInfoList[$i][2] = DllStructGetData($tTrayData, 'uID')
   Next
   Return $sSystrayIconsInfoList
EndFunc

Func _RemoveSystrayIcon($sMode, $sSystrayWndHandle = 0, $sSystrayIconTitle = '', $sProcessName = '', $sSystrayIconUid = 0)
   ;$sSystrayIconTitle contains list of full or partial icon titles (with | as delimiter) related to wanted systray icon
   ;$sMode values: title or process
   If $sMode <> 'title' and $sMode <> 'process' Then Return SetError(1, 0, False)
   If $sProcessName = 'explorer.exe' and not WinExists('[CLASS:PNIHiddenWnd]') Then Return SetError(2, 0, False)
   $sSystrayIconTrayDataInfoList = _GetSystrayIconTrayDataInfo($sMode, $sSystrayWndHandle, $sSystrayIconTitle, $sProcessName, $sSystrayIconUid)
   If @error Then Return SetError(3, @error, False)
   $tTrayData = $sSystrayIconTrayDataInfoList[2]
   If $sProcessName = 'explorer.exe' Then
      $sFuncReturn = _GUICtrlToolbar_DeleteButton($sSystrayIconTrayDataInfoList[0], $sSystrayIconTrayDataInfoList[1])
   Else
      $tNotifyIconData = DllStructCreate($tagNOTIFYICONDATA)
      DllStructSetData($tNotifyIconData, 'Size', DllStructGetSize($tNotifyIconData))
      DllStructSetData($tNotifyIconData, 'hWnd', DllStructGetData($tTrayData, 'hWnd'))
      DllStructSetData($tNotifyIconData, 'ID', DllStructGetData($tTrayData, 'uID'))
      $sFuncReturn = _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNotifyIconData)
   EndIf
   If $sFuncReturn = False Then Return SetError(4, 0, False)
   If $sProcessName = 'explorer.exe' Then
      If @TrayIconVisible = 1 Then
         TraySetState($TRAY_ICONSTATE_HIDE)
         TraySetState($TRAY_ICONSTATE_SHOW)
      Else
         TraySetState($TRAY_ICONSTATE_SHOW)
         TraySetState($TRAY_ICONSTATE_HIDE)
      EndIf
   EndIf
   Return True
EndFunc

Func _GetSystrayIconTrayDataInfo($sMode, $sSystrayWndHandle = 0, $sSystrayIconTitle = '', $sProcessName = '', $sSystrayIconUid = 0)
   ;$sSystrayIconTitle contains list of full or partial icon titles (with | as delimiter) related to wanted systray icon
   ;$sMode values: title or process
   Local $sSystrayIconTrayDataInfoList[3]
   If $sMode <> 'title' and $sMode <> 'process' Then Return SetError(1, 0, '')
   $sSystrayIconsTrayDataDllStructList = _GetSystrayIconsTrayDataDllStructList($sSystrayWndHandle)
   If @error Then Return SetError(2, @error, '')
   $sMatchFound = False
   For $i = 1 to UBound($sSystrayIconsTrayDataDllStructList) - 1
      $tTrayData = $sSystrayIconsTrayDataDllStructList[$i][2]
      Switch $sMode
      Case 'title'
         $sSystrayIconTitleList = StringSplit($sSystrayIconTitle, '|', $STR_ENTIRESPLIT)
         $sSystrayIconText = _GUICtrlToolbar_GetButtonText($sSystrayIconsTrayDataDllStructList[$i][0], $sSystrayIconsTrayDataDllStructList[$i][1])
         For $j = 1 to $sSystrayIconTitleList[0]
            If StringInStr($sSystrayIconText, $sSystrayIconTitleList[$j]) Then
               $sMatchFound = True
               ExitLoop
            EndIf
         Next
      Case 'process'
         If _ProcessGetName(WinGetProcess(DllStructGetData($tTrayData, 'hWnd'))) = $sProcessName and DllStructGetData($tTrayData, 'uID') = $sSystrayIconUid Then $sMatchFound = True
      EndSwitch
      If $sMatchFound = True Then
         $sSystrayIconTrayDataInfoList[0] = $sSystrayIconsTrayDataDllStructList[$i][0]
         $sSystrayIconTrayDataInfoList[1] = $sSystrayIconsTrayDataDllStructList[$i][1]
         $sSystrayIconTrayDataInfoList[2] = $tTrayData
         ExitLoop
      EndIf
   Next
   If $sMatchFound = False Then Return SetError(3, 0, '')
   Return $sSystrayIconTrayDataInfoList
EndFunc

Func _GetSystrayIconsTrayDataDllStructList($sSystrayWndHandle = 0)
   Local $sReadBytes
   Local $sSystrayIconsTrayDataDllStructList[1][3] = [['Systray toolbar handle', 'Icon command identifier', 'TrayData DllStruct']]
   If @OSBuild < 7600 or IsHWnd($sSystrayWndHandle) or RegRead('HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer', 'EnableAutoTray') = '0' Then
      $sSystrayWndCount = 1
   Else
      $sSystrayWndCount = 2
   EndIf
   $sProcessHandle = _WinAPI_OpenProcess(BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ), False, WinGetProcess(WinGetHandle('[CLASS:Shell_TrayWnd]')), True)
   If $sProcessHandle = 0 Then Return SetError(1, 0, '')
   $sAllSystrayIconsCount = 0
   For $i = 1 to $sSystrayWndCount
      If IsHWnd($sSystrayWndHandle) Then
         $sSystrayToolbarHandle = _GetSystrayToolbarHandle($sSystrayWndHandle)
      Else
         Switch $i
         Case 1
            $sSystrayToolbarHandle = _GetSystrayToolbarHandle(WinGetHandle('[CLASS:Shell_TrayWnd]'))
         Case 2
            $sSystrayToolbarHandle = _GetSystrayToolbarHandle(WinGetHandle('[CLASS:NotifyIconOverflowWindow]'))
         EndSwitch
      EndIf
      If IsHWnd($sSystrayToolbarHandle) Then
         $sSystrayIconsCount = _GUICtrlToolbar_ButtonCount($sSystrayToolbarHandle)
         If $sSystrayIconsCount > 0 Then
            ReDim $sSystrayIconsTrayDataDllStructList[UBound($sSystrayIconsTrayDataDllStructList) + $sSystrayIconsCount][3]
            For $j = 0 to $sSystrayIconsCount - 1
               $sSystrayIconCommandId = _GUICtrlToolbar_IndexToCommand($sSystrayToolbarHandle, $j)
               $sSystrayIconParam = _GUICtrlToolbar_GetButtonParam($sSystrayToolbarHandle, $sSystrayIconCommandId)
               $tTrayData = DllStructCreate('hwnd hWnd;uint uID;uint uCallbackMessage;dword Reserved[2];ptr hIcon')
               _WinAPI_ReadProcessMemory($sProcessHandle, $sSystrayIconParam, DllStructGetPtr($tTrayData), DllStructGetSize($tTrayData), $sReadBytes)
               $sAllSystrayIconsCount +=1
               $sSystrayIconsTrayDataDllStructList[$sAllSystrayIconsCount][0] = $sSystrayToolbarHandle
               $sSystrayIconsTrayDataDllStructList[$sAllSystrayIconsCount][1] = $sSystrayIconCommandId
               $sSystrayIconsTrayDataDllStructList[$sAllSystrayIconsCount][2] = $tTrayData
            Next
         EndIf
      EndIf
   Next
   _WinAPI_CloseHandle($sProcessHandle)
   ReDim $sSystrayIconsTrayDataDllStructList[$sAllSystrayIconsCount + 1][3]
   If UBound($sSystrayIconsTrayDataDllStructList) - 1 = 0 Then Return SetError(2, 0, '')
   Return $sSystrayIconsTrayDataDllStructList
EndFunc

Func _GetSystrayToolbarHandle($sSystrayWndHandle)
   Switch _WinAPI_GetClassName($sSystrayWndHandle)
   Case 'Shell_TrayWnd'
      If @OSBuild < 10240 Then
         Return ControlGetHandle($sSystrayWndHandle, '', '[CLASS:ToolbarWindow32; INSTANCE:1]')
      Else
         Return ControlGetHandle($sSystrayWndHandle, '', '[CLASS:ToolbarWindow32; INSTANCE:3]')
      EndIf
   Case 'NotifyIconOverflowWindow'
      Return ControlGetHandle($sSystrayWndHandle, '', '[CLASS:ToolbarWindow32; INSTANCE:1]')
   Case Else
      Return SetError(1, 0, 0)
   EndSwitch
EndFunc

 

Systray Icons Remover.au3

Edited by kosamja

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...