Show a Form without stealing focus?

C#.NetWinforms

C# Problem Overview


I'm using a Form to show notifications (it appears at the bottom right of the screen), but when I show this form it steals the focus from the main Form. Is there a way to show this "notification" form without stealing focus?

C# Solutions


Solution 1 - C#

Hmmm, isn't simply overriding Form.ShowWithoutActivation enough?

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

And if you don't want the user to click this notification window either, you can override CreateParams:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams baseParams = base.CreateParams;

    const int WS_EX_NOACTIVATE = 0x08000000;
    const int WS_EX_TOOLWINDOW = 0x00000080;
    baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );

    return baseParams;
  }
}

Solution 2 - C#

Stolen from PInvoke.net's ShowWindow method:

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

[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
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

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

static void ShowInactiveTopmost(Form frm)
{
     ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
     SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
     frm.Left, frm.Top, frm.Width, frm.Height,
     SWP_NOACTIVATE);
}

(Alex Lyman answered this, I'm just expanding it by directly pasting the code. Someone with edit rights can copy it over there and delete this for all I care ;) )

Solution 3 - C#

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

Solution 4 - C#

If you're willing to use Win32 P/Invoke, then you can use the ShowWindow method (the first code sample does exactly what you want).

Solution 5 - C#

Doing this seems like a hack, but it seems to work:

this.TopMost = true;  // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top

Edit: Note, this merely raises an already created form without stealing focus.

Solution 6 - C#

The sample code from pinvoke.net in Alex Lyman/TheSoftwareJedi's answers will make the window a "topmost" window, meaning that you can't put it behind normal windows after it's popped up. Given Matias's description of what he wants to use this for, that could be what he wants. But if you want the user to be able to put your window behind other windows after you've popped it up, just use HWND_TOP (0) instead of HWND_TOPMOST (-1) in the sample.

Solution 7 - C#

In WPF you can solve it like this:

In the window put these attributes:

<Window
    x:Class="myApplication.winNotification"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Notification Popup" Width="300" SizeToContent="Height"
  WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>

The last one attribute is the one you need ShowActivated="False".

Solution 8 - C#

I have something similar, and I simply show the notification form and then do

this.Focus();

to bring the focus back on the main form.

Solution 9 - C#

You might want to consider what kind of notification you would like to display.

If it's absolutely critical to let the user know about some event, using Messagebox.Show would be the recommended way, due to its nature to block any other events to the main window, until the user confirms it. Be aware of pop-up blindness, though.

If it's less than critical, you might want to use an alternative way to display notifications, such as a toolbar on the bottom of the window. You wrote, that you display notifications on the bottom-right of the screen - the standard way to do this would be using a balloon tip with the combination of a system tray icon.

Solution 10 - C#

Create and start the notification Form in a separate thread and reset the focus back to your main form after the Form opens. Have the notification Form provide an OnFormOpened event that is fired from the Form.Shown event. Something like this:

private void StartNotfication()
{
  Thread th = new Thread(new ThreadStart(delegate
  {
    NotificationForm frm = new NotificationForm();
    frm.OnFormOpen += NotificationOpened;
    frm.ShowDialog();
  }));
  th.Name = "NotificationForm";
  th.Start();
} 

private void NotificationOpened()
{
   this.Focus(); // Put focus back on the original calling Form
}

You can also keep a handle to your NotifcationForm object around so that it can be programmatically closed by the main Form (frm.Close()).

Some details are missing, but hopefully this will get you going in the right direction.

Solution 11 - C#

This works well.

See: OpenIcon - MSDN and SetForegroundWindow - MSDN

using System.Runtime.InteropServices;

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

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

public static void ActivateInstance()
{
    IntPtr hWnd = IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;

    // Restore the program.
    bool result = OpenIcon(hWnd); 
    // Activate the application.
    result = SetForegroundWindow(hWnd);

    // End the current instance of the application.
    //System.Environment.Exit(0);    
}

Solution 12 - C#

You can handle it by logic alone too, although I have to admit that the suggestions above where you end up with a BringToFront method without actually stealing focus is the most elegant one.

Anyhow, I ran into this and solved it by using a DateTime property to not allow further BringToFront calls if calls were made already recently.

Assume a core class, 'Core', which handles for example three forms, 'Form1, 2, and 3'. Each form needs a DateTime property and an Activate event that call Core to bring windows to front:

internal static DateTime LastBringToFrontTime { get; set; }

private void Form1_Activated(object sender, EventArgs e)
{
    var eventTime = DateTime.Now;
    if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
        Core.BringAllToFront(this);
    LastBringToFrontTime = eventTime;
}

And then create the work in the Core Class:

internal static void BringAllToFront(Form inForm)
{
    Form1.BringToFront();
    Form2.BringToFront();
    Form3.BringToFront();
    inForm.Focus();
}

On a side note, if you want to restore a minimized window to its original state (not maximized), use:

inForm.WindowState = FormWindowState.Normal;

Again, I know this is just a patch solution in the lack of a BringToFrontWithoutFocus. It is meant as a suggestion if you want to avoid the DLL file.

Solution 13 - C#

I don't know if this is considered as necro-posting, but this is what I did since I couln't get it working with user32's "ShowWindow" and "SetWindowPos" methods. And no, overriding "ShowWithoutActivation" doesn't work in this case since the new window should be always-on-top. Anyway, I created a helper method that takes a form as parameter; when called, it shows the form, brings it to the front and makes it TopMost without stealing the focus of the current window (apparently it does, but the user won't notice).

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

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

    public static void ShowTopmostNoFocus(Form f)
    {
        IntPtr activeWin = GetForegroundWindow();

        f.Show();
        f.BringToFront();
        f.TopMost = true;

        if (activeWin.ToInt32() > 0)
        {
            SetForegroundWindow(activeWin);
        }
    }

Solution 14 - C#

I know it may sound stupid, but this worked:

this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();

Solution 15 - C#

I needed to do this with my window TopMost. I implemented the PInvoke method above but found that my Load event wasn't getting called like Talha above. I finally succeeded. Maybe this will help someone. Here is my solution:

		form.Visible = false;
		form.TopMost = false;
		ShowWindow(form.Handle, ShowNoActivate);
		SetWindowPos(form.Handle, HWND_TOPMOST,
			form.Left, form.Top, form.Width, form.Height,
			NoActivate);
		form.Visible = true;	//So that Load event happens

Solution 16 - C#

You don't need to make it anywhere near as complicated.

a = new Assign_Stock(); 
a.MdiParent = this.ParentForm;
a.Visible = false;   //hide for a bit.                 
a.Show(); //show the form. Invisible form now at the top.
this.Focus(); //focus on this form. make old form come to the top.
a.Visible = true; //make other form visible now. Behind the main form.

Solution 17 - C#

enter image description here

Github Sample

Form.ShowWithoutActivation Property

Add this in your child form class

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

Working Code

Form2

   public partial class Form2 : Form
    {
        Form3 c;
        public Form2()
        {
            InitializeComponent();
             c = new Form3();
        }

        private void textchanged(object sender, EventArgs e)
        {


            c.ResetText(textBox1.Text.ToString());
            c.Location = new Point(this.Location.X+150, this.Location.Y);
            c .Show();

//removethis
//if mdiparent 2 add this.focus() after show form

            c.MdiParent = this.MdiParent;
            c.ResetText(textBox1.Text.ToString());
            c.Location = new Point(this.Location.X+150, this.Location.Y);
            c .Show();
           this.Focus();
////-----------------


        }


       
    }

Form3

   public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
            //ShowWithoutActivation = false;
        }
        protected override bool ShowWithoutActivation
        {
            get { return true; }
        }


        internal void ResetText(string toString)
        {
            label2.Text = toString;
        }

     
    }

Solution 18 - C#

When you create a new form using

Form f = new Form();
f.ShowDialog();

it steals focus because your code can't continue executing on the main form until this form is closed.

The exception is by using threading to create a new form then Form.Show(). Make sure the thread is globally visible though, because if you declare it within a function, as soon as your function exits, your thread will end and the form will disappear.

Solution 19 - C#

Figured it out: window.WindowState = WindowState.Minimized;.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTuteView Question on Stackoverflow
Solution 1 - C#Martin PlanteView Answer on Stackoverflow
Solution 2 - C#TheSoftwareJediView Answer on Stackoverflow
Solution 3 - C#RenniePetView Answer on Stackoverflow
Solution 4 - C#Alex LymanView Answer on Stackoverflow
Solution 5 - C#Matthew ScharleyView Answer on Stackoverflow
Solution 6 - C#MicahView Answer on Stackoverflow
Solution 7 - C#ZiketoView Answer on Stackoverflow
Solution 8 - C#pkrView Answer on Stackoverflow
Solution 9 - C#Silver DragonView Answer on Stackoverflow
Solution 10 - C#Bob NadlerView Answer on Stackoverflow
Solution 11 - C#AerikView Answer on Stackoverflow
Solution 12 - C#MetaView Answer on Stackoverflow
Solution 13 - C#DomiView Answer on Stackoverflow
Solution 14 - C#HasanView Answer on Stackoverflow
Solution 15 - C#Steven CvetkoView Answer on Stackoverflow
Solution 16 - C#Antony CartwrightView Answer on Stackoverflow
Solution 17 - C#lavaView Answer on Stackoverflow
Solution 18 - C#FryView Answer on Stackoverflow
Solution 19 - C#Pawel PawlowskiView Answer on Stackoverflow