Opening a WinForms Form with TopMost = true but not having it steal focus?
Asked Answered
F

7

20

I have a form that pops up on a user's screen and has TopMost=true, but it steals the focus. How can I get it to not steal focus when it first appears?

Flyte answered 16/9, 2010 at 19:9 Comment(3)
+1: I hate windows that steal the focus!Instate
If it's possible, I bet Raymond Chen wrote about it: blogs.msdn.com/b/oldnewthingInstate
I'm surprised this isn't something just built into WinForms...Flyte
B
6

Paste this code in your form:

protected override bool ShowWithoutActivation
{
    get { return true; }
}
Busybody answered 16/9, 2010 at 19:31 Comment(4)
It does not work in VS2008 when TopMost is set to True. I will try it on VS2010 now.Oxycephaly
Still doesn't work in VS 2010. Only works when TopMost on the popup form is set to false.Oxycephaly
Oh rats, that's true, TopMost messes this up. Won't work in VS2010 either. You'll have to P/Invoke SetWindowPos() with HWND_TOPMOST and SWP_NOACTIVATE. Use pinvoke.net for the declarations.Busybody
@Soo: Not sure how you got it to work as it is a well known bug. @Hans: +1 on the comment adding the mentioning of P/Invoke to solve that issue.Oxycephaly
D
17

This is what worked for me. It provides TopMost but without focus-stealing.

    protected override bool ShowWithoutActivation
    {
       get { return true; }
    }

    private const int WS_EX_TOPMOST = 0x00000008;
    protected override CreateParams CreateParams
    {
       get
       {
          CreateParams createParams = base.CreateParams;
          createParams.ExStyle |= WS_EX_TOPMOST;
          return createParams;
       }
    }

Remember to omit setting TopMost in Visual Studio designer, or elsewhere.

This is stolen, err, borrowed, from here (click on Workarounds):

https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost

Denaedenarius answered 9/8, 2014 at 14:11 Comment(2)
this link is also deadFactorial
@FactorMystic Eh, late but Archive.org link.Sociality
B
6

Paste this code in your form:

protected override bool ShowWithoutActivation
{
    get { return true; }
}
Busybody answered 16/9, 2010 at 19:31 Comment(4)
It does not work in VS2008 when TopMost is set to True. I will try it on VS2010 now.Oxycephaly
Still doesn't work in VS 2010. Only works when TopMost on the popup form is set to false.Oxycephaly
Oh rats, that's true, TopMost messes this up. Won't work in VS2010 either. You'll have to P/Invoke SetWindowPos() with HWND_TOPMOST and SWP_NOACTIVATE. Use pinvoke.net for the declarations.Busybody
@Soo: Not sure how you got it to work as it is a well known bug. @Hans: +1 on the comment adding the mentioning of P/Invoke to solve that issue.Oxycephaly
D
2

You can set:

this.TopMost = True;

on Load event of that form.

It's OK with me!

Delegate answered 11/4, 2014 at 8:50 Comment(1)
dont forget to disable the .topmost on the IDE first though - works like a charmClotheshorse
C
2

You can do it like this:

    private const int SW_SHOWNOACTIVATE = 4;
    private const int HWND_TOPMOST = -1;
    private const uint SWP_NOACTIVATE = 0x0010;

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    private static extern bool SetWindowPos(
         int hWnd,             // Window handle
         int hWndInsertAfter,  // Placement-order handle
         int X,                // Horizontal position
         int Y,                // Vertical position
         int cx,               // Width
         int cy,               // Height
         uint uFlags);         // Window positioning flags

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow);

    public static void ShowInactiveTopmost(System.Windows.Forms.Form frm)
    {
        try
        {
            ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
            SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
            frm.Left, frm.Top, frm.Width, frm.Height,
            SWP_NOACTIVATE);
        }
        catch (System.Exception ex)
        {
            // error handling
        }
    }
Cryolite answered 11/4, 2014 at 9:4 Comment(0)
O
1

I tested the below code using a timer on form1 to instantiate and show form2 with form1 as owner.

In form2's Shown event I then set focus to the owner, which is the current active form.

I have a textbox on form1 and was able to continuesly write in the textbox without loosing focus during this process.

My timer code in form1:

private void timer1_Tick(object sender, EventArgs e)
{
    Form2 popup = new Form2();
    popup.TopMost = true;
    popup.Show(this);
    timer1.Enabled = false;
}

My code in the Shown event of form2:

private void Form2_Shown(object sender, EventArgs e)
{
    this.Owner.Focus();
}

You can do this or simply set TopMost to false and use the override of ShowWithoutActivation as Hans Passant stated.

Edit: (Or use p/invoke as seen in Hans Passant's additional comment I missed while I wrote this)

Oxycephaly answered 16/9, 2010 at 20:4 Comment(0)
G
1

I came across the same problem. I'm not using C# but C++. I figure this could be useful anyways:

Using windows.h:

BOOL WINAPI SetWindowPos(
  __in      HWND hWnd,
  __in_opt  HWND hWndInsertAfter,
  __in      int X,
  __in      int Y,
  __in      int cx,
  __in      int cy,
  __in      UINT uFlags
);

Passing the flag SWP_NOACTIVATE to the uFlags argument worked for me.

Giuseppinagiustina answered 10/5, 2012 at 3:24 Comment(0)
G
0

Instead of writing .setfocus()in _activated event; write it to .shown event of the form.

Grandmotherly answered 25/1, 2016 at 10:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.