1

私たちのアプリケーションには次の要件があります。アプリケーションが実行中で、アプリケーションを再起動する場合、新しいインスタンスを開く代わりに、最初のインスタンスをアクティブにする必要があります。

これを実現するために、メイン ルーチンで実行中のインスタンスが既に存在するかどうかを確認します。はいの場合、次のコマンドを使用して最初のインスタンスを前面に出します。

Microsoft.VisualBasic.Interaction.AppActivate(appIdentifier);

これまでのところ、すべてが期待どおりに機能しています。このソリューションの唯一の問題は、最初のインスタンスが最小化されている場合、アプリケーションを再起動すると、最初のインスタンスがアクティブになりますが、表示されない (まだ最小化されている) ことです。

これが私の質問です。インスタンスをアクティブ化して、最後の WindowState に戻るにはどうすればよいですか。私の解決策は、 Form.Activated イベントを購読し、 eventhandler メソッドで次のコードを実行することでした:

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

しかし、このソリューションでは、アプリケーションを最小化する前にアプリケーションが最大化された状態にあった場合、アプリケーションをアクティブ化した後にアプリケーションに戻らないという問題があります。

どうすればこれを解決できるか考えている人はいますか? 最後のwindowStateを取得する機会はありますか?

よろしくお願いします。

4

4 に答える 4

2

まず、Steve と StevenP に感謝します。今、私はあなたの両方の解決策に基づいて私のケースの方法を見つけました.

「stevenP」ソリューションを使用しなかった理由: これにより、1 つのケースを除き、すべて正常に動作します。アプリケーションが通常のサイズの状態で、最初のインスタンスを最小化せずにアプリケーションを再起動すると、最初のインスタンスが通常のサイズではなく最大化されたサイズで開きます。

今、私のソリューションは次のようになります(私が言ったように、それは2つのソリューションのマージです:-)):

インスタンスがすでに実行されている場合のメインルーチンで、私は呼び出します

 NativeMethods.ActivateWindow(appIdentifier);

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

最初に言ったように: 助けてくれた Steve と StevenP に感謝します! 私はそこの解決策だけを適応させ、同じ問題を抱えている他の人のためにここに投稿しました。

于 2012-03-23T12:19:46.770 に答える
1

最小化から以前の状態に復元するには、以前の状態が何であったかを知る必要があります。

これはフォームの拡張メソッドで、タスクバーのウィンドウをクリックした場合に使用する復元状態を Windows に要求します。つまり、Normal または Maximized です。

        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);
于 2012-03-22T21:43:49.210 に答える
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);
于 2012-03-22T14:55:48.420 に答える
0

これが私のために働いたものです。別のアプリケーションからウィンドウをアクティブ化しているため、Form オブジェクトにアクセスできないことに注意してください。また、WinForms ではなく WPF を使用していますが、使用したソリューションでは問題ありません。

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;
    }
于 2014-02-27T01:29:00.200 に答える