Как реализовать сворачивание в трей на C#

Не так давно мне захотелось сделать так, чтобы моя программа могла сворачиваться в трей. Интересовал, как видно из заголовка, код на C#. Чтобы ускорить процесс, я вбил «сворачивание в трей C#» в Яндекс и по первой же ссылке получил более-менее подходящий ответ. Из любопытства было просмотрено еще несколько ссылок. Где-то (уже точно не вспомню, где именно), были представлены даже ссылки на проект с примером. Он был успешно скачан и изучен. Пример оказался рабочим, но естественно, одного лишь сворачивания мне стало мало и я решил добавить к нему еще пару, если так можно выразиться, «эффектов». Таких как:

  • мигание иконки в трее (как мигает QIP, когда есть непрочитанное сообщение)
  • появление всплывающего сообщения (а-ля сообщение uTorrent’а, что закачка завершена)
  • и, собственно, сворачивание в трей при загрузке (понятно, что это элементарно, но захотелось поиграться)

В скорости это было сделано. Код был изменен, добавлены подробные (даже слишком подробные) комментарии. Зато теперь даже если стукнет склероз, можно будет быстро вспомнить, что к чему:).

Итак, вот что получилось:

    public partial class ForTrey : Form
    {
        public ForTrey()
        {
            InitializeComponent();
            //привязываем контекстное меню к иконке в трее
            _nfIcon.ContextMenuStrip = _cMenuStrip;
        }

        void _nfIcon_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (WindowState == FormWindowState.Normal)
                {
                    WindowState = FormWindowState.Minimized;
                    Hide();
                }
                else
                {
                    Show();
                    WindowState = FormWindowState.Normal;
                }
            }
        }

        ///
        /// Обрабатываем событие изменения размера
        ///
        private void ForTrey_Resize(object sender, EventArgs e)
        {
            //если окно "свернуто", то скрываем его
            if (FormWindowState.Minimized == WindowState)
            {
                Hide();
                //показ всплывающего окна с сообщением из трея
                _nfIcon.ShowBalloonTip(500, "Сообщение", "Я свернулась:)", ToolTipIcon.None);
            }
        }

        ///
        /// Обработка события перерисовки
        ///
        private void IconToBitmap(object sender, PaintEventArgs e)
        {
            // создаем иконку
            Icon icon = new Icon(SystemIcons.Exclamation, 40, 40);

            // комвертируем иконку в bmp
            Bitmap bmp = icon.ToBitmap();

            // прорисовка картинки на форме
            e.Graphics.DrawImage(bmp, new Point(30, 30));
        }

        ///
        /// обрабатываем клик на Exit в меню
        ///
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        ///
        /// Реализация "мигания" значков
        ///
        private void TickOn(object sender, EventArgs e)
        {
            if (_nfIcon.Icon == SystemIcons.Exclamation)//если картинка - "восклицательный знак", то меняем её на "щит"
            {
                _nfIcon.Icon = SystemIcons.Shield;
            }
            else//в противном случае - ставим "восклицательный"
            {
                _nfIcon.Icon = SystemIcons.Exclamation;
            }
        }

        ///
        /// Делаем так, чтобы чтобы  форма  призагрузке сразу пряталась  в   трей
        ///
        private void ForTrey_Load(object sender, EventArgs e)
        {
            ForTrey_Resize(sender, e);
        }
    }

Также стоит не забыть про подписку на события (это делалось в графическом режиме, поэтому здесь будут фрагменты из файла Designer.cs):

this.Load += new System.EventHandler(this.ForTrey_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.IconToBitmap);
this.Resize += new System.EventHandler(this.ForTrey_Resize);
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
this._Timer.Tick += new System.EventHandler(this.TickOn);

Были использованы элементы управления NotifyIcon (находится в разделе стандартных элементов управления; требуется как раз для отображения иконки в трее ), Timer (в «компонентах»; для подсчета тиков) и ContextMenuStrip (соответственно, искать в категории «меню»; как видно из названия, это и есть контекстное меню).

Примечания: в таймере установлено значение в 450 миллисекунд (что на глаз очень близко к частоте мигания в QIP).

Что делает эта простая программа:

  1. при загрузке сразу сворачивается в трей
  2. «мигает» в трее , чередуя между собой два стандартных значка
  3. сворачивается-разворачивается из/ в трей по клику левой кнопки мыши на значке
  4. после сворачивания выдает всплывающее сообщение из трея «я свернулась:)»
  5. при нажатии правой кнопки мыши выводит контекстное меню с пунктом «Выход», по нажатии на который приложение закрывается
  6. рисует системную иконку на самой форме

Вот архив с этим решением: скачать.

Дополнительных комментариев к коду, думаю не требуется, ибо все есть в MSDN, причем на русском. Можно просто открыть проект, ткнуть в нужный элемент, нажать F1 и получить ответ в справке Microsoft:)

Этот пост публикуется возможно даже больше «для себя», просто, чтобы не забыть и знать, где искать, если что. Однако, надеюсь, что он пригодится и кому-нибудь кроме меня.

P.S.: Сколько же мороки у разработчиков при составлении документации к проектам, если описание такой примитивной программы занимает столько времени и места…

Полезная статья? Их будет больше, если вы поддержите меня!

https://money.yandex.ru/embed/small.xml?account=410011399843532&quickpay=small&yamoney-payment-type=on&button-text=06&button-size=l&button-color=orange&targets=%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D1%8E+%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82+lexpenz.com&default-sum=50&successURL=

Архив комментариев

1 комментарий из прежней версии блога. Архив закрыт для новых ответов.

  1. Молодчина! Отличная помощь для столкнувшихся с такой проблемой. Архив оказался весьма кстати, поскольку из куска кода понять все не получилось.