首页 > 解决方案 > 如何使用 .Net Core 在单个实例中更改主窗口状态

问题描述

我试图让我的应用程序只保留一个实例。

代码工作正常,但我想操作已经打开的窗口。

当我打开多个实例时,如何将已经打开的窗口带到前面。

public partial class App : Application {

private static Mutex _mutex = null;

protected override void OnStartup(StartupEventArgs e)
{
    const string appName = "MyAppName";
    bool createdNew;

    _mutex = new Mutex(true, appName, out createdNew);

    if (!createdNew)
    {
        Application.Current.Shutdown();
    }

    base.OnStartup(e);
}          

}

OnStartup我试图调用窗口 usingMainWindow.WindowState = WindowState.Normal;但它在该调用中失败,注意到错误System.Windows.Application.MainWindow.get 返回 null

标签: c#wpf.net-core

解决方案


我在 WPF 中为单实例应用程序创建了一个示例项目。也许有帮助:

Wpf 单实例应用程序

您需要以下本机方法:

public static class NativeMethod
{
    public static IntPtr BroadcastHandle => (IntPtr)0xffff;
    public static int ReactivationMessage => RegisterWindowMessage("WM_SHOWME");

    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
}

在应用程序主窗口中添加窗口消息挂钩,当您收到激活消息时,您应该将主窗口置于其他窗口的顶部。像这样:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        RegisterWndProcCallback();
    }

    private void RegisterWndProcCallback()
    {
        var handle = new WindowInteropHelper(this).EnsureHandle();
        var hock = new HwndSourceHook(WndProc);
        var source = HwndSource.FromHwnd(handle);

        source.AddHook(hock);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == NativeMethod.ReactivationMessage)
            ReactivateMainWindow();

        return IntPtr.Zero;
    }

    private void ReactivateMainWindow()
    {
        if (WindowState == WindowState.Minimized)
            WindowState = WindowState.Normal;

        Topmost = !Topmost;
        Topmost = !Topmost;
    }
}

在应用启动时,您应该检查应用实例,如果需要,您应该向旧实例发送消息并激活它。像这样:

public partial class App
{
    private static readonly Mutex _singleInstanceMutex =
        new Mutex(true, "{40D7FB99-C91E-471C-9E34-5D4A455E35E1}");

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        if (_singleInstanceMutex.WaitOne(TimeSpan.Zero, true))
        {
            Current.MainWindow = new MainWindow();
            Current.MainWindow.Show();
            Current.MainWindow.Activate();

            _singleInstanceMutex.ReleaseMutex();
        }
        else
        {
            NativeMethod.PostMessage(
                NativeMethod.BroadcastHandle,
                NativeMethod.ReactivationMessage,
                IntPtr.Zero,
                IntPtr.Zero);

            Current.Shutdown();
        }
    }
}

推荐阅读