单实例Windows窗体应用程序,最小化到托盘

时间:2015-10-08 16:23:31

标签: c# .net winforms

我有一个名为" Restoring.exe"的示例WinForm应用程序。在最小化窗口的同时,它将移动到系统托盘并隐藏在任务栏中。如果我单击系统托盘中的通知图标,窗口将显示在前面。

public void notifyicon_MouseClick(object sender, System.EventArgs e)
{
    notifyicon.Visible = false;
    Show();
    Activate();
    TopMost = true;
    BringToFront();
    this.WindowState = FormWindowState.Normal;
}

但我的实际要求是,在第二次点击应用程序时,需要从系统托盘恢复应用程序。

为此,我尝试了下面的代码

的Program.cs:

static void Main()
{
    if (IsServiceManagerAlreadyRunning())
    {
        Form1 form1 = new Form1();
        form1.Restore();
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

Form1.cs中:

public void Restore()
{
    notifyicon.Visible = false;
    Show();
    Activate();
    TopMost = true;
    BringToFront();
    this.WindowState = FormWindowState.Normal;
} 

我的实际问题是,如果应用程序已在运行,则“恢复”'方法正在命中,其中列出的所有操作都在运行,窗口出现在前面。 但是在完成这些操作后,窗口再次进入系统托盘。不坐在前面。

有人可以为此提供解决方案吗?

3 个答案:

答案 0 :(得分:5)

制作单一实例

向您的项目添加对Microsoft.VisualBasic.dll的引用,并将此类添加到您的项目中:

using System;
using Microsoft.VisualBasic.ApplicationServices;
using System.Windows.Forms;

namespace Sample
{
    public class ApplicationController : WindowsFormsApplicationBase
    {
        private Form mainForm;
        public ApplicationController(Form form)
        {
            //We keep a reference to main form 
            //To run and also use it when we need to bring to front
            mainForm = form;
            this.IsSingleInstance = true;
            this.StartupNextInstance += this_StartupNextInstance;
        }

        void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e)
        {
            //Here we bring application to front
            e.BringToForeground = true;
            mainForm.ShowInTaskbar = true;
            mainForm.WindowState = FormWindowState.Minimized;
            mainForm.Show();
            mainForm.WindowState = FormWindowState.Normal;
        }

        protected override void OnCreateMainForm()
        {
            this.MainForm = mainForm;
        }
    }
}

然后在Program.cs使用ApplicationController运行程序:

using System;
using System.Windows.Forms;

namespace Sample
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            //create a controller and Pass an instance of your application main form
            var controller =  new Sample.ApplicationController(new YourMainForm());

            //Run application
            controller.Run(Environment.GetCommandLineArgs());
        }
    }
}

现在您的应用程序是单实例,当您单击您的exe文件时,而不是运行另一个实例,将现有实例放在前面。

使用NotifyIcon

在主窗体上放置NotifyIcon,然后在单击最小化按钮时隐藏窗口,并在单击通知图标时显示窗口,并且您可以处理这些事件:

//When click on notify icon, we bring the form to front
private void notifyIcon_Click(object sender, EventArgs e)
{
    this.ShowInTaskbar = true;
    this.WindowState = FormWindowState.Minimized;
    this.Show();
    this.WindowState = FormWindowState.Normal;
}

//here we check if the user minimized window, we hide the form
private void ApplicationMainForm_Resize(object sender, EventArgs e)
{
    if (this.WindowState == FormWindowState.Minimized)
    {
        this.ShowInTaskbar = false;
        this.Hide();
    }
}

//when the form is hidden, we show notify icon and when the form is visible we hide it
private void ApplicationMainForm_VisibleChanged(object sender, EventArgs e)
{
    this.notifyIcon1.Visible = !this.Visible;
}

答案 1 :(得分:1)

问题是main()中if块的两个分支都创建了一个新表单,因此你没有对已经运行的表单做任何事情。

如果程序的某个实例已在运行( IsServiceManagerAlreadyRunning() == true?),您需要从第一个实例中找到该窗口并将其激活,而不是创建新表单

您可以尝试按窗口标题或更复杂的解决方案查找窗口。在Google上搜索“Windows应用程序单个实例”会返回一些文章。

答案 2 :(得分:-1)

我认为这就像你需要的那样: -

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void Form1_ResizeBegin(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                this.Hide();
            }
        }

    }