41

I am writing a Windows Forms Application in C#. I need to be able to bring it to the foreground. After some Googling and experimentation, I have a working solution that looks pretty hacky.

I would like to know the elegant way to do this, if there is one. I need the app to restore and come to the foreground whether it was minimized, or not minimized but in background.

Current code looks like this:

WindowState = FormWindowState.Minimized;
WindowState = FormWindowState.Normal;
BringToFront();
Focus();
D'Arcy Rittich
  • 167,292
  • 40
  • 290
  • 283
  • 3
    With an audio recording of Emeril Lagasse! BAM! – Ben M Sep 23 '09 at 01:04
  • 1
    Ok, after some Googling, I think that is funny. – D'Arcy Rittich Sep 23 '09 at 01:10
  • 3
    I normally hate people that say things like this, but seriously please don't make your app do this unless you have no say in the matter. Apps that steal focus should be Considered Harmful. – Coxy Sep 23 '09 at 01:25
  • 1
    @coxymla: I hear you and might say the same thing myself. In this case, I have complete say in the matter: this is for my own exclusive use, and I find it a really simple way to get my attention and provide input when event x has occurred. – D'Arcy Rittich Sep 23 '09 at 01:30
  • I updated my answer; I think form.Activate plus setting the window state gets you what you are asking for. – bobbymcr Sep 23 '09 at 01:58
  • See my solution [here](http://stackoverflow.com/a/22141725/505893). It works both for `Show()` and `ShowDialog()`. – bluish Mar 03 '14 at 08:17

12 Answers12

61

Have you tried Form.Activate?

This code seems to do what you want, by restoring the form to normal size if minimized and then activating it to set the focus:

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

this.Activate();

Warning: this is annoying! If it's just an app for your personal use, as you say, maybe you can live with it. :)

bobbymcr
  • 23,769
  • 3
  • 56
  • 67
  • 1
    I just tried this. Activate() will not work if the form is an MDI child form and the user is working with another application. – Jacob Seleznev Sep 23 '09 at 06:10
  • 5
    Also useful if you minimize to the System Tray and need to activate and bring to front on click when window is already in Normal state. – Robb Sadler Nov 04 '14 at 17:20
  • 1
    I also found [this](http://stackoverflow.com/questions/4410717/c-sharp-programmatically-unminimize-form) useful for restoring the form to its prior state (normal or maximised). – Giles Jul 06 '16 at 23:34
  • I found that on some machines Activate merely made the taskbar icon flash. – Robin Bennett Oct 09 '18 at 14:31
13

Note. Below I have copied the most voted answer in a linked question closed as a duplicate to this one. That answer is the only pure C# answer I've found that solves this problem.

this.WindowState = FormWindowState.Minimized;
this.Show();
this.WindowState = FormWindowState.Normal;

It always brings the desired window to the front of all the others.

Community
  • 1
  • 1
John
  • 5,735
  • 3
  • 46
  • 62
  • 1
    Maybe it's not beautiful, but in my (very specific) case, that was indeed the way to go. Thanks a lot for bringing this "up2 :-) – Xan-Kun Clark-Davis Dec 08 '15 at 21:59
  • 2
    Curiously, in one machine I could use just `this.Activate()`. And it wouldn't work in another machine (theoretically the same Windows 7 version). This answer solved the problem. – Daniel Möller Jul 11 '17 at 15:17
  • 1
    @Daniel, Agreed! The other answers did not work nearly as well for me, as this approach. – John Jul 11 '17 at 15:23
  • 1
    Thanks for this. It is SO ANNOYING that I had to resort to this. So appreciate the help :) – Missy Dec 14 '18 at 00:07
  • The problem with this is that the window is minimized and then brought back in to view. Because I am unable to reliably detect if the form is visible on the screen, this is messy in cases where the form is already visible on the screen. – Appleoddity Dec 22 '20 at 19:44
  • @Appleoddity, I've not noticed flickering with this approach in our GUI's. However, if you're getting flickering that totally sucks, and is worth a new question IMHO with a reproducible code demonstrating it. – John Dec 22 '20 at 23:30
9
private static class User32
{
    [DllImport("User32.dll")]
    internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    internal static readonly IntPtr InvalidHandleValue = IntPtr.Zero;
    internal const int SW_MAXIMIZE = 3;
}
public void Activate()
{
    Process currentProcess = Process.GetCurrentProcess();
    IntPtr hWnd = currentProcess.MainWindowHandle;
    if (hWnd != User32.InvalidHandleValue)
    {
        User32.SetForegroundWindow(hWnd);
        User32.ShowWindow(hWnd, User32.SW_MAXIMIZE);
    }
}
bluish
  • 26,356
  • 27
  • 122
  • 180
Jacob Seleznev
  • 8,013
  • 3
  • 24
  • 34
  • Hmm, that doesn't win any prizes for elegant, is there not a good native .Net way? – D'Arcy Rittich Sep 23 '09 at 01:35
  • From MSDN: "The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window". With this your application can force the window to the foreground, while the user working with another application. – Jacob Seleznev Sep 23 '09 at 05:52
  • This works for me, all other solutions did not work. – CodingBarfield Aug 28 '17 at 11:50
7

You can set .TopMost to true, call DoEvents(), and then set .TopMost back to false. It's still hackish, but if Activate and Show aren't working it's better than minimizing/re-showing.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • This does not work for me, at least not in the Visual Studio host debug environment. – D'Arcy Rittich Sep 23 '09 at 01:36
  • 2
    DoEvents can lead to all sorts of nastiness - I'd strongly advise against using it. – Jon Cage Sep 12 '14 at 15:57
  • 2
    @JonCage Definitely agree: http://stackoverflow.com/questions/11352301/how-to-use-doevents-without-being-evil/11352575#11352575 – Joel Coehoorn Sep 12 '14 at 19:10
  • 1
    If DoEvents is so evil then maybe M$ should have made sure that Show or BringToFront actually work so we don't have to rely on DoEvents for that. I had the same issue that a window I sent to the tray was always in the background when coming back and nothing but this worked. – BloodyRain2k Feb 07 '17 at 10:03
  • I found that even after setting TopMost back to false, the window would remain on top after the user clicked away (unless you click a menu), until it had received at least one click – Robin Bennett Oct 09 '18 at 14:35
3

After several attempts I found out working combination:

form.Show();
form.WindowState = FormWindowState.Normal;
form.Activate();
AlexThunder
  • 168
  • 11
2

After a lot of trial and error I got to this code. This is tested. The BringToFront method is called on your form after the focus has been passed on to it. This makes it pop up in front.

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);

public static bool BringToFrontCustom(Form f)
{
    bool toReturn = true;
    try
    {
        //This is the same as the name of the executable without the .exe at the end            
        Process[] processes = Process.GetProcessesByName("MyFormName");

        SetForegroundWindow(processes[0].MainWindowHandle);
        f.BringToFront();
    }
    catch(Exception e)
    {
         toReturn = false;
         MessageBox.Show("Something went wrong, Please bring the window to front manually");
    }
    return toReturn;
}
demoncrate
  • 390
  • 2
  • 14
1

Actually, just call Activate() inside Shown event.

In your Example.Designer.cs:

this.Shown += new System.EventHandler(this.Example_Shown);

In your Example.cs:

private void Example_Shown(object sender, EventArgs e)
{
    this.Activate();
}

This worked even if your form is being launch by another process (ex: a splash screen form running in a different thread).

codenamezero
  • 2,724
  • 29
  • 64
0

Setting Form.TopMost to true will force the form window to the foreground.

Jim Fell
  • 13,750
  • 36
  • 127
  • 202
0

set .TopMost = true

and use

ShowDialog()
Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
cortexm_0
  • 1
  • 1
0

I had a similar problem, to which

form.TopMost = true;
form.Activate();

was quite a satisfying solution.

But it's still not guaranteed that the form will have focus then, because TopMost might not always work, depending on how the user has interacted before with the windows in other processes:

TopMost does not work when used on Forms running in consecutively in different threads and closed by user code

Philip
  • 1
  • 1
0

As already stated in another response, one (of course unelegant) way to do this would be by using user32.dll and call the native methods, this can be valid if we are using some unlinked process or thread from the window caller, that was set in the main caller as a background window (eg: always on top for the window that we want topmost).

this was partially copied, but only for easyness:

public enum WindowPos : int
{
    HWND_NOTOPMOST=-2,
    HWND_TOPMOST=-1,
    HWND_TOP=0,
    HWND_BOTTOM=1
}
public enum WindowFlags : uint
{
    SWP_NOSIZE=0x0001,
    SWP_NOMOVE=0x0002,
    SWP_NOZORDER=0x0004,
    SWP_NOREDRAW=0x0008,
    SWP_NOACTIVATE=0x0010,
    SWP_FRAMECHANGED=0x0020,  /* The frame changed: send WM_NCCALCSIZE */
    SWP_SHOWWINDOW=0x0040,
    SWP_HIDEWINDOW=0x0080,
    SWP_NOCOPYBITS=0x0100,
    SWP_NOOWNERZORDER=0x0200,  /* Don't do owner Z ordering */
    SWP_NOSENDCHANGING=0x0400  /* Don't send WM_WINDOWPOSCHANGING */
}
public enum ShowWindowCommands : int
{
    SW_HIDE=0,
    SW_SHOWNORMAL=1,
    SW_NORMAL=1,
    SW_SHOWMINIMIZED=2,
    SW_SHOWMAXIMIZED=3,
    SW_MAXIMIZE=3,
    SW_SHOWNOACTIVATE=4,
    SW_SHOW=5,
    SW_MINIMIZE=6,
    SW_SHOWMINNOACTIVE=7,
    SW_SHOWNA=8,
    SW_RESTORE=9,
    SW_SHOWDEFAULT=10,
    SW_FORCEMINIMIZE=11,
    SW_MAX=11
}

private static class User32
{
    [DllImport("user32.dll")]
    internal static unsafe extern IntPtr SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    internal static unsafe extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    internal static unsafe extern bool SetWindowPos(IntPtr hWnd, int hWndPutAfter, int x, int y, int cx, int cy, uint flags);

    [DllImport("user32.dll")]
    internal static unsafe extern IntPtr SetFocus( IntPtr hWnd );
}
public void Activate()
{
    Process currentProcess = Process.GetCurrentProcess();
    IntPtr hWnd = currentProcess.MainWindowHandle;
    if (hWnd != IntPtr.Zero)
    {
        User32.SetWindowPos(hWnd, (int)WindowPos.Top, 0, 0, 0, 0, (uint)(WindowFlags.SWP_NOMOVE | WindowFlags.SWP_NOSIZE));
        User32.ShowWindow(hWnd, (int)ShowWindowCommands.SW_SHOW);
        User32.SetForegroundWindow(hWnd);
        User32.SetFocus( hWnd );
    }
}

For completeness I added most references from the constants that are available in the windows SDK

Sascha
  • 1
  • 2
-1

Instead of using windowstate minimize or topmost=false etc etc...

I have a Winform App... it launches an automation routine - I wanted the app minimized when the automation sequence is performed then presented again after the automation sequence was complete.

It was easy - just make the form not visible while the other process/thread/ whatever is running

 //hide the app

 this.Visible=false;

 //do something 

 some_form.ShowDialog();
 doSomethingHere();

 //reshow the app

 this.visible=true;  
Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53