Click to See Complete Forum and Search --> : Updating/Refreshing the system tray


leojose
November 30th, 2005, 10:00 AM
Hi all,

How do I refresh the system tray programmatically? I noticed that one of the applications I run, creates an icon in the system tray. But when it shuts down, it fails to remove it. Each time I start and stop the application, it leaves a new icon on the tray!...which makes the tray a bit of a mess.
But if I move my mouse over the tray, the icons vanish. I believe it happens so because the system tray window refreshes itself when a mouse moves over it. Now I would like to make that happen without any mouse activity.

Thanks

wildfrog
November 30th, 2005, 10:27 AM
How do I refresh the system tray programmatically?Now I would like to make that happen without any mouse activity.
You can locate the window (Shell_TrayWnd/TrayNotifyWnd) using FindWindow/FindWindowEx and then send alot of WM_MOUSEMOVE message to that windows (ok, not randomly but use some logics so that every icon is hit aleast once).

- petter

ovidiucucu
November 30th, 2005, 11:33 AM
What means "when it shuts down, it fails to remove it"? Does your application call Shell_NotifyIcon with NIM_DELETE when is closed?
Sample function below can be called for example from WM_DESTROY message handler:
void RemoveTaskbarIcon(HWND hWnd, UINT nID)
{
DWORD dwMessage = NIM_DELETE;
NOTIFYICONDATA nid;

nid.cbSize = sizeof(NOTIFYICONDATA);
nid.uID = nID;
nid.hWnd = hWnd;

Shell_NotifyIcon(dwMessage, &nid);
}

leojose
December 2nd, 2005, 02:29 AM
You can locate the window (Shell_TrayWnd/TrayNotifyWnd) using FindWindow/FindWindowEx and then send alot of WM_MOUSEMOVE message to that windows (ok, not randomly but use some logics so that every icon is hit aleast once).
It quite explains what I need to do...a little complex though :rolleyes: Alternately can I just re-paint the window or something like that?


What means "when it shuts down, it fails to remove it"? Does your application call Shell_NotifyIcon with NIM_DELETE when is closed?
actually it's an external application that I don't have any control over. I will but be informed when its shutdown and so I can take some actions to 'refresh' the system tray.

golanshahar
December 2nd, 2005, 02:51 AM
It quite explains what I need to do...a little complex though :rolleyes: Alternately can I just re-paint the window or something like that?


its not that complex ;)

look at this code:


HWND g_hToobarTray = 0;
BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lParam )
{
char szClass[MAX_PATH]={0};
::GetClassName(hwnd,szClass,sizeof(szClass));
if ( strcmp(szClass,"ToolbarWindow32") == 0 )
{
g_hToobarTray = hwnd;
return FALSE;
}
return TRUE;
}

void RefreshTray ( )
{
HWND hTray = ::FindWindow( "Shell_TrayWnd",0);
if ( hTray )
{
::EnumChildWindows (hTray, EnumChildProc, 0);
if ( g_hToobarTray )
{
RECT rc;
::GetClientRect (g_hToobarTray, &rc);
for (int i=1; i< rc.right; i++)
::SendMessage (g_hToobarTray, WM_MOUSEMOVE, 0, MAKELONG(1,i));
}
}

}


Cheers

leojose
December 2nd, 2005, 03:03 AM
its not that complex ;)
wow!...you really know how to make it 'not complex' :) ...thanks golanshahar ;)

kirants
December 2nd, 2005, 12:47 PM
See last post here (http://www.codeguru.com/forum/showthread.php?t=150081)

It's slightly complex, should take care of vertical taskbar and such ;)

leojose
January 5th, 2006, 08:58 AM
kirants, the code you provided has been really useful to me but on some machines the movement of the cursor is visible on the taskbar. Is it possible to hide the cursor icon while it is moving all over the taskbar?

kirants
January 5th, 2006, 10:58 AM
You may want to experiment with ShowCursor

leojose
January 5th, 2006, 11:57 PM
I did try ShowCursor(), but it doesn't work in this case. I had once subclassed a window and used this api to hide the cursor whenever the mouse moved, but in the present scenario it doesn't :(
There is an even more complicated method where I use SetSystemCursor() to change the cursor and then restore it back...but I just want to avoid that if its possible.
I think if I could just turn the cursor into a tiny dot or something it could still do the trick.. :ehh: . Do you think there is an easy method to do that?

golanshahar
January 6th, 2006, 02:37 AM
I did try ShowCursor(), but it doesn't work in this case. I had once subclassed a window and used this api to hide the cursor whenever the mouse moved, but in the present scenario it doesn't :(
There is an even more complicated method where I use SetSystemCursor() to change the cursor and then restore it back...but I just want to avoid that if its possible.
I think if I could just turn the cursor into a tiny dot or something it could still do the trick.. :ehh: . Do you think there is an easy method to do that?

even if you want to change the cursor to tiny one you will still need to use ::SetSystemCursor(..) cause you need to change it in the whole system since you move the cursor from A point to B point while in the way there are other windows :).
so i think you should use ::SetSytemCursor() and to restore the cursor use:

::SystemParametersInfo(SPI_SETCURSORS,0,0,WM_SETTINGCHANGE |SPIF_UPDATEINIFILE );


Cheers