2009-03-17 14 views
11

Dodałem ikonę Powiadom do mojej aplikacji i dość często widzę do 3 kopii ikony powiadomień w mojej pamięci podręcznej. czy istnieje ku temu powód?Dlaczego widzę wiele ikon Systray?

Czy istnieje sposób, aby temu zapobiec?

Często to się utrzymuje po zamknięciu mojej aplikacji, dopóki nie przejdę do zasobnika systemowego, a zasobnik systemowy rozszerzy się i zapadnie, a następnie wszystkie znikną.

+0

W jaki sposób dodano narzędzie NotifyIcon? W projektancie lub w kodzie? – OregonGhost

+0

... i jak usunąć go podczas zamykania aplikacji? –

+0

Projektant i nie usuwam go powinienem? –

Odpowiedz

21

Czy to podczas debugowania aplikacji? jeśli tak, to dlatego, że wiadomości, które usuwają ikonę z paska zadań, są wysyłane tylko wtedy, gdy aplikacja wychodzi normalnie, jeśli kończy się z powodu wyjątku lub z powodu zakończenia pracy w Visual Studio, ikona pozostanie widoczna, dopóki jej nie wskażesz.

+0

Nienawidzę pracować nad aplikacjami, które mają ikony w zasobniku systemowym i zatrzymują je za pomocą Visual Studio. Kończy się ich tuzinami, jeśli nie przeskoczę nad nimi myszką. – Samuel

+6

mimo że poruszanie ręką trochę dłużej może być zdrowe: p – Svish

+2

Tak, ale na monitorze o przekątnej 24 cali to spora podróż dla myszy. ;) – Samuel

9

Możesz zabić ikonę przy użyciu zdarzenia Zamykanie okna nadrzędnego. Działa to w mojej aplikacji WPF, nawet podczas testowania w Visual Studio (2010 w moim przypadku):

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

Co zrobiłem:

  1. Tworzenie biblioteki klasy, który aktualizuje zasobniku systemowym.

    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. skopiować dll do "%ProgramFiles%\Microsoft Visual Studio x.x\Common7\IDE\PublicAssemblies\SystrayUtil.dll"

    gdzie xx to numer wersji programu Visual Studio

  3. Record makro i zapisać go

  4. Edycja makra

    Add odniesienie do utworzonej biblioteki dll.

    Dodaj Imports SystrayUtil do listy importów u góry Module EnvironmentEvents.

    Usuń niepotrzebne przedmioty i dodaj następujący kod do modułu EnvironmentEvents

    Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode 
    Systray.Cleanup() 
    MsgBox("Entered design mode!") 
    End Sub 
    
  5. Jeśli działa usunąć MsgBox("Entered design mode!") bo to irytujące mieć okno komunikatu pojawiały się przy każdym powrocie z sesji debugowania.

0

To powinno działać, kiedy normalnie zamknąć aplikację:

// 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 { } 
} 

Po zatrzymaniu aplikacji z przyciskiem debugowania programu Visual Studio zatrzymania - proces zostanie zabity i nie ma Usunąć wydarzenia są wypalane.

Powiązane problemy