Windows.Forms: активировать приложение, которое уже запущено в правом FormWindowState - PullRequest
1 голос
/ 22 марта 2012

Наше приложение имеет следующее требование: если приложение запущено, и я снова запускаю приложение, вместо этого необходимо активировать первый экземпляр, чтобы открыть новый экземпляр.

Чтобы реализовать это, в основной процедуреЯ проверяю, есть ли уже запущенный экземпляр.Если да, я использую следующую команду, чтобы вывести первый экземпляр:

Microsoft.VisualBasic.Interaction.AppActivate(appIdentifier);

До сих пор все работает как положено.Единственная проблема с этим решением состоит в том, что в случае, если первый экземпляр свернут, при повторном запуске приложения первый экземпляр будет активным, но не видимым (все еще свернутым)

И это мой вопрос.Как я могу вернуться к последнему WindowState, активировав экземпляр.Мое решение состояло в том, чтобы подписаться на событие Form.Activation и выполнить следующий код в методе обработчика событий:

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

Но с этим решением у меня возникает проблема, заключающаяся в том, что если приложение находилось в развернутом состоянии до минимизацииприложение не возвращается к нему после активации.

Кто-нибудь знает, как я могу решить эту проблему?есть ли шанс получить последнее окно состояния?

Заранее спасибо за помощь!

Ответы [ 4 ]

2 голосов
/ 23 марта 2012

Во-первых, большое спасибо Стиву и Стивену. Теперь я нашел способ для моего дела, основанный на ваших обоих решениях.

Причина, по которой я не принял решение «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,
}

Как я сказал вначале: большое спасибо Стиву и Стивену за помощь! Я только адаптировал там решение и разместил его здесь для других с такой же проблемой.

1 голос
/ 23 марта 2012

Восстановите предыдущее состояние из свернутого, вы должны знать, что было в предыдущем состоянии.

Вот метод расширения формы, который запрашивает у 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 голосов
/ 27 февраля 2014

Вот что сработало для меня. Обратите внимание, что я активирую окно из другого приложения, поэтому у меня нет доступа к объекту 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;
    }
0 голосов
/ 22 марта 2012

Немного 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...