none
Сворачивание в трей (в NotifyIcon) при запуске главной формы RRS feed

  • Вопрос

  • Стоит задача, при старте приложения сразу сворачивать его в трей.

    Изначально было реализовано нажатием кнопки, все работало замечательно.

    private void button1_Click(object sender, EventArgs e)
        {
          Hide();
        }
    

    Сейчас попробовал сделать так:

    private void Form1_Load(object sender, EventArgs e)
    {
    Hide();
    }
    

    Но работать отказывается - программа запускается и форму (Form1) все равно видно.

    Как же таки скрыть форму при запуске программы (а также, интересно, почему не работает приведенный выше код)? Заранее спасибо!


    C#, VS2010Pro, .NET PHP, DreamWeaver
    19 февраля 2011 г. 21:19

Ответы

  • Есть еще вариант с глушением сеттера Visible по показа из трея. Насчет сайдэффектов - не уверен. Работает и не мерцает на моем компьютере. Примерно так:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.Visible = false;
            this.IsVisibilityChangeAllowed = false;
        }

        bool IsVisibilityChangeAllowed { get; set; }

        protected override void SetVisibleCore(bool value)
        {
            if (this.IsVisibilityChangeAllowed)
            {
                base.SetVisibleCore(value);
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.IsVisibilityChangeAllowed = true;
            this.Show();
        }
    }
     

    My blog
    • Помечено в качестве ответа Abolmasov Dmitry 20 февраля 2011 г. 21:10
    20 февраля 2011 г. 0:29
  • Вот пример:

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication18
    {
      static class Program
      {
        private static Form1 form1 = null;
        private static NotifyIcon notifyIcon = null;
    
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          notifyIcon = new NotifyIcon();
          notifyIcon.Icon = Properties.Resources.MyIcon;
          notifyIcon.Click += notifyIcon_Click;
          notifyIcon.Visible = true;
          Application.Run();
        }
    
        private static void notifyIcon_Click(object sender, EventArgs e)
        {
          if (form1 == null || form1.IsDisposed)
            form1 = new Form1();
          if (!form1.Visible)
            form1.Show();
        }
      }
    }
    
    
    В нем предполагается, что иконка для значка в трее находится в ресурсе "MyIcon" приложения.

    Для выхода из приложения нужно будет вызвать метод Dispose() у значка в трее и Application.Exit().

    • Помечено в качестве ответа Abolmasov Dmitry 20 февраля 2011 г. 21:11
    20 февраля 2011 г. 13:11

Все ответы

  • Корректно работающим способом будет создание в методе Main класса Program элемента NotifyIcon и запуск Application.Run() без формы. При нажатии на NotifyIcon проверять, создана ли главная форма, и если нет, то создавать ее именно в этот момент.

    Весь инициализационный код (если он есть) нужно будет вынести из класса формы.

    Во всех остальных случаях форма будет промелькивать перед скрытием (и такое, кстати, нередко встречается в коммерческих приложениях).

    19 февраля 2011 г. 21:41
  • Можно еще  вынести этот код в таймер и присвоить значение периода 100, после чего таймер отключать.

    А причина показа в том что событие Load срабатывает до показа формы, т.е. вы пытаетесь скрыть окно, которое и так еще не появилось на экране. После чего происходит Form.Show() и естественно форма показывается на экране.

    19 февраля 2011 г. 22:34
  • Да, верно — насчет причин.

    Вариант с таймером будет приводить к мельканию окна.

    19 февраля 2011 г. 23:16
  • Есть еще вариант с глушением сеттера Visible по показа из трея. Насчет сайдэффектов - не уверен. Работает и не мерцает на моем компьютере. Примерно так:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.Visible = false;
            this.IsVisibilityChangeAllowed = false;
        }

        bool IsVisibilityChangeAllowed { get; set; }

        protected override void SetVisibleCore(bool value)
        {
            if (this.IsVisibilityChangeAllowed)
            {
                base.SetVisibleCore(value);
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.IsVisibilityChangeAllowed = true;
            this.Show();
        }
    }
     

    My blog
    • Помечено в качестве ответа Abolmasov Dmitry 20 февраля 2011 г. 21:10
    20 февраля 2011 г. 0:29
  • Алексей, буду крайне благодарен, если объясните как это сделать :) Новичок с c# совсем)

    У меня есть код (задан студией) в файле Program.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication18
    {
      static class Program
      {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new Form1());
        }
      }
    }
    

    Каким образом его надо модифицировать? Большое спасибо заранее)


    C#, VS2010Pro, .NET PHP, DreamWeaver
    20 февраля 2011 г. 12:47
  • В посте выше я привел полностью рабочий код, без мерцания и без выноса NotifyIcon из формы. Вы пробовали его использовать? Или просто поверили на слово, что "все остальные варианты некорректны"?
    My blog
    20 февраля 2011 г. 13:01
  • Вот пример:

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication18
    {
      static class Program
      {
        private static Form1 form1 = null;
        private static NotifyIcon notifyIcon = null;
    
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          notifyIcon = new NotifyIcon();
          notifyIcon.Icon = Properties.Resources.MyIcon;
          notifyIcon.Click += notifyIcon_Click;
          notifyIcon.Visible = true;
          Application.Run();
        }
    
        private static void notifyIcon_Click(object sender, EventArgs e)
        {
          if (form1 == null || form1.IsDisposed)
            form1 = new Form1();
          if (!form1.Visible)
            form1.Show();
        }
      }
    }
    
    
    В нем предполагается, что иконка для значка в трее находится в ресурсе "MyIcon" приложения.

    Для выхода из приложения нужно будет вызвать метод Dispose() у значка в трее и Application.Exit().

    • Помечено в качестве ответа Abolmasov Dmitry 20 февраля 2011 г. 21:11
    20 февраля 2011 г. 13:11
  • Алексей, вы не могли бы указать, чем именно некорректен мой вариант? И почему вместо переопределения метода стоит так наворачивать систему? Т.е. должны же быть какие-то аргументы, чтобы утвержать что все варианты, кроме вашего, неправильные.

    Может я действительно что-то пропустил - опыт в WinForms у меня не слишком обширный, да и код в последнее время редко пишу :(  


    My blog
    20 февраля 2011 г. 15:28
  • Я не утверждал, что Ваш вариант некорректен, он работает вполне корректно и выполняет поставленную автором задачу (признаюсь, говоря "во всех остальных случаях" я был неправ; следовало сказать "в большинстве других случаев").

    Единственное замечание, которое можно адресовать Вашему коду, это то, что вряд ли большинство разработчиков (особенно, начинающих) в курсе, что существует виртуальный метод SetVisibleCore в классе Form, и что он делает. Человек, разбирающийся с этим кодом, с большой долей вероятности обратится к MSDN, чтобы получить эту информацию. Я предпочитаю следовать принципу "Keep it simple" и явно выражать намерения программы, самым простым способом, пусть это и приводит к небольшому увеличению объема кода.

    Впрочем, и мой вариант тоже не без изъянов: нужно было сделать свойство для доступа к notifyIcon в классе Program, чтобы впоследствии можно было вызывать Dispose().

    Резюмируя: оба варианта, скорее всего, подойдут для решения задачи автора.

    20 февраля 2011 г. 15:45
  • Оба варианта верны, топик-стартер выберет, что ближе) Причина показа формы в изначальном варианте топик-стартера, была объяснена ниже Istorik-ом.


    Для связи [mail]
    20 февраля 2011 г. 21:10