2009-03-17 17 views
11

Ho aggiunto un'icona di notifica alla mia app, e abbastanza spesso vedo fino a 3 copie dell'icona di notifica nella mia systray. c'è una ragione per questo?Perché vedo più icone Systray?

c'è un modo per impedirlo.

Spesso questo persiste dopo che la mia app si è chiusa, fino a quando non mi avvicino alla systray e la systray si espande e collassa e poi tutti scompaiono.

+0

Come è stato aggiunto NotifyIcon? Nel designer o nel codice? – OregonGhost

+0

... e come lo rimuovi durante la chiusura dell'applicazione? –

+0

Designer e io non lo rimuovono, dovrei? –

risposta

21

È in corso il debug dell'applicazione? in tal caso, poiché i messaggi che rimuovono l'icona dalla barra delle applicazioni vengono inviati solo quando l'applicazione viene chiusa normalmente, se termina a causa di un'eccezione o perché la si interrompe da Visual Studio, l'icona rimarrà finché non si passa il mouse su di essa.

+0

Odio lavorare su app che hanno icone nel systray e fermarle con Visual Studio. Finisce con dozzine di loro se non li topo sopra. – Samuel

+6

anche se muoverti un po 'di tanto in tanto potrebbe essere salutare: p – Svish

+2

Sì, ma su un monitor da 24 pollici, è piuttosto un viaggio per il mouse. ;) – Samuel

9

È possibile eliminare l'icona utilizzando l'evento chiuso della finestra principale. Questo funziona nel mio WPF app, anche quando il test in Visual Studio (2010 nel mio caso):

 parentWindow.Closing += (object sender, CancelEventArgs e) => 
     { 
      notifyIcon.Visible = false; 
      notifyIcon.Icon = null; 
      notifyIcon.Dispose(); 
     }; 
2

Quello che ho fatto:

  1. Creare una libreria di classi che aggiorna il vassoio di sistema.

    using System; 
    using System.Diagnostics; 
    using System.Runtime.InteropServices; 
    
    namespace SystrayUtil 
    { 
        internal enum MessageEnum 
        { 
         WM_MOUSEMOVE = 0x0200, 
         WM_CLOSE = 0x0010, 
        } 
    
        internal struct RECT 
        { 
         internal int Left; 
         internal int Top; 
         internal int Right; 
         internal int Bottom; 
    
         internal RECT(int left, int top, int right, int bottom) 
         { 
          Left = left; 
          Top = top; 
          Right = right; 
          Bottom = bottom; 
         } 
        } 
    
        public sealed class Systray 
        { 
         [DllImport("user32.dll", SetLastError = true)] 
         private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
    
         [DllImport("user32.dll", SetLastError = true)] 
         private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, IntPtr lpszWindow); 
    
         [DllImport("user32.dll", SetLastError = true)] 
         private static extern IntPtr SendMessage(IntPtr hWnd, int message, uint wParam, long lParam); 
    
         [DllImport("user32.dll", SetLastError = true)] 
         private static extern bool GetClientRect(IntPtr hWnd, out RECT usrTray); 
    
         public static void Cleanup() 
         { 
          RECT sysTrayRect = new RECT(); 
          IntPtr sysTrayHandle = FindWindow("Shell_TrayWnd", null); 
          if (sysTrayHandle != IntPtr.Zero) 
          { 
           IntPtr childHandle = FindWindowEx(sysTrayHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero); 
           if (childHandle != IntPtr.Zero) 
           { 
            childHandle = FindWindowEx(childHandle, IntPtr.Zero, "SysPager", IntPtr.Zero); 
            if (childHandle != IntPtr.Zero) 
            { 
             childHandle = FindWindowEx(childHandle, IntPtr.Zero, "ToolbarWindow32", IntPtr.Zero); 
             if (childHandle != IntPtr.Zero) 
             { 
              bool systrayWindowFound = GetClientRect(childHandle, out sysTrayRect); 
              if (systrayWindowFound) 
              { 
               for (int x = 0; x < sysTrayRect.Right; x += 5) 
               { 
                for (int y = 0; y < sysTrayRect.Bottom; y += 5) 
                { 
                 SendMessage(childHandle, (int)MessageEnum.WM_MOUSEMOVE, 0, (y << 16) + x); 
                } 
               } 
              } 
             } 
            } 
           } 
          } 
         } 
        } 
    } 
    
  2. Copiare la DLL per "%ProgramFiles%\Microsoft Visual Studio x.x\Common7\IDE\PublicAssemblies\SystrayUtil.dll"

    dove xx è il numero di versione di Visual Studio

  3. registrare una macro e salvarlo

  4. modificare la macro

    Add un riferimento alla dll creata.

    Aggiungi Imports SystrayUtil all'elenco delle importazioni nella parte superiore di Module EnvironmentEvents.

    rimuovere tutti gli elementi indesiderati e aggiungere il seguente codice al modulo EnvironmentEvents

    Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode 
    Systray.Cleanup() 
    MsgBox("Entered design mode!") 
    End Sub 
    
  5. Se funziona rimuoverlo MsgBox("Entered design mode!") perché è fastidioso avere una finestra di messaggio popping up ogni volta che si torna da una sessione di debug.

0

Questo dovrebbe funzionare normalmente quando si chiude l'applicazione:

// in form's constructor 
Application.ApplicationExit += new EventHandler(this.OnApplicationExit); 

private void OnApplicationExit(object sender, EventArgs e) 
{ 
    try 
    { 
     if (notifyIcon1!= null) 
     { 
      notifyIcon1.Visible = false; 
      notifyIcon1.Icon = null; 
      notifyIcon1.Dispose(); 
      notifyIcon1= null; 
     } 
    } 
    catch { } 
} 

Quando si arresta l'applicazione da tasto di debug di Visual Studio di arresto - il processo viene ucciso e eventi Smaltire sono licenziato.