views:

3546

answers:

6

This problem has been afflicting me for quite a while and it's been really annoying.

Every time I login after a reboot/power cycle the explorer takes some time to show up. I've taken the step of waiting for all the services to boot up and then I login, but it doesn't make any difference. The result is always the same: Some of the icons do not show up even if the applications have started.

I've dug a bit on the code that makes one application "stick" an icon in there, but is there an API call that one can perform so explorer re-reads all that icon info? Like invalidate or redraw or something of the sort?

+2  A: 

As far as I know that isn't possible Gustavo - it's up to each application to put its notifyicon in the systray, and ensure it's kept in the right state.

You'll notice sometimes when explorer.exe crashes that certain icons don't reappear - this isn't because their process has crashed, simply that their application hasn't put the notifyicon in the systray when the new instance of explorer.exe started up. Once again, it's the application that's responsible.

Sorry not to have better news for you!

LordSauce
+2  A: 

Include following code with yours to refresh System Tray.

public const int WM_PAINT = 0xF; [DllImport("USER32.DLL")] public static extern int SendMessage(IntPtr hwnd, int msg, int character, IntPtr lpsText);

Send WM_PAINT Message to paint System Tray which will refresh it. SendMessage(traynotifywnd,WM_PAINT,0,IntPtr.Zero);

Bob Dizzle
I'm actually a Delphi kinda guy but that makes sense.So basically send a WM_PAINT message to the below found Handle.I'll test it and report back.
Gustavo Carreno
A: 
Mark Ransom
Thanks for the added info. I would probably be pulling my hair out looking for that hierarchy.
Gustavo Carreno
+1  A: 

Apparently, it looks like Jon was right and it's not possible to do it.

I've followed Bob Dizzle and Mark Ransom code and build this (Delphi Code):

procedure Refresh;
var
  hSysTray: THandle;
begin
  hSysTray := GetSystrayHandle;
  SendMessage(hSysTray, WM_PAINT, 0, 0);
end;

function GetSystrayHandle: THandle;
var
  hTray, hNotify, hSysPager: THandle;
begin
  hTray := FindWindow('Shell_TrayWnd', '');
  if hTray = 0 then
  begin
    Result := hTray;
    exit;
  end;

  hNotify := FindWindowEx(hTray, 0, 'TrayNotifyWnd', '');
  if hNotify = 0 then
  begin
    Result := hNotify;
    exit;
  end;

  hSyspager := FindWindowEx(hNotify, 0, 'SysPager', '');
  if hSyspager = 0 then
  begin
    Result := hSyspager;
    exit;
  end;

  Result := FindWindowEx(hSysPager, 0, 'ToolbarWindow32', 'Notification Area');
end;

But to no avail.

I've even tried with

InvalidateRect()
and still no show.

Any other suggestions?

Gustavo Carreno
+2  A: 

Take a look at this blog entry: REFRESHING THE TASKBAR NOTIFICATION AREA. I am using this code to refresh the system tray to get rid of orphaned icons and it works perfectly. The blog entry is very informative and gives a great explanation of the steps the author performed to discover his solution.

#define FW(x,y) FindWindowEx(x, NULL, y, L"")

void RefreshTaskbarNotificationArea()
{
    HWND hNotificationArea;
    RECT r;

    GetClientRect(
        hNotificationArea = FindWindowEx(
            FW(FW(FW(NULL, L"Shell_TrayWnd"), L"TrayNotifyWnd"), L"SysPager"),
            NULL,
            L"ToolbarWindow32",
            L"Notification Area"),
        &r);

    for (LONG x = 0; x < r.right; x += 5)
        for (LONG y = 0; y < r.bottom; y += 5)
            SendMessage(
                hNotificationArea,
                WM_MOUSEMOVE,
                0,
                (y << 16) + x);
}
Louis Davis
New challenge, but in reverse: http://stackoverflow.com/questions/1114887/can-i-re-gain-a-systray-icon-of-a-running-app-that-has-gone-missing
Gustavo Carreno
I have some doubts whether the last parameter "Notification Area" will work on international versions of Windows.
dummzeuch
dummzeuch is correct. The "Notification Area" string will need to be localized for the appropriate Windows language.
Louis Davis
+1  A: 

I covered this issue last year on my Codeaholic weblog in an article entitled [Delphi] Updating SysTray.

My solution is a Delphi ActiveX/COM DLL. The download link still works (though for how much longer I don't know as my PLUG membership has lapsed.)

boost
I'm sorry I did not choose your answer, but Louis has less points and both you guys have the same answer.
Gustavo Carreno
New challenge, but in reverse: http://stackoverflow.com/questions/1114887/can-i-re-gain-a-systray-icon-of-a-running-app-that-has-gone-missing
Gustavo Carreno