NotifyIcon bleibt auch nach dem Schließen der Anwendung in der Taskleiste, verschwindet jedoch beim Bewegen der Maus


76

Es gibt viele Fragen zu SO, die den gleichen Zweifel aufwerfen. Die Lösung hierfür ist das Einstellen

notifyIcon.icon = nullund Aufruf Disposeim FormClosing-Ereignis.

In meiner Anwendung gibt es kein solches Formular, aber das Benachrichtigungssymbol, das bei Ereignissen aktualisiert wird. Bei der Erstellung verstecke ich mein Formular und mache ShowInTaskbarEigentum false. Daher kann ich keine "FormClosing" - oder "FormClosed" -Ereignisse haben.

Wenn diese Anwendung ein Ereignis zum Beenden erhält, ruft sie Process.GetCurrentProcess().Kill();zum Beenden auf.

Ich habe notifyIcon.icon = nullvor dem Töten sowohl hinzugefügt als auch entsorgt, aber das Symbol bleibt die Taskleiste, bis ich mit der Maus darüber fahre.

BEARBEITEN : Wenn ich davon ausgehe , dass dieses Verhalten auf einen Aufruf zurückzuführen GetCurrentProcess().Kill()ist, gibt es eine elegante Möglichkeit, die Anwendung zu beenden, um alle Ressourcen zu löschen und das Symbol aus der Taskleiste zu entfernen.


1
Zeit, eine Antwort anzunehmen, denkst du nicht: D Lass mich dir die von "The Muffin Man" vorschlagen: D
Felix D.

@ Nacktheit Problem ist, ich habe gerade dieses Benachrichtigungssymbol entfernt ... Und jetzt habe ich diesen Code nicht, um eine Lösung zu überprüfen :-)
Swanand

Habe ich gerade getan: D und die Dispose () haben es behoben: D
Felix D.

Antworten:


52

Sie können entweder einstellen

notifyIcon1.Visible = false;

ODER

notifyIcon.Icon = null;

im Formular Abschlussereignis.


2
Behebt das Problem nicht.
Gigi

@ Gigi Hast du es versucht?
Jason Dias

14
icon.BalloonTipClosed += (sender, e) => { var thisIcon = (NotifyIcon)sender; thisIcon.Visible = false; thisIcon.Dispose(); };
Der Muffin-Mann

2
@ TheMuffinMan: Das ist genial! Ich habe mein Problem so gelöst, wie ich es lösen wollte. Danke vielmals!
C4d

5
Für diejenigen, die auf diese Antwort fallen, ist es wichtig zu beachten, dass dies das Problem behebt. Wenn Ihr Symbol erhalten bleibt, liegt es daran, dass Sie debuggen (nicht jeder PC macht das, aber wir haben 2 von 11, die das hier machen). Wenn Sie die Exe ausführen, verschwindet das Symbol tatsächlich.
Franck

19

Die einzige Lösung, die für mich funktioniert hat, war, das Ereignis Geschlossen zu verwenden und das Symbol auszublenden und zu entsorgen.

icon.BalloonTipClosed += (sender, e) => { 
                                            var thisIcon = (NotifyIcon)sender;
                                            thisIcon.Visible = false;
                                            thisIcon.Dispose(); 
                                        };

4
Dies sollte die akzeptierte Antwort sein ... Dispose()ist das, was Sie dort brauchen!
Felix D.

wie heißt das? + = (Absender, e) => {// Code};
Der Muffin-Junge

2
@ user3365695 Es ist ein Lambda-Ausdruck. Überprüfen Sie diesen Link mit Beispielen der 3 Möglichkeiten, um den Delegaten msdn.microsoft.com/en-us/library/…
The Muffin Man

Ich erinnere mich, als ich lernte, wurden Delegierte nicht gut erklärt. Ein Delegat ist einfach eine Möglichkeit, den Namen einer Methode anzugeben, die später von etwas aufgerufen werden soll. Sie können jede von Ihnen erstellte Methode verwenden, die der vom Ereignis erwarteten Signatur entspricht. In diesem Fall registrieren wir eine Methode, die aufgerufen werden soll, sobald die Ballonspitze das BalloonTipClosedEreignis intern aufruft . In diesem Beispiel geben wir syntaktisch nicht den Namen einer Methode an, sondern definieren eine sogenannte anonyme Funktion / Methode. Dies ist eine neuere Codefunktion, weshalb Sie mehrere Möglichkeiten sehen, dies insbesondere zu tun delegate(string s) {//code}.
Der Muffin-Mann

13

Komponenten müssen nur in der richtigen Reihenfolge wie folgt entsorgt werden:

NotifyIcon.Icon.Dispose();

NotifyIcon.Dispose();

Fügen Sie dies dem MainWindowAbschlussereignis hinzu.

Hoffe das wird helfen.


11

Verwendung notifyIcon.Visible = Falseim FormClosingEreignis


2
Um eine Bereinigung durchzuführen, sollten Sie trotzdem anrufen notifyIcon.Dispose(). Wenn Ihre Klasse keine Funktion hat, die Sie aufrufen können, sollten Sie sie implementieren IDisposable.
Daniel Eisenreich

Ich bin mir nicht sicher, warum dies nicht als Antwort markiert ist, aber es hat auch mein Problem behoben ... danke @Ismael
Kevin Moore

@ KevinMoore, weil das OP ausdrücklich erklärt hat, dass er keine hat, Formauf der sie das FormClosingEreignis behandeln könnten
ardila

9

Verwenden Sie diesen Code, wenn Sie dies tun möchten, wenn Sie auf die Schaltfläche Beenden oder Schließen klicken:

private void ExitButton_Click(object sender, EventArgs e)
{
    notifyIcon.Dispose();
    Application.Exit(); // or this.Close();
}

Verwenden Sie diesen Code, wenn Sie dies beim Schließen des Formulars tun möchten:

private void Form1_FormClosing(object sender, EventArgs e)
{
    notifyIcon.Dispose();
    Application.Exit(); // or this.Close();
}

Der wichtige Code lautet:

notifyIcon.Dispose();

Ich habe den folgenden Code ausprobiert und es hat funktioniert. private void Window_Closed (Objektabsender, EventArgs e) {mNotifyIcon.Dispose (); }
Garland

3

Dies ist leider normal; Das liegt an der Funktionsweise von Windows. Sie können wirklich nichts dagegen tun.

Siehe Problem mit NotifyIcon nicht dissappearing auf WinForms App für einige Vorschläge, aber keiner von ihnen jemals für mich gearbeitet.

Siehe auch Benachrichtigungssymbol bleibt in der Taskleiste beim Schließen der Anwendung

Microsoft hat dies in Microsoft Connect als "wird nicht behoben" markiert.


3
Ich habe das Gefühl, dass Windows dies schon immer getan hat.
j_mcnally

OSX hinterlässt in einer ähnlichen Situation häufig eine Lücke in der Taskleiste, nur eine Eigenart, wie beide Betriebssysteme ihre Task- / Menüleisten zeichnen.
j_mcnally

Gibt es keine elegante Möglichkeit, diesen Prozess anstelle von "GetCurrentProcess.Kill ()" zu beenden, und wird dies mein Verhalten ändern?
Swanand

Es könnte! Ich habe das Gefühl, dass die Tatsache, dass Sie es töten, einige der Probleme verursacht. Sie können versuchen, vor dem Töten auf die nächste Laufschleife zu warten, nachdem Sie das Symbol auf Null gesetzt und entsorgt haben.
j_mcnally

1
@MatthewWatson Kannst du mir einen Link geben, auf dem steht "Wird nicht repariert"?
Swanand

2

Ich glaube nicht, dass WPF ein eigenes NotifyIcon hat, oder? Wenn Sie Harcodet.Wpf.TaskbarNotification von Drittanbietern verwenden, versuchen Sie Folgendes:

Um zu verhindern, dass meine App geschlossen wird, wenn das Fenster geschlossen wird (im Hintergrund ausgeführt), habe ich die Logik zum Schließen des Fensters (Drücken der x-Taste oben rechts) und zum tatsächlichen Herunterfahren (über das Kontextmenü) getrennt. Damit dies funktioniert, setzen Sie Ihr Kontextmenü _isExplicitCloseauf true. Andernfalls wird das Fenster einfach ausgeblendet und weiter ausgeführt.

Beim expliziten Schließen werden das Fachsymbol und das Formular vor dem Schließen ausgeblendet. Auf diese Weise bleibt das Symbol nach dem Herunterfahren der Anwendung nicht hängen.

private bool _isExplicitClose;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
    base.OnClosing(e);

    if (!_isExplicitClose)
    {
        e.Cancel = true;
        Hide();
    }
}

protected void QuitService(object sender, RoutedEventArgs e)
{
   _isExplicitClose = true;
   TaskbarIcon.Visibility = Visibility.Hidden;
   Close();
}

2

Versuchen Sie Application.DoEvents();nach dem Einstellen notifyIcon.Iconauf nullund Entsorgung:

notifyIcon.Icon = null;
notifyIcon.Dispose();
Application.DoEvents();

Und überlegen Sie Environment.Exit(0);statt Process.GetCurrentProcess().Kill().


1

Ich kann Ihnen sagen, dass Sie das Problem einfach mit der .dispose () -Methode lösen können, aber das wird nicht aufgerufen, wenn Sie den Prozess beenden, anstatt die Anwendung zu beenden.

Weitere Informationen finden Sie unter Application.Exit. Wenn Sie eine einfache Windows Form-Anwendung erstellt haben, beziehen Sie sich auf Environment.Exit , das allgemeiner ist.


1

Ich habe all dies ausprobiert und keiner von ihnen hat für mich funktioniert. Nachdem ich eine Weile darüber nachgedacht hatte, stellte ich fest, dass die Anwendung, die den "Ballon" erstellt, beendet wurde, bevor sie die Möglichkeit hatte, den Ballon tatsächlich zu entsorgen. Ich habe eine while-Schleife hinzugefügt, kurz bevor ich Application.Exit()einen Application.DoEvents()Befehl enthielt . Dadurch konnte ich NotifyIcon1_BalloonTipCloseddas Symbol vor dem Beenden tatsächlich entsorgen.

while (notifyIcon1.Visible)
{
    Application.DoEvents();
}
Application.Exit();

Und die Tipp geschlossene Methode: (Sie müssen die einschließen thisIcon.visible = false, damit dies funktioniert)

private void NotifyIcon1_BalloonTipClosed(object sender, EventArgs e)
{
    var thisIcon = (NotifyIcon)sender;
    thisIcon.Icon = null;
    thisIcon.Visible = false;
    thisIcon.Dispose();
}


0

Bearbeiten Sie die Codes von ... Designer.cs wie folgt.

        protected override void Dispose(bool disposing)
           {
           if (disposing )
               {
               this.notifyicon.Dispose();
               }
           base.Dispose(disposing);
           }

Bitte fügen Sie eine Erklärung hinzu.
Herr Mush

0

Der einzige Weg, der für mich funktioniert, war:

  1. Auf dem Entwurfsbildschirm wird die Eigenschaft notifyicon1 sichtbar = false geändert

  2. Geben Sie den folgenden Code in das Hauptereignis "aktiviert" ein:

NotifyIcon1.Visible = True
  1. Fügen Sie den folgenden Code in das Ereignis "Schließen" des Hauptformulars ein:
NotifyIcon1.Visible = false
NotifyIcon1.Icon.Dispose()
NotifyIcon1.Dispose()

-1

Die richtige Antwort wurde bereits gegeben. Sie müssen aber auch eine Verzögerung angeben, beispielsweise mit einem Timer. Nur dann kann die Anwendung das Symbol im Hintergrund noch entfernen.

private System.Windows.Forms.Timer mCloseAppTimer;
private void ExitButton_Click(object sender, EventArgs e) 
{ 
    notifyIcon.Visible = false; notifyIcon.Dispose; 
    mCloseAppTimer = new System.Windows.Forms.Timer(); 
    mCloseAppTimer.Interval = 100; 
    mCloseAppTimer.Tick += new EventHandler(OnCloseAppTimerTick); 
} 
private void OnCloseAppTimerTick(object sender, EventArgs e) 
{ 
    Environment.Exit(0); // other exit codes are also possible 
}

1
Sicherlich ist die Verwendung eines Timers ein Overkill - würde Thread.Sleep (1000) nicht dasselbe tun? Man könnte es auch in einem neuen Thread verwenden , damit es nicht ‚Pause‘ jede GUI ect
Mark
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.