Search code examples
c#winformssingle-instance

Windows.Forms: Activate an application that is already running in right FormWindowState


Our application has the following requirement: If the application is running and I start the application again, the first instance has to be activated instead to open a new instance.

To realize this, in the main routine I check if there is already a running instance. If yes I use following command to bring in front the first instance:

Microsoft.VisualBasic.Interaction.AppActivate(appIdentifier);

Until now all works as expected. The only problem with this solution is that in case of the first instance is minimized, by start the application again the first instance will be active, but not visible (still minimized)

And this is my question. How can I go back to the last WindowState by activating the instance. My solution was, to subscribe for the Form.Activated event and execute following code in the eventhandler method:

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

But with this solution I have the problem, that if the application was in maximized-state before minimizing the application do not goes back to it after activate it.

Has anybody an idea how I can solve this? is there a chance to get the last windowState?

Thanks in advance for your help!


Solution

  • First, thanks a lot to Steve and StevenP. Now I found a way for my case based on your both solutions.

    The reason why I didn't took the "stevenP" solution: with this, all works fine unless in one case. If the application is in normal size state and then I start the application again without minimize the first instance the first instance will open in maximized size instead of normal size.

    Now my solution looks like this (like I said, it's a merge of the two solutions :-) ):

    In main routine in case that already an instance is running I call

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

    As I said at the beginning: Thanks a lot to Steve and StevenP for the help! I only adapted there solution and post it here for others with the same problem.