因为正好有网友问到我这个问题。所以做了一个简单的Demo实现了 应用程序的单例 效果。
简单的说。APP1启动后,最小化到任务栏。这时候 再次双击APP1.exe,进行下判断,判断APP1已经启动,那么启动的 第二个应用发送消息给已经起懂的APP1,然后自己结束。APP1接收到消息后,Show出来。 就这么个意思。
当然,根据需要可以住家大小设置,Active设置 等等,不在详述。
用到知识点。
Windows下的 应用间消息通讯。
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
FindWindow方法,查找应用程序中窗口句柄。lpClassName 实际上是类名,不知道可以用null,lpWindowsName,是窗口标题,一般用这个就可以获得窗口句柄了。
FindWindowEx是具体获取窗口上的某一个控件的句柄,hwndParent是窗口句柄引用,hwndChildAfter是子窗口句柄(如果是MDI这样),lpszClass是类名,lpWindowName是控件名称。例如Login按钮。如果想直接调用窗体某按钮事件,可以用。这里没用到。
PostMessage,发送消息方法。hwnd, 对象句柄,wMsg 消息值,wParam,lParam一般不用,可以用IntPtr.Zero代替。
来看Program.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
// WindowsFormsApp2.exe
if(CheckExist())
{
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
static bool CheckExist()
{
Process[] app = Process.GetProcessesByName("WindowsFormsApp2");
if (app.Length > 1)
{
MessageBox.Show("请关闭已经启动的程序后再进行尝试");
PostMessage();
return true;
}
else
{
return false;
}
}
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
static void PostMessage()
{
IntPtr hwnd_win;
hwnd_win = FindWindow(null, "Form1"); // 窗口标题
const int BM_CLICK = 0x00F5; // 命令代码
PostMessage(hwnd_win, BM_CLICK, IntPtr.Zero, IntPtr.Zero); // 发送消息
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.Hide();
notifyIcon1.Visible = true;
e.Cancel = true;
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.Show();
notifyIcon1.Visible = false;
}
// 系统消息重写
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case 0x00F5:
//收到指定消息,执行
this.Show();
notifyIcon1.Visible = false;
break;
default:
base.DefWndProc(ref m);//一定要调用基类函数,以便系统处理其它消息。
break;
}
}
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
Form1上实现了一个关闭最小化到任务栏功能。
DefWndProc方法是C#的Winfrom窗体中用来接受并处理系统消息的入口。这里添加了自定义消息的处理分支。
这时候再打开一个应用程序的时候,会通过Process判断是否已经开过了,开过了的话,PostMessage给第一个应用。然后自己关闭。第一个应用重新Show出来。
简单的Demo。
Demo下载
以上