Jump to content
Sign in to follow this  
Valik

_RefreshSystemTray()

Recommended Posts

Valik

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
  • Like 1

Share this post


Link to post
Share on other sites
this-is-me

Could this be modded to take into account XP's automatic hiding of icons? Sometimes the "dead" icons are also hidden.


Who else would I be?

Share this post


Link to post
Share on other sites
Valik

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.

Share this post


Link to post
Share on other sites
Valik

Could this be modded to take into account XP's automatic hiding of icons? Sometimes the "dead" icons are also hidden.

<{POST_SNAPBACK}>

I updated the code in the top post, should work now.

Share this post


Link to post
Share on other sites
Nova

Very nice...... I expected the cursor to become un-usable for at least a second but that really is lightning fast.

Im sure this function will come in very usful, tnx for sharing it.

Share this post


Link to post
Share on other sites
this-is-me

Thanks, Valik.


Who else would I be?

Share this post


Link to post
Share on other sites
killaz219

Wow, very good.

I havn't seen a Valik script in a while..

Share this post


Link to post
Share on other sites
JSThePatriot

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)

Share this post


Link to post
Share on other sites
DirtyBanditos

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:

Share this post


Link to post
Share on other sites
SlimShady

Awesome! It does work! :P

This is definitely useful.

Share this post


Link to post
Share on other sites
Valik

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.

Share this post


Link to post
Share on other sites
Valik

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.

Share this post


Link to post
Share on other sites
MHz

Thankyou Valik.

Will be a nice addition to my include folder. :lmao:

Share this post


Link to post
Share on other sites
GEOSoft

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!"

Share this post


Link to post
Share on other sites
big_daddy

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

Returns the value of the previous setting for the option.

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

Share this post


Link to post
Share on other sites
GEOSoft

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!"

Share this post


Link to post
Share on other sites
MilesAhead

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.

Share this post


Link to post
Share on other sites
wraithdu

Try my modified UDF HERE and see if it works for you.

Share this post


Link to post
Share on other sites
MilesAhead

Try my modified UDF HERE and see if it works for you.

Thanks for the reply. I tried calling the refresh function twice with a little Sleep() between. So far it seems to work every time. I'm only using it for a kludge to launch and close a browser and download manager together. It's ok if it looks a bit clunky. :)

Share this post


Link to post
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
Sign in to follow this  

×