Make a form remain on top of or below other windows in C#

Keeping a form on top of other windows is simple. Just set the form's TopMost property to true.

Keeping a form below other windows is harder. To do that, the program must override its WndProc method, look for messages that might move the form to the top, and use SetWindowPos to move the form to the bottom when they occur.

This program starts with the following API declarations.

[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(
    IntPtr hWnd, IntPtr hWndInsertAfter,
    int x, int y, int cx, int cy, uint uFlags);

// Constants for detecting messages.
private const UInt32 WM_ACTIVATE = 0x0006;
private const UInt32 WM_PAINT = 0xF;
private const UInt32 WM_MOVE = 0x0003;

// Constants for positioning the window.
public IntPtr HWND_BOTTOM = (IntPtr)1;
public const UInt32 SWP_NOMOVE = 0x0002;
public const UInt32 SWP_NOSIZE = 0x0001;

This code declares the SetWindowPost method used to move the form to the bottom of the window stacking order. It defines the messages that the program must look for and the values it passes to SetWindowPost to move the window to the bottom.

The following code shows the form's overridden WndProc method.

protected override void WndProc(ref Message m)
    // See if we should be bottommost.
    if (radBottommost.Checked)
        if ((m.Msg == WM_ACTIVATE) ||
            (m.Msg == WM_PAINT) ||
            (m.Msg == WM_MOVE))
            // We're being activated. Move to the bottom.

    // Handle the message normally.
    base.WndProc(ref m);

This method executes when the form receives a message from Windows. If the Bottommost radio button is checked, then the code examines the message to see if it is activate, paint, or move. If it is one of those messages, the code calls the following MoveToBottom method.

// If we should be on the bottom, move there.
// Move to the bottom.
private void MoveToBottom()
    UInt32 flags = SWP_NOSIZE | SWP_NOMOVE;
    if (!SetWindowPos(this.Handle, HWND_BOTTOM, 0, 0, 0, 0, flags))
        Console.WriteLine("Error in SetWindowPos");

This code calls SetWindowPos, passing it the HWND_BOTTOM value to make it move the form to the bottom of the window stacking order. It also passes the flags SWP_NOSIZE and SWP_NOMOVE to indicate that SetWindowPost should not resize or move the form.

If the user checks the Bottommost radio button, the following code executes.

private void radBottommost_CheckedChanged(object sender, EventArgs e)
    if (radBottommost.Checked) MoveToBottom();

If the Bottommost radio button is checked, this code calls MoveToBottom to immediately move the form to the bottom.

The final piece of code is the easiest.

// If this option is checked, make the form topmost.
private void radTopmost_CheckedChanged(object sender, EventArgs e)
    this.TopMost = radTopmost.Checked;

When the user checks or unchecks the Topmost radio button, the code sets the form's TopMost property accordingly. When this property is true, the form automatically keeps itself on top of all other windows (except possibly other topmost windows).



What did you think of this article?

  • No trackbacks exist for this post.
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.


 Email (will not be published)


Your comment is 0 characters limited to 3000 characters.