NotifyIcon залишається в треї навіть після закриття програми, але зникає при наведенні миші


76

Є багато запитань щодо SO, що ставлять однакові сумніви. Рішення для цього - встановити

notifyIcon.icon = nullі закликаючи Disposeце до події FormClosing.

У моїй заявці такої форми немає, але є піктограма сповіщення, яка оновлюється щодо подій. Під час створення я приховую свою форму і роблю ShowInTaskbarвласність false. Отже, я не можу мати події "FormClosing" або "FormClosed".

Якщо ця програма отримує подію для виходу, вона викликає Process.GetCurrentProcess().Kill();вихід.

Я додав notifyIcon.icon = null, а також Dispose перед вбивством, але піктограма все ще залишається на панелі завдань, доки я не наведу на неї мишу.

РЕДАГУВАТИ : Якщо я припускаю, що така поведінка зумовлена ​​викликом GetCurrentProcess().Kill(), чи є якийсь елегантний спосіб вийти з програми, який очистить всі ресурси та видалить піктограму з системного трея.


1
Час прийняти відповідь, чи не думаєш ти: D Дозвольте мені запропонувати вам той із "Людини кексів": D
Фелікс Д.

Проблема з наготою полягає в тому, що я щойно позбувся цієї піктограми сповіщення ... І тепер у мене немає цього коду, щоб перевірити будь-яке рішення :-)
Swanand

Чи я щойно зробив: D and the Dispose () це виправило: D
Фелікс Д.

Відповіді:


52

Ви можете встановити

notifyIcon1.Visible = false;

АБО

notifyIcon.Icon = null;

у формі закриття форми.


2
Не вирішує проблему.
Gigi

@Gigi Ти спробував?
Джейсон Діас,

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

2
@TheMuffinMan: Це геніально! Вирішив свою проблему так само, як хотів її вирішити. Дуже дякую!
C4d

5
Тим, хто розгляне цю відповідь, важливо зазначити, що це НЕ ВИРІШЮЄ проблему. Якщо ваша піктограма залишається, це тому, що ви налагоджуєте (не всі ПК це роблять, але у нас є 2 з 11, які роблять це тут). Якщо запустити exe, значок насправді зникне.
Франк

20

Єдиним рішенням, яке працювало для мене, було використання закритої події та приховування та розпорядження піктограмою.

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

4
Це має бути прийнятою відповіддю ... Dispose()ось що вам там потрібно!
Фелікс Д.

як це називається? + = (відправник, e) => {// код};
The Muffin Boy

2
@ user3365695 Це лямбда-вираз. Перевірте це посилання на прикладах 3 способів вказати делегата msdn.microsoft.com/en-us/library/…
The Muffin Man

Пам’ятаю, коли я вчився, делегатам не пояснювали добре. Делегат - це просто спосіб назви імені методу, який буде викликаний пізніше чимось. Ви можете використовувати будь-який зроблений вами метод, який відповідає підпису, якого очікує подія. У цьому випадку ми реєструємо метод, який буде викликаний, коли наконечник повітряної кулі внутрішньо викликає BalloonTipClosedподію. У цьому прикладі синтаксично ми не вказуємо назву методу, ми визначаємо те, що називається анонімною функцією / методом. Це новіша функція коду, тому ви бачите кілька способів зробити це особливо delegate(string s) {//code}.
The Muffin Man

Не працює ....
PinnedObject

14

Компоненти просто повинні бути розташовані у правильному порядку, як це:

NotifyIcon.Icon.Dispose();

NotifyIcon.Dispose();

Додайте це до MainWindowзавершальної події.

Сподіваюся, це допоможе.


11

Використовувати notifyIcon.Visible = Falseу FormClosingвипадку


2
Для чистого очищення вам все-таки слід зателефонувати notifyIcon.Dispose(). Якщо у вашому класі немає функції, оскільки ви могли б викликати це, вам слід реалізувати IDisposable.
Даніель Айзенрайх

Не знаю, чому це не позначено як відповідь, але це вирішило і мою проблему ... дякую @Ismael
Кевін Мур

@KevinMoore, оскільки ОП чітко заявив, що у нього немає жодного, Formна якому вони могли б впоратися з FormClosingподією
Арділа,

9

Використовуйте цей код, коли ви хочете це зробити, коли натискаєте кнопку Вийти або Закрити:

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

Використовуйте цей код, коли ви хочете зробити це, коли форма закривається:

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

Важливий код:

notifyIcon.Dispose();

Я спробував наступний код, і він спрацював. private void Window_Closed (відправник об’єкта, EventArgs e) {mNotifyIcon.Dispose (); }
Гарланд

3

На жаль, це нормальна поведінка; це пов’язано з тим, як працює Windows. Ви дійсно можете щось з цим зробити.

Див. Проблему з NotifyIcon, яка не зникає в програмі Winforms, щоб отримати деякі пропозиції, але жодна з них ніколи не працювала для мене.

Також див. Сповіщення про залишення піктограм у системному треї при закритті програми

Microsoft позначила це як "не виправляє" у Microsoft Connect.


3
я відчуваю, що вікна робили це вічно.
j_mcnally

OSX часто залишає GAP на панелі завдань у подібній ситуації, просто химерність, я думаю, як обидві ОС малюють свої панелі завдань / меню.
j_mcnally

Чи не існує елегантного способу вийти з цього процесу замість "GetCurrentProcess.Kill ()" і чи змінить це мою поведінку?
Swanand

Це може! Я відчуваю, що той факт, що ви його вбиваєте, є причиною проблеми. Ви можете спробувати дочекатися наступного циклу запуску перед вбивством, після встановлення піктограми нуль та утилізації.
j_mcnally

1
@MatthewWatson Чи можете ви надати мені будь-яке посилання, де сказано "Не виправляю"?
Swanand

2

Я не думаю, що WPF має власний NotifyIcon, правда? Якщо ви використовуєте сторонній Harcodet.Wpf.TaskbarNotification, спробуйте наступне:

Щоб запобігти закриттю мого додатка, коли вікно закрито (працює у фоновому режимі), я відокремив логіку закриття вікна (натискання кнопки x у верхньому правому куті) і фактичного його вимкнення (через контекстне меню). Щоб це працювало, встановіть для контекстного меню значення _isExplicitClosetrue. В іншому випадку він просто приховає вікно і продовжить працювати.

Це робить те, що при явному закритті піктограма лотка та форма приховуються перед закриттям. Таким чином, піктограма не висить після вимкнення програми.

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

Спробуйте Application.DoEvents();після установки notifyIcon.Iconв nullі утилізації:

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

І розглянути Environment.Exit(0);замість Process.GetCurrentProcess().Kill().


1

я можу сказати, що ви можете вирішити проблему, просто використовуючи метод .dispose (), але це не викликається, якщо ви вбиваєте процес замість виходу з програми.

Будь ласка, зверніться до Application.Exit, якщо ви створили просту програму Windows Form, інакше зверніться до Environment.Exit, що є більш загальним.


1

Я спробував усе це, і жоден з них не працював у мене. Подумавши деякий час, я зрозумів, що програма, що створює "повітряну кулю", виходить, перш ніж вона мала можливість фактично розпорядитися повітряною кулею. Я додав цикл while безпосередньо перед тим, як Application.Exit()містити Application.DoEvents()команду. Це дозволило мені NotifyIcon1_BalloonTipClosedфактично закінчити утилізацію ікони перед виходом.

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

І метод закритого наконечника: ( thisIcon.visible = falseДля того, щоб це працювало, потрібно включити параметр )

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


0

редагувати коди ... Designer.cs, як показано нижче, кодування.

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

Будь ласка, додайте пояснення.
Містер Муш,

0

Єдиний спосіб, який мені працює:

  1. На екрані дизайну змінюється властивість notifyicon1 visible = false

  2. Вставте код нижче в основну форму "активованої" події:

NotifyIcon1.Visible = True
  1. Вставте код нижче в основну форму "закриття" події:
NotifyIcon1.Visible = false
NotifyIcon1.Icon.Dispose()
NotifyIcon1.Dispose()

-1

Правильна відповідь вже дана. Але ви також повинні вказати затримку, наприклад, з таймером. Тільки тоді програма все ще може видалити піктограму у фоновому режимі.

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
Напевно, використання таймера є надмірним - чи не Thread.Sleep (1000) зробить те саме? Ви навіть можете використовувати його в новому ланцюжку, щоб він не призупиняв будь-який графічний інтерфейс
Марк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.