我正在一个wpf应用程序上,而不是在用户关闭按钮时退出该应用程序,而是将其最小化到托盘上(类似于钉钉等客户端).
需要的是,如果用户忘记了该应用程序的一个实例,并尝试打开一个新实例,则必须关闭第二个实例,并将我的应用程序设置为前台应用程序.如果应用处于最小化状态(未隐藏),则可以执行此操作.我正在使用以下代码
Process currentProcess = Process.GetCurrentProcess();
var runningProcess = (from process in Process.GetProcesses()
where
process.Id != currentProcess.Id &&
process.ProcessName.Equals(
currentProcess.ProcessName,
StringComparison.Ordinal)
select process).FirstOrDefault();
if (runningProcess != null)
{
Application.Current.Shutdown();
ShowWindow(runningProcess.MainWindowHandle, 5);
ShowWindow(runningProcess.MainWindowHandle, 3);
}
当应用程序最小化时,它对于MainWindowHandle具有一些唯一的值.当我隐藏应用程序时,runningProcess的MainWindowHandle显示为0.我认为这就是为什么我的应用程序处于隐藏状态时无法打开
原因一:
WPF的WIN32窗口的行为与标准WIN32窗口略有不同.它的类名称由单词HwndWrapper,创建该单词的AppDomain的名称以及唯一的随机变量Guid(每次启动都会更改)组成,例如HwndWrapper [WpfApp.exe ;; 4d426cdc-31cf-4e4c-88c7-ede846ab6d44].
原因二:
使用该Hide()方法隐藏WPF的窗口时,它将在内部调用UpdateVisibilityProperty(Visibility.Hidden),进而将内部可见性标志设置UIElement为false.当我们调用的Show()方法时WPF Window,会UpdateVisibilityProperty(Visibility.Visible)被调用,并且的内部可见性标志会UIElement被切换.
当我们使用来显示WPF窗口时ShowWindow(),UpdateVisibilityProperty()不会触发该方法,因此内部可见性标记不会反转(这将导致该窗口以黑色背景显示).
通过查看WPF Window内部实现,无需调用Show()orHide()方法即可切换内部可见性标志的唯一方法是发送WM_SHOWWINDOW消息.
增加以下代码
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
if (runningProcess.MainWindowHandle == IntPtr.Zero) {
var handle = GetWindowHandle(runningProcess.Id, runningProcess.MainWindowTitle);
if (handle != IntPtr.Zero) {
// show window
ShowWindow(handle, 5);
// send WM_SHOWWINDOW message to toggle the visibility flag
SendMessage(handle, 0x0018, IntPtr.Zero, new IntPtr(3));
}
}