Warm tip: This article is reproduced from serverfault.com, please click

c#-如何使用.Net Core在单个实例中更改主窗口状态

(c# - how to change main window state in a single instance using .Net Core)

发布于 2020-11-28 14:33:55

我正在尝试仅将我的应用程序留给一个实例。

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

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

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我尝试使用调用窗口,MainWindow.WindowState = WindowState.Normal;但在调用中失败,并注意到错误System.Windows.Application.MainWindow.get返回null

Questioner
robert
Viewed
11
AmRo 2020-11-29 01:10:31

我在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();
        }
    }
}