Jump to content

_RefreshSystemTray()


Valik
 Share

Recommended Posts

Here's a function to remove dead icons from the Notification Area (Tray). When an application dies, its icon isn't always removed. The simple solution is to mouse over the icon and it will vanish. Thats pretty much what this function does; it programatically mouses over the tray and removes any dead icons. I used SetCursorPos() from the Windows API because it is far faster than MouseMove(). Its so fast, in fact, that all you should see is a brief flicker of your cursor and the icons vanish.

Requires: Beta build containing DllCall().

; ===================================================================
; _RefreshSystemTray($nDealy = 1000)
;
; Removes any dead icons from the notification area.
; Parameters:
;   $nDelay - IN/OPTIONAL - The delay to wait for the notification area to expand with Windows XP's
;       "Hide Inactive Icons" feature (In milliseconds).
; Returns:
;   Sets @error on failure:
;       1 - Tray couldn't be found.
;       2 - DllCall error.
; ===================================================================
Func _RefreshSystemTray($nDelay = 1000)
; Save Opt settings
    Local $oldMatchMode = Opt("WinTitleMatchMode", 4)
    Local $oldChildMode = Opt("WinSearchChildren", 1)
    Local $error = 0
    Do; Pseudo loop
        Local $hWnd = WinGetHandle("classname=TrayNotifyWnd")
        If @error Then
            $error = 1
            ExitLoop
        EndIf

        Local $hControl = ControlGetHandle($hWnd, "", "Button1")
        
    ; We're on XP and the Hide Inactive Icons button is there, so expand it
        If $hControl <> "" And ControlCommand($hWnd, "", $hControl, "IsVisible") Then 
            ControlClick($hWnd, "", $hControl)
            Sleep($nDelay)
        EndIf
        
        Local $posStart = MouseGetPos()
        Local $posWin = WinGetPos($hWnd)    
        
        Local $y = $posWin[1]
        While $y < $posWin[3] + $posWin[1]
            Local $x = $posWin[0] 
            While $x < $posWin[2] + $posWin[0]
                DllCall("user32.dll", "int", "SetCursorPos", "int", $x, "int", $y)
                If @error Then
                    $error = 2
                    ExitLoop 3; Jump out of While/While/Do
                EndIf
                $x = $x + 8
            WEnd
            $y = $y + 8
        WEnd
        DllCall("user32.dll", "int", "SetCursorPos", "int", $posStart[0], "int", $posStart[1])
    ; We're on XP so we need to hide the inactive icons again.
        If $hControl <> "" And ControlCommand($hWnd, "", $hControl, "IsVisible") Then 
            ControlClick($hWnd, "", $hControl)
        EndIf
    Until 1
    
; Restore Opt settings
    Opt("WinTitleMatchMode", $oldMatchMode)
    Opt("WinSearchChildren", $oldChildMode)
    SetError($error)
EndFunc; _RefreshSystemTray()

Edit: Code updated to support Windows XP's "Hide Inactive Icons" feature.

Edit 2: Removed $class variable and all references to it; $hWnd is now properly used ($class was a leftover from debugging the "Hide Inactive Icons" feature). There shouldn't be a functional change to the code, however.

Edit 3: Added optional parameter to specify the delay to give to Windows XP's "Hide Inactive Icons" feature. There is an animation during the expansion of the notification area. The default pause is 1 second, however, passing a new time (in milliseconds) can alter the delay if 1 second isn't enough.

Edited by Valik
Link to comment
Share on other sites

Some logic necessary off the top of my head:

  • Check for the existence of "Button2" in Shell_TrayWnd (This is the button to expand).
  • Do a click on that button if present (This call would go after getting the mouse position but before getting the window position)
  • After its expanded, make the WinGetPos() call.
  • All other code should be identical.
I would think those changes should work. They are, however, untested. Later I'll test them and post the results.
Link to comment
Share on other sites

Nicely done Valik. I probably will be able to find a use for this as I am constantly shutting down programs while 'cleaning' peoples PC's and that would be nice to save me the trouble.

JS

AutoIt Links

File-String Hash Plugin Updated! 04-02-2008 Plugins have been discontinued. I just found out.

ComputerGetInfo UDF's Updated! 11-23-2006

External Links

Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)

Link to comment
Share on other sites

Here's a function to remove dead icons from the Notification Area (Tray). When an application dies, its icon isn't always removed. The simple solution is to mouse over the icon and it will vanish. Thats pretty much what this function does; it programatically mouses over the tray and removes any dead icons. I used SetCursorPos() from the Windows API because it is far faster than MouseMove(). Its so fast, in fact, that all you should see is a brief flicker of your cursor and the icons vanish.

Requires: Beta build containing DllCall().

:D Hello Valik it wörks nice for me thx you for made this script :lol:

I have adde this on my automated Pc cleaner tool for my pc) :idiot:

Link to comment
Share on other sites

Excellent work!

Does this work on Windows 98?  (I just tried under Virtual PC 2004, and the tray icons did not seem to refresh)

<{POST_SNAPBACK}>

I have no clue, I only have XP to test on.

I also updated the top post. There shouldn't be a functional change, I only cleaned up the code a bit.

Link to comment
Share on other sites

  • 4 weeks later...
  • 3 years later...

I know this is old and I just started using it (shame). It seems to be working fine and in the script I'm using it in there would be no difference but I spotted something that makes no sense, at least to me. Perhaps you could clarify this?

Existing

; Save Opt settings
    Local $oldMatchMode = Opt("WinTitleMatchMode", 4)
    Local $oldChildMode = Opt("WinSearchChildren", 1)

Should this not be as follows?

; Save Opt settings
   ;; Read the existing values
    Local $oldMatchMode = Opt("WinTitleMatchMode")
    Local $oldChildMode = Opt("WinSearchChildren")
   ;;Set the new values
    Opt("WinTitleMatchMode", 4)
    Opt("WinSearchChildren", 1)

If not, then why not? Like I said, in my current script it doesn't seem to affect anything, just curious.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

The help file states that the return value for Opt() is...

This means you can store the old value and set the new value in the same line.

Thank you. That means that I've been doing it the hard way all this time. Oh well, that's not unusual either. :)

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

  • 1 year later...

Updated the top post with slightly changed code. It should better support XP's "Hide Inactive Icons" feature. See Edit 3 in the top post for details.

Thanks for the function. On both Windows 7 and Vista64 I use a double height Taskbar. I notice that sometimes it cleans the dead icon and sometimes not. I have my settings to always show all icons, so it's not due to being hidden. I'm wondering if the double height might be the trouble?

I notice the tray area action and it seems that often the missed dead icon is moved to the 2nd row, then moves back to the top. Maybe it's being missed in the shuffle due to task tray dynamic resizing.

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

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