在做WinFrom开发的时候,很多时候我们想只有一个例程(routine)在运行。就像是设计模式中的Single Pattern,其原理大致相同。
那么我们看一下Single Pattern的实现原理。
- public class SinglePattern
- {
- private static SinglePattern instance = null;
- public static SinglePattern Instance()
- {
- if (instance == null)
- {
- instance = new SinglePattern();
- }
- return instance;
- }
- }
在这样的一个最基本的单例模式中,使用了静态变量instance来保存SinglePattern的实例。无论如何在我们的应用程序中都只有一个分instance,并且以此确定了SinglePattern.Instance()方法返回的实例是单一实例。
那么我们又怎么在WinForm中,给Form创建单一的窗口呢?
比葫芦画瓢,我们需要寻找一个跟静态变量类似的东西来确认只有一份存在。
- 文件系统中的文件,统一路径下没有重名的文件(包含扩展名)。
- 多线程中的Mutex,在操作系统级别也是唯一的。
如何用文件实现WinFrom的单例在这儿就不多说了。举例说一下如何使用Mutex实现WinForm的单例。
- bool isNew = false;
- Mutex mutext = new Mutex(true, "testFrom", out isNew);
当名字为testForm的Mutext存在时,isNew为False,否则为True。现在看来实现单例的WinFrom就有了理论依据。但是总部能再WinForm的构造函数中写这样的判断吧,这样只是完成了一个窗口的单例。我们现在想要是应用程序级别的单例。从何处下手呢?
不要着急Main()函数是所有应用程序的入口函数。这要在这里加入判断就行了。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Windows.Forms;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Diagnostics;
- namespace Young.Winfrom.Singleton
- {
- static class Program
- {
- //把句柄hWnd设置为以cmdShow的模式显示出来
- [DllImport("user32.dll", EntryPoint = "ShowWindowAsync")]
- public static extern int ShowWindowAsync(IntPtr hWnd, int cmdShow);
- //把句柄hWnd放置到所有窗口的最前端
- [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
- public static extern int SetForegroundWindow(IntPtr hWnd);
- static Mutex me;
- private const int SHOWNORMAL = 1; //正常显示
- private const int CLOSE = 0; //关闭
- private const int MINISIZE = 2; //最小化
- private const int MAXSIZE = 3; //最大化
- /// <summary>
- /// 应用程序的主入口点。
- /// </summary>
- [STAThread]
- static void Main()
- {
- bool isNew = false;
- me = new Mutex(true, "testFrom", out isNew);
- if (!isNew)
- {
- Process pro = GetProcess();
- if (pro != null)
- {
- IntPtr fromHandle = pro.MainWindowHandle;
- ShowWindowAsync(fromHandle, SHOWNORMAL);
- SetForegroundWindow(fromHandle);
- }
- return;
- }
- else
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new Form1());
- }
- }
- static Process GetProcess()
- {
- Process pro = Process.GetCurrentProcess();
- string current = pro.MainModule.FileName;
- Process[] pros = Process.GetProcessesByName(pro.ProcessName);
- int l = pros.Length;
- foreach (Process p in pros)
- {
- if (p.MainModule.FileName.Equals(current, StringComparison.CurrentCultureIgnoreCase))
- {
- if (p.Id != pro.Id)
- return p;
- }
- }
- return null;
- }
- }
- }
上边的例子中使用了Windows的API,激活已经启动例程并将窗口移动到最顶端。
转载于:https://blog.51cto.com/official/663293