#c# #wpf #.net-core
#c# #wpf #.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
я попытался вызвать окно с помощью MainWindow.WindowState = WindowState.Normal;
, но в этом вызове произошел сбой, отметив систему ошибок.Windows.Приложение.MainWindow.get возвращает значение null.
Комментарии:
1. Используйте Win32
PostMessage
из дублирующего дочернего процесса для отправки сообщения исходному процессу (через его дескриптор главного окна).
Ответ №1:
Я создал пример проекта для приложения с одним экземпляром в 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();
}
}
}