要实现程序单实例运行并打开前一个实例有许多方法,如大多数网上的Process 方法。但,如果程序从IDE(像vs)运行,然后再双击bin/debug里的程序,运行了2个实例了。本人用的是Mutex来控制程序单实例运行,API操作前实例的窗体句柄来实现的。.Net里有Form的Handle属性来获取窗体句柄。
本人在vs2008中写的,效果:可行;最大最小化时双击会变为普通状态。
如有更好的方法,请大家拿出来研究。代码如下:
创建程序设置:
名称:w 类型:Int64 范围:用户 值:0
在Program.cs里:
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
using WindowsFormsApplication1.Properties; //加入项目设置
static class Program
{
#region Win32 API 函数
//该函数设置由不同线程产生的窗口的显示状态;
//如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零。
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
//该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。
//如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零。
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
// IsIconic、IsZoomed ------ 分别判断窗口是否已最小化、最大化
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool IsZoomed(IntPtr hWnd);
//获取当前系统中被激活的窗口
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
//获取指定窗口的进程 ID 或线程 ID
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
#endregion
private const int SW_SHOWNORMAL = 1;
private const int SW_RESTORE = 9;
[STAThread]
static void Main()
{
bool b;
string a = "1"; //名字任意
Mutex m = new Mutex(true, a, out b);
if (b)
{
m.ReleaseMutex();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
Settings s = new Settings();
IntPtr i = (IntPtr)s.w;
SetForegroundWindow(i);
if (IsIconic(i))
{
ShowWindowAsync(i, SW_RESTORE);
}
else
{
ShowWindowAsync(i, SW_SHOWNORMAL);
}
}
}
}
在Form1.cs里:(加入Load事件)
using WindowsFormsApplication3.Properties;
private void Form1_Load(object sender, EventArgs e)
{
Settings r = new Settings();
r.w = (Int64)this.Handle;
r.Save();
}
ok了.wpf也一样能行,方法一样,只不过是在Loaded事件中罢了.