You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:01:19