C#单实例程序优化:唤醒隐藏实例而非启动新实例
解决单实例检测时唤醒隐藏窗体的问题
步骤1:添加Windows API函数声明
在Program.cs文件顶部插入以下代码,用来调用系统级的窗口操作函数:
using System.Runtime.InteropServices; public class NativeMethods { [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); }
步骤2:修改单实例检测逻辑
把原代码else块里的提示框代码替换成以下内容,实现找到已隐藏的窗体并恢复显示:
else { // 查找已运行的Form1窗口,第二个参数填你自己窗体的标题 IntPtr existingWindow = NativeMethods.FindWindow(null, "Form1"); if (existingWindow != IntPtr.Zero) { // 恢复窗口显示(9代表还原最小化/隐藏的窗口) NativeMethods.ShowWindow(existingWindow, 9); // 将窗口放到前台 NativeMethods.SetForegroundWindow(existingWindow); } }
补充:自动恢复窗体位置
因为你之前把窗体挪到了屏幕外的(10000,10000),可以在Form1里加个激活事件,让窗体回到屏幕中心:
private void Form1_Activated(object sender, EventArgs e) { // 计算屏幕中心位置并恢复 this.Location = new Point( (Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2, (Screen.PrimaryScreen.WorkingArea.Height - this.Height) / 2 ); this.ShowInTaskbar = true; }
记得在Form1的构造函数里绑定这个事件:
public Form1() { InitializeComponent(); this.Activated += Form1_Activated; }
完整修改后的Program.cs示例
using System; using System.Windows.Forms; using System.Threading; using System.Runtime.InteropServices; namespace YourAppNamespace // 替换成你的项目命名空间 { public class NativeMethods { [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); } static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Mutex mutex = new Mutex(false, "MyUniqueMutexName"); try { if (mutex.WaitOne(0, false)) { Application.Run(new Form1()); } else { IntPtr existingWindow = NativeMethods.FindWindow(null, "Form1"); if (existingWindow != IntPtr.Zero) { NativeMethods.ShowWindow(existingWindow, 9); NativeMethods.SetForegroundWindow(existingWindow); } } } finally { mutex?.Close(); } } } }
注意:如果你的窗体标题不是
Form1,一定要把FindWindow的第二个参数改成你实际的窗体标题;要是标题会变化,也可以用窗体类名作为第一个参数(可以用Spy++工具查看类名)。
内容的提问来源于stack exchange,提问作者Ibrahim
相关产品推荐
相关产品推荐

