2012-03-22 62 views
1

我们的应用程序具有以下要求:如果应用程序正在运行并且我再次启动应用程序,则必须激活第一个实例才能打开一个新实例。Windows.Forms:激活已经在正确运行的应用程序FormWindowState

为了实现这一点,在主例程中我检查是否已经有一个正在运行的实例。如果是,我使用以下命令将第一个实例带到前面:

Microsoft.VisualBasic.Interaction.AppActivate(appIdentifier); 

到目前为止所有工作都按预期工作。 这个解决方案的唯一问题是,如果第一个实例被最小化,通过再次启动应用程序,第一个实例将是活动的,但不可见(仍然最小化)

这是我的问题。如何通过激活实例回到最后一个WindowState。 我的解决办法,认购Form.Activated事件,在事件处理方法执行以下代码:

if (MyForm.WindowState == FormWindowState.Minimized) 
    { 
     MyForm.WindowState = FormWindowState.Normal; 
    } 

但是这种解决方案我有问题,如果应用程序在最大化状态最小化前激活后,应用程序不会回到它。

有没有人知道我可以如何解决这个问题?有没有机会获得最后一个windowState?

在此先感谢您的帮助!

+0

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/a5bcfc8a-bf69-4bbc-923d-f30f9ecf5f64 – 2012-03-22 23:55:54

回答

2

首先,非常感谢Steve和StevenP。现在,我基于您的两种解决方案为我的案例找到了一种方法。

我之所以没有采用“stevenP”解决方案:除此之外,所有工作都正常。如果应用程序处于正常大小状态,然后再次启动应用程序而不使第一个实例最小化,则第一个实例将以最大化大小而不是正常大小打开。

现在我的解决方案看起来是这样的(就像我说的,这是两种解决方案:-)合并):已实例运行我打电话

NativeMethods.ActivateWindow(appIdentifier); 

在主程序的情况下,

静态NativeMethods-类:

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, 
} 

正如我在开始时说:感谢很多史蒂夫和StevenP的帮助!我只适应了那里的解决方案,并将其发布给其他人以解决同样的问题。

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); 
+0

谢谢!我会尝试! :-) – rhe1980 2012-03-22 15:32:33

1

不要恢复到最小化,从以前的状态,你必须知道rprevious状态是什么。

以下是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); 
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; 
    } 
相关问题