2009-03-17 7 views
11

J'ai ajouté une icône Notify à mon application, et bien souvent je vois jusqu'à 3 copies de l'icône Notify dans mon systray. Y a-t-il une raison à cela?Pourquoi est-ce que je vois plusieurs icônes Systray?

est-il un moyen d'arrêter de se produire.

Souvent, cela persiste après la fermeture de mon application, jusqu'à ce que je me retrouve sur la barre des tâches et que la barre des tâches se dilate et s'effondre, puis disparaissent toutes.

+0

Comment avez-vous ajouter le NotifyIcon? Dans le concepteur ou dans le code? – OregonGhost

+0

... et comment l'enlever pendant la fermeture de l'application? –

+0

Designer et je ne l'enlève pas devrait-il? –

Répondre

21

Est-ce pendant que vous déboguez votre application? Si c'est le cas, les messages qui suppriment l'icône de la barre d'état système ne sont envoyés que lorsque l'application se ferme normalement, s'arrêtent à cause d'une exception ou parce que vous la fermez à partir de Visual Studio.

+0

Je déteste travailler sur des applications qui ont des icônes dans le systray et les arrêter avec Visual Studio. Finit avec des dizaines d'entre eux si je ne souris pas sur eux. – Samuel

+6

Bien que bouger votre bras un peu de temps en temps pourrait être en bonne santé: p – Svish

+2

Oui, mais sur un moniteur de 24 pouces, c'est tout un voyage pour la souris. ;) – Samuel

9

Vous pouvez tuer l'icône en utilisant l'événement fermé du parent fenêtre. Cela fonctionne dans mon application WPF, même lors des tests dans Visual Studio (2010 dans mon cas):

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

Ce que je l'ai fait:

  1. Créer une bibliothèque de classe qui met à jour la barre d'état système.

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

    Où xx est le numéro de version de Visual Studio

  3. Enregistrer une macro et enregistrez-

  4. Modifier la macro

    Ajouter une référence à la DLL créée.

    Ajouter Imports SystrayUtil à la liste des importations en haut du module EnvironmentEvents.

    Retirez tous les éléments indésirables et ajoutez le code suivant au module EnvironmentEvents

    Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode 
    Systray.Cleanup() 
    MsgBox("Entered design mode!") 
    End Sub 
    
  5. Si cela fonctionne supprimer MsgBox("Entered design mode!") parce qu'il est gênant d'avoir une boîte de message apparaître chaque fois que vous revenez d'une session de débogage.

0

Cela devrait fonctionner lorsque vous normalement fermer l'application:

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

Lorsque vous arrêtez l'application du bouton de mise au point d'arrêt Visual Studio - le processus est tué et aucun événement Dispose sont tirés.