Можете ли вы отправить сигнал в Проводник Windows, чтобы обновить значки systray?

эта проблема беспокоила меня довольно долго, и это было действительно раздражает.

каждый раз, когда я вхожу в систему после перезагрузки / цикла питания, проводник занимает некоторое время. Я сделал шаг, ожидая загрузки всех служб, а затем вошел в систему, но это не имеет никакого значения. Результат всегда один и тот же: некоторые значки не отображаются, даже если приложения запущены.

Я немного покопался в коде, который делает одно приложение "вставьте" значок там, но есть ли вызов API, который можно выполнить, чтобы explorer перечитал всю информацию об этом значке? Например, аннулировать или перерисовать или что-то в этом роде?


по-видимому, похоже, что Джон был прав, и это невозможно сделать.

я следовал коду Боба Дизла и Марка Рэнсома и построил это (код Delphi):

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;

но безрезультатно.

Я даже пробовал с

InvalidateRect()
и все еще нет шоу.

любой другой предложения?

6 ответов


взгляните на эту запись в блог: ОБНОВЛЕНИЕ ОБЛАСТИ УВЕДОМЛЕНИЙ ПАНЕЛИ ЗАДАЧ. Я использую этот код для обновления системного трея, чтобы избавиться от осиротевших значков, и он отлично работает. Запись в блоге очень информативна и дает отличное объяснение шагов, которые автор выполнил, чтобы найти свое решение.

#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"), // Windows XP
            L"User Promoted Notification Area"), // Windows 7 and up
        &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);
}

две важные детали для тех, кто использует ответ Луиса (от ОБНОВЛЕНИЕ ОБЛАСТИ УВЕДОМЛЕНИЙ ПАНЕЛИ ЗАДАЧ) В Windows 7 или Windows 8:

во-первых, как было отражено в ответе, окно под названием "область уведомлений" в XP теперь называется "область уведомлений пользователя" в Windows 7 (на самом деле, вероятно, Vista) и выше.

во-вторых, этот код не очищает значки, которые в настоящее время скрыты. Они содержатся в отдельном окне. Использовать оригинал код для обновления видимых значков и следующие для обновления скрытых значков.

//Hidden icons
GetClientRect(
    hNotificationArea = FindWindowEx(
        FW(NULL, L"NotifyIconOverflowWindow"),
        NULL,
        L"ToolbarWindow32",
        L"Overflow 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);

для тех, кому просто нужна утилита для запуска, чтобы выполнить это, а не код, я построил простой exe с этим обновлением:Обновить Область Уведомлений


включите следующий код с вашим, чтобы обновить системный трей.

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);

насколько я знаю, это невозможно, Густаво - это до каждого приложения, чтобы поместить его notifyicon в systray и убедиться, что он находится в правильном состоянии.

вы заметите иногда, когда explorer.exe аварийно завершает работу, что некоторые значки не появляются-это не потому, что их процесс разбился, просто их приложение не поместило notifyicon в systray, когда новый экземпляр explorer.exe запустился. Еще раз, это приложение, которое ответственный.

Извините, что у вас нет лучших новостей для вас!


я освещал этот вопрос в прошлом году на моем Codeaholic weblog в статье под названием [Delphi] Обновление SysTray.

мое решение является Delphi ActiveX/COM DLL. Ссылка для загрузки все еще работает (хотя сколько еще я не знаю, как мой PLUG членство истек.)


Я использую следующий код C++, чтобы получить дескриптор окна к окну поднос. Примечание: Это было протестировано только на Windows XP.

HWND FindSystemTrayIcons(void)
{
    // the system tray icons are contained in a specific window hierarchy;
    // use the Spy++ utility to see the chain
    HWND hwndTray = ::FindWindow("Shell_TrayWnd", "");
    if (hwndTray == NULL)
        return NULL;
    HWND hwndNotifyWnd = ::FindWindowEx(hwndTray, NULL, "TrayNotifyWnd", "");
    if (hwndNotifyWnd == NULL)
        return NULL;
    HWND hwndSysPager = ::FindWindowEx(hwndNotifyWnd, NULL, "SysPager", "");
    if (hwndSysPager == NULL)
        return NULL;
    return ::FindWindowEx(hwndSysPager, NULL, "ToolbarWindow32", "Notification Area");
}