在做WinFrom开发的时候,很多时候我们想只有一个例程(routine)在运行。就像是设计模式中的Single Pattern,其原理大致相同。
那么我们看一下Single Pattern的实现原理。
- publicclassSinglePattern
- {
- privatestaticSinglePatterninstance=null;
- publicstaticSinglePatternInstance()
- {
- if(instance==null)
- {
- instance=newSinglePattern();
- }
- returninstance;
- }
- }
在这样的一个最基本的单例模式中,使用了静态变量instance来保存SinglePattern的实例。无论如何在我们的应用程序中都只有一个分instance,并且以此确定了SinglePattern.Instance()方法返回的实例是单一实例。
那么我们又怎么在WinForm中,给Form创建单一的窗口呢?
比葫芦画瓢,我们需要寻找一个跟静态变量类似的东西来确认只有一份存在。
如何用文件实现WinFrom的单例在这儿就不多说了。举例说一下如何使用Mutex实现WinForm的单例。
- boolisNew=false;
- Mutexmutext=newMutex(true,"testFrom",outisNew);
当名字为testForm的Mutext存在时,isNew为False,否则为True。现在看来实现单例的WinFrom就有了理论依据。但是总部能再WinForm的构造函数中写这样的判断吧,这样只是完成了一个窗口的单例。我们现在想要是应用程序级别的单例。从何处下手呢?
不要着急Main()函数是所有应用程序的入口函数。这要在这里加入判断就行了。
- usingSystem;
- usingSystem.Collections.Generic;
- usingSystem.Linq;
- usingSystem.Windows.Forms;
- usingSystem.Runtime.InteropServices;
- usingSystem.Threading;
- usingSystem.Diagnostics;
- namespaceYoung.Winfrom.Singleton
- {
- staticclassProgram
- {
- //把句柄hWnd设置为以cmdShow的模式显示出来
- [DllImport("user32.dll",EntryPoint="ShowWindowAsync")]
- publicstaticexternintShowWindowAsync(IntPtrhWnd,intcmdShow);
- //把句柄hWnd放置到所有窗口的最前端
- [DllImport("user32.dll",EntryPoint="SetForegroundWindow")]
- publicstaticexternintSetForegroundWindow(IntPtrhWnd);
- staticMutexme;
- privateconstintSHOWNORMAL=1;//正常显示
- privateconstintCLOSE=0;//关闭
- privateconstintMINISIZE=2;//最小化
- privateconstintMAXSIZE=3;//最大化
- ///<summary>
- ///应用程序的主入口点。
- ///</summary>
- [STAThread]
- staticvoidMain()
- {
- boolisNew=false;
- me=newMutex(true,outisNew);
- if(!isNew)
- {
- Processpro=GetProcess();
- if(pro!=null)
- {
- IntPtrfromHandle=pro.MainWindowHandle;
- ShowWindowAsync(fromHandle,SHOWNORMAL);
- SetForegroundWindow(fromHandle);
- }
- return;
- }
- else
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(newForm1());
- }
- }
- staticProcessGetProcess()
- {
- Processpro=Process.GetCurrentProcess();
- stringcurrent=pro.MainModule.FileName;
- Process[]pros=Process.GetProcessesByName(pro.ProcessName);
- intl=pros.Length;
- foreach(Processpinpros)
- {
- if(p.MainModule.FileName.Equals(current,StringComparison.CurrentCultureIgnoreCase))
- {
- if(p.Id!=pro.Id)
- returnp;
- }
- }
- returnnull;
- }
- }
- }
上边的例子中使用了Windows的API,激活已经启动例程并将窗口移动到最顶端。