单实例Windows窗体应用程序与最小化托盘
本文关键字:应用程序 最小化 窗体 Windows 实例 单实例 | 更新日期: 2023-09-27 18:16:58
我有一个示例WinForm应用程序名为" restore .exe"。在最小化其窗口时,它将移动到系统托盘并隐藏在任务栏中。如果我点击系统托盘中的通知图标,窗口将出现在前面。
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;
}
我的实际问题是,如果应用程序已经在运行,"恢复"方法正在运行,其中列出的所有操作都在运行,窗口出现在前面。但是在完成这些操作之后,窗口再次进入系统托盘。而不是坐在前面。
谁能提供一个解决方案吗?
创建单个实例
将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;
}
问题在于main()中if块的两个分支都创建了一个新表单,因此您没有对已经运行的表单做任何事情。
如果有一个程序的实例已经在运行(IsServiceManagerAlreadyRunning() == true?),你需要从第一个实例中找到窗口并激活它,而不是创建一个新的Form。
您可以尝试通过窗口标题或更复杂的解决方案来查找窗口。在Google上搜索"windows应用程序单个实例",返回了许多文章。
我想这就是你需要的:-
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();
}
}
}