Можете ли вы отправить сигнал в Windows Explorer, чтобы он обновлял значки системного экрана? - PullRequest
10 голосов
/ 16 сентября 2008

Эта проблема мучила меня довольно долго, и это очень раздражало.

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

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


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

Я следовал коду Боба Диззла и Марка Рэнсома и строю это (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;

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

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

InvalidateRect()
и до сих пор нет шоу.

Есть другие предложения?

Ответы [ 8 ]

10 голосов
/ 04 августа 2013

Две важные детали для любого, кто использует ответ Луи (из ОБНОВЛЕНИЕ ОБЛАСТИ УВЕДОМЛЕНИЯ О TASKBAR ) в 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 с этим обновлением: Обновить область уведомлений

10 голосов
/ 27 июня 2009

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

#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);
}
3 голосов
/ 16 сентября 2008

Добавьте следующий код для обновления системного трея.

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);
2 голосов
/ 27 июня 2009

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

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

2 голосов
/ 16 сентября 2008

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

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

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

1 голос
/ 16 сентября 2008

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

<code>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");
}
0 голосов
/ 11 мая 2019

После многих попыток я обнаружил, что есть три вопроса, которые вы должны знать:

  • Родитель окна скрытого лотка - NotifyIconOverflowWindow, отличный от Shell_TrayWnd.
  • Вы не должны использовать caption параметр FindWindowEx, чтобы найти окно, потому что это много языковых версий ОС Windows, они не всегда имеют одинаковый заголовок Очевидно.
  • Используйте spy++ Visual Studio, чтобы найти или подтвердить то, что вы хотите.

Итак, я изменил код с @Stephen Klancher и @Louis Davis, спасибо, ребята.

У меня сработал следующий код.

#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
    HWND hNotificationArea;
    RECT r;
    GetClientRect(hNotificationArea = FindWindowEx(FW(NULL, L"NotifyIconOverflowWindow"), NULL, L"ToolbarWindow32", NULL), &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);
        }
    }
}
0 голосов
/ 27 декабря 2018

@ Пропустите R, и любой другой, кто хочет сделать это в C, с проверенным кодом, скомпилированным в недавнем (самом последнем) mingw на Windows 10 64-битной (но с установленным 32-битным пакетом mingw), похоже, работает в Windows XP / 2003, чтобы избавиться от устаревших значков области уведомлений.

Я установил Mingw через Chocolatey, как это:

choco install mingw --x86 --force --params "/exception:sjlj"

(ваш пробег может варьироваться в зависимости от того, в моей системе компилятор был установлен здесь:

C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw32\bin\gcc.exe

, а затем простой

gcc refresh_notification_area.c

дал файл a.exe, который решил проблему со значком устаревшей области уведомлений, которая была у меня в Windows 2003 (32-разрядная версия).

Код, адаптированный из приведенного выше @Stephen Klancher, (обратите внимание, это может работать только на Windows XP / 2003, которая выполнила мои задачи):

#include <windows.h>

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

int main ()
{

    HWND hNotificationArea;
    RECT r;

    //WinXP
    // technique found at:
    // /65402/mozhete-li-vy-otpravit-signal-v-windows-explorer-chtoby-on-obnovlyal-znachki-sistemnogo-ekrana#65414
    GetClientRect(
        hNotificationArea = FindWindowEx(
            FW(FW(FW(NULL, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
            NULL,
            "ToolbarWindow32",
            "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);

  return 0;

}
...