Pouvez-vous envoyer un signal à l'Explorateur Windows pour qu'il actualise les icônes de la barre des tâches?

StackOverflow https://stackoverflow.com/questions/74723

Question

Ce problème m’afflige depuis un certain temps et c’est vraiment agaçant.

Chaque fois que je me connecte après un redémarrage / un cycle d'alimentation, l'explorateur met du temps à s'afficher. J'ai déjà attendu que tous les services démarrent, puis je me connecte, mais cela ne fait aucune différence. Le résultat est toujours le même: certaines icônes n'apparaissent pas, même si les applications ont démarré.

J'ai un peu creusé dans le code qui fait qu'une application "colle" une icône, mais existe-t-il un appel d'API que l'on peut effectuer pour que l'explorateur relise toutes les informations relatives à cette icône? Comme invalider ou redessiner ou quelque chose du genre?

Apparemment, Jon semble avoir raison et ce n'est pas possible.

J'ai suivi le code de Bob Dizzle et Mark Ransom et je l'ai construit (code 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;

Mais en vain.

J'ai même essayé avec

InvalidateRect()
et toujours pas de show.

D'autres suggestions?

Était-ce utile?

La solution

Jetez un coup d'œil à cette entrée de blog: RAFRAICHISSEMENT DE ZONE DE NOTIFICATION DE TASKAR . J'utilise ce code pour actualiser la barre d'état système afin de supprimer les icônes orphelines et cela fonctionne parfaitement. L’entrée du blog est très informative et donne une bonne explication des étapes que l’auteur a effectuées pour découvrir sa 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"), // 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);
}

Autres conseils

Deux informations importantes pour ceux qui utilisent la réponse de Louis (tirées de RÉNOVATION DE LA ZONE DE NOTIFICATION TASKBAR ) sous Windows 7 ou Windows 8:

Tout d'abord, comme l'indiquait la réponse, la fenêtre intitulée "Zone de notification". dans XP est désormais intitulé "Zone de notification sponsorisée par l'utilisateur". sous Windows 7 (probablement probablement Vista) et plus.

Deuxièmement, ce code ne supprime pas les icônes actuellement masquées. Ceux-ci sont contenus dans une fenêtre séparée. Utilisez le code d'origine pour actualiser les icônes visibles et le suivant pour actualiser les icônes masquées.

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

Pour ceux qui ont juste besoin d'un utilitaire à exécuter, plutôt que de code, j'ai construit un simple exe avec cette mise à jour: Actualiser la zone de notification

Incluez le code suivant dans le vôtre pour actualiser la barre d'état système.

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

Autant que je sache, Gustavo n’est pas possible. Il appartient à chaque application de placer son avis de notification dans la barre des tâches et de s’assurer qu’il est maintenu dans le bon état.

Vous remarquerez parfois, lorsque crash.exe se bloque, que certaines icônes ne réapparaissent pas - ce n'est pas parce que leur processus s'est bloqué, mais simplement que leur application n'a pas mis le notifyicon dans la barre des tâches lorsque la nouvelle instance de l'explorateur .exe démarré. Encore une fois, c'est l'application qui est responsable.

Désolé de ne pas avoir de meilleures nouvelles pour vous!

J'ai couvert ce problème l'année dernière dans mon blog Codeaholic dans un article intitulé [Delphi] Mise à jour de SysTray .

Ma solution est une DLL Delphi ActiveX / COM. Le lien de téléchargement fonctionne toujours (mais je ne sais pas pendant combien de temps encore mon adhésion PLUG a expiré .)

J'utilise le code C ++ suivant pour obtenir le handle de fenêtre dans la fenêtre de la barre des tâches. Remarque: cela n'a été testé que sous 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");
}

@Skip R, et tous ceux qui souhaitent le faire en C, avec ce code vérifié compilé dans une version récente (la plus récente) sous Windows 10 64 bits (mais avec le package mingw 32 bits installé), cela semble fonctionner sous Windows XP / 2003 pour vous débarrasser des icônes périmées de la zone de notification.

J'ai installé mingw via Chocolatey, comme ceci:

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

(votre kilométrage peut varier en conséquence, sur mon système, le compilateur a alors été installé ici:

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

puis un simple

gcc refresh_notification_area.c

a généré un a.exe qui résolvait le problème de l'icône de zone de notification obsolète que je rencontrais sous Windows 2003 (32 bits).

Le code, adapté de @Stephen Klancher ci-dessus, est le suivant (notez que cela ne fonctionne que sous Windows XP / 2003, ce qui a rempli mes objectifs):

#include <windows.h>

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

int main ()
{

    HWND hNotificationArea;
    RECT r;

    //WinXP
    // technique found at:
    // https://stackoverflow.com/questions/74723/can-you-send-a-signal-to-windows-explorer-to-make-it-refresh-the-systray-icons#18038441
    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;

}

Après avoir essayé maintes fois, j'ai découvert qu'il y avait trois problèmes à connaître:

  • Le parent de la fenêtre de bac masqué est NotifyIconOverflowWindow , autre que Shell_TrayWnd .
  • Vous ne devez pas utiliser le paramètre caption de FindWindowEx pour rechercher une fenêtre, car il existe de nombreuses versions linguistiques de Windows OS, elles ne sont pas toujours le même titre. Évidemment.
  • Utilisez spy ++ de Visual Studio pour rechercher ou garantir ce que vous voulez.

Alors, j'ai changé le code de @Stephen Klancher et @Louis Davis, merci les gars.

Le code suivant a fonctionné pour moi.

#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);
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top