Puoi inviare un segnale a Windows Explorer per aggiornare le icone della barra delle applicazioni?

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

Domanda

Questo problema mi affligge da un bel po' ed è davvero fastidioso.

Ogni volta che accedo dopo un riavvio/spegnimento, Explorer impiega del tempo per essere visualizzato.Ho deciso di attendere l'avvio di tutti i servizi e quindi di accedere, ma non fa alcuna differenza.Il risultato è sempre lo stesso:Alcune icone non vengono visualizzate anche se le applicazioni sono state avviate.

Ho scavato un po' nel codice che fa sì che un'applicazione "attacchi" un'icona lì dentro, ma esiste una chiamata API che è possibile eseguire in modo che Explorer rilegga tutte le informazioni sull'icona?Tipo invalidare, ridisegnare o qualcosa del genere?


A quanto pare, sembra che Jon avesse ragione e non è possibile farlo.

Ho seguito il codice di Bob Dizzle e Mark Ransom e ho creato questo (codice 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;

Ma inutilmente.

Ci ho anche provato con

InvalidateRect()
e ancora nessuno spettacolo.

Altri suggerimenti?

È stato utile?

Soluzione

Dai un'occhiata a questo post sul blog: AGGIORNAMENTO DELL'AREA DI NOTIFICA DELLA BARRA DELLE APPLICAZIONI.Sto usando questo codice per aggiornare la barra delle applicazioni per eliminare le icone orfane e funziona perfettamente.Il post sul blog è molto istruttivo e fornisce un'ottima spiegazione dei passaggi eseguiti dall'autore per scoprire la sua soluzione.

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

Altri suggerimenti

Due dettagli importanti per chiunque utilizzi la risposta di Louis (da AGGIORNAMENTO DELL'AREA DI NOTIFICA DELLA BARRA DELLE APPLICAZIONI) su Windows 7 o Windows 8:

Innanzitutto, come si è riflesso nella risposta, la finestra intitolata "Area di notifica" in XP è ora intitolata "Area di notifica promossa dall'utente" in Windows 7 (in realtà probabilmente Vista) e versioni successive.

In secondo luogo, questo codice non cancella le icone attualmente nascoste.Questi sono contenuti in una finestra separata.Utilizza il codice originale per aggiornare le icone visibili e quanto segue per aggiornare le icone nascoste.

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

Per chiunque abbia solo bisogno di un'utilità da eseguire per ottenere questo risultato, piuttosto che del codice, ho creato un semplice exe con questo aggiornamento: Aggiorna area di notifica

Includi il seguente codice con il tuo per aggiornare la barra delle applicazioni.

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

Per quanto ne so, non è possibile Gustavo: spetta a ciascuna applicazione mettere la propria icona di notifica nella barra delle applicazioni e assicurarsi che sia mantenuta nello stato corretto.

Noterai a volte quando explorer.exe si blocca che alcune icone non ricompaiono: questo non è perché il loro processo si è bloccato, semplicemente perché la loro applicazione non ha inserito l'icona di notifica nella barra delle applicazioni quando è stata avviata la nuova istanza di explorer.exe su.Ancora una volta, la responsabilità è dell'applicazione.

Mi dispiace non avere notizie migliori per te!

Ho trattato questo problema l'anno scorso sul mio Codeaholic blog in un articolo intitolato [Delphi] Aggiornamento SysTray.

La mia soluzione è una DLL Delphi ActiveX/COM.Il collegamento per il download funziona ancora (anche se per quanto tempo ancora non so come mio TAPPO l'iscrizione è scaduta.)

Utilizzo il seguente codice C++ per ottenere l'handle della finestra nella finestra del vassoio. Nota: questo è stato testato solo su 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, e chiunque altro voglia farlo in C, con questo codice verificato compilato in un mingw recente (più recente) su Windows 10 a 64 bit (ma con il pacchetto mingw a 32 bit installato), sembra funzionare in Windows XP /2003 per eliminare le icone obsolete dell'area di notifica.

Ho installato mingw tramite Chocolatey, in questo modo:

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

(il tuo chilometraggio può variare in base al fatto che, sul mio sistema, il compilatore è stato quindi installato qui:

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

e poi un semplice

gcc refresh_notification_area.c

ha prodotto un file a.exe che ha risolto un problema relativo all'icona dell'area di notifica obsoleta che avevo su Windows 2003 (32 bit).

Il codice, adattato da @Stephen Klancher sopra è (nota che potrebbe funzionare solo su Windows XP/2003, che ha soddisfatto i miei scopi):

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

}

Dopo molti tentativi ho scoperto che ci sono tre problemi che devi conoscere:

  • Il genitore della finestra del vassoio nascosto è NotifyIconOverflowWindow, diverso da Shell_TrayWnd.
  • Non dovresti usare caption parametro di FindWindowEx per trovare una finestra, poiché ci sono molte versioni in lingua del sistema operativo Windows, ovviamente non hanno sempre lo stesso titolo.
  • Utilizzo spy++ di Visual Studio per trovare o verificare ciò che desideri.

Quindi, ho cambiato il codice di @Stephen Klancher e @Louis Davis, grazie ragazzi.

Il seguente codice ha funzionato per me.

#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);
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top