我们的应用程序具有以下要求:如果应用程序正在运行并且我再次启动应用程序,则必须激活第一个实例,而不是打开新实例。
为了实现这一点,在主例程中我检查是否已经有一个正在运行的实例。如果是,我使用以下命令将第一个实例带到前面:
Microsoft.VisualBasic.Interaction.AppActivate(appIdentifier);
到目前为止,所有工作都按预期进行。 此解决方案的唯一问题是,在第一个实例最小化的情况下,通过再次启动应用程序,第一个实例将处于活动状态,但不可见(仍然最小化)
这是我的问题。如何通过激活实例返回到最后一个WindowState。 我的解决方案是,订阅Form.Activated事件并在eventhandler方法中执行以下代码:
if (MyForm.WindowState == FormWindowState.Minimized)
{
MyForm.WindowState = FormWindowState.Normal;
}
但是使用这个解决方案我遇到了问题,如果应用程序在最小化应用程序之前处于最大化状态,则在激活它之后不会返回到它。
有人知道如何解决这个问题吗?有没有机会获得最后一个windowState?
提前感谢您的帮助!
答案 0 :(得分:2)
首先,非常感谢Steve和StevenP。现在,我根据您的两种解决方案为我的案例找到了一种方法。
我没有采用“stevenP”解决方案的原因:除非在一个案例中,否则一切正常。如果应用程序处于正常大小状态,然后我再次启动应用程序而不最小化第一个实例,则第一个实例将以最大化大小而不是正常大小打开。
现在我的解决方案看起来像这样(就像我说的,这是两个解决方案的合并:-)):
在已经运行实例的情况下的主例程中,我调用
NativeMethods.ActivateWindow(appIdentifier);
static NativeMethods- class:
public static void ActivateWindow(string appIdentifier)
{
var process = Process.GetProcesses().
FirstOrDefault(actual => actual.MainWindowTitle == appIdentifier);
if (process == null)
{
return;
}
var mainWin = process.MainWindowHandle;
var placement = new WindowPlacement();
placement.Length = Marshal.SizeOf(placement);
GetWindowPlacement(mainWin, ref placement);
if (placement.ShowCmd == SW_SHOWMINIMIZED)
{
ShowWindow(mainWin, (uint)WindowShowStyle.Restore);
}
else
{
Interaction.AppActivate(appIdentifier);
}
}
internal struct WindowPlacement
{
internal int Length;
internal int Flags;
internal int ShowCmd;
internal Point MinPosition;
internal Point MaxPosition;
internal Rectangle NormalPosition;
}
internal enum WindowShowStyle : uint
{
Hide = 0,
ShowNormal = 1,
ShowMinimized = 2,
ShowMaximized = 3,
Restore = 9,
}
正如我在开始时所说:非常感谢Steve和StevenP的帮助!我只是在那里修改了解决方案并将其发布给其他有同样问题的人。
答案 1 :(得分:1)
从最小化恢复到以前的状态,你必须知道上一个状态是什么。
这是Form的扩展方法,如果您单击任务栏中的窗口,它将向Windows询问它将使用的还原状态。也就是说,正常或最大化。
public static void Restore(this Form form)
{
if (form.WindowState == FormWindowState.Minimized)
{
var placement = new WindowPlacement();
placement.length = Marshal.SizeOf(placement);
NativeMethods.GetWindowPlacement(form.Handle, ref placement);
if ((placement.flags & RESTORETOMAXIMIZED) == RESTORETOMAXIMIZED)
form.WindowState = FormWindowState.Maximized;
else
form.WindowState = FormWindowState.Normal;
}
form.Show();
}
public struct WindowPlacement
{
public int length;
public int flags;
public int showCmd;
public Point ptMinPosition;
public Point ptMaxPosition;
public Rectangle rcNormalPosition;
}
public const int RESTORETOMAXIMIZED = 0x2;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);
答案 2 :(得分:0)
一点PInvoke可以解决您的问题:
DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
/// <summary>
/// Enumeration of the different ways of showing a window using
/// ShowWindow</summary>
private enum WindowShowStyle : uint
{
Hide = 0,
ShowNormal = 1,
ShowMinimized = 2,
ShowMaximized = 3,
// Many more, but this one seems to be the one required
/// <summary>
/// Activates and displays the window. If the window is
/// minimized or maximized, the system restores it to its original size
/// and position. An application should specify this flag when restoring
/// a minimized window.
/// </summary>
/// <remarks>See SW_RESTORE</remarks>
Restore = 9
}
IntPtr mainWin = Process.GetProcessByID(appIdentifier).MainWindowHandle;
ShowWindow(mainWin, WindowShowStyle.Restore);
答案 3 :(得分:0)
这对我有用。请注意,我正在从其他应用程序激活窗口,因此我无法访问Form对象。我也在使用WPF而不是WinForms,尽管它对我使用的解决方案并不重要:
internal static class NativeMethods
{
public static void ActivateWindow(IntPtr windowHandle)
{
var placement = new WindowPlacement();
placement.Length = Marshal.SizeOf(placement);
GetWindowPlacement(windowHandle, ref placement);
if (placement.ShowCmd == (uint)WindowShowStyle.ShowMinimized)
{
ShowWindow(windowHandle, (uint)WindowShowStyle.Restore);
}
else
{
ShowWindow(windowHandle, placement.ShowCmd);
}
SetForegroundWindow(windowHandle);
}
private struct WindowPlacement
{
internal int Length;
internal int Flags;
internal uint ShowCmd;
internal Point MinPosition;
internal Point MaxPosition;
internal Rectangle NormalPosition;
}
private enum WindowShowStyle : uint
{
Hide = 0,
ShowNormal = 1,
ShowMinimized = 2,
ShowMaximized = 3,
Restore = 9,
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("User32.dll")]
private static extern IntPtr SetForegroundWindow(IntPtr hWnd);
}
这就是我调用ActivateWindow方法(减去我的日志代码)的方法:
private bool GiveFocusToAnotherProcess(Process runningProcess)
{
try
{
NativeMethods.ActivateWindow(runningProcess.MainWindowHandle);
}
catch (Exception ex)
{
return false;
}
return true;
}