How do I see if my form is currently on top of the

2019-02-18 09:53发布

问题:

Basically, how do I tell if my program is layered above all the other ones?

回答1:

A fairly simple way is to P/Invoke GetForegroundWindow() and compare the HWND returned to the application's form.Handle property.

using System;
using System.Runtime.InteropServices;

namespace MyNamespace
{
    class GFW
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        public bool IsActive(IntPtr handle)
        {
            IntPtr activeHandle = GetForegroundWindow();
            return (activeHandle == handle);
        }
    }
}

Then, from your form:

if (MyNamespace.GFW.IsActive(this.Handle))
{
  // Do whatever.
}


回答2:

You can use:

if (GetForegroundWindow() == Process.GetCurrentProcess().MainWindowHandle)
{
     //do stuff
}

WINAPI imports (at class level):

[System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool GetForegroundWindow();

Assign a property to hold the value, and add the check to the form's GotFocus event through IDE, or after InitializeComponent();

e.g.:

//.....
InitalizeComponent();
this.GotFocus += (myFocusCheck);
//...

private bool onTop = false;

private void myFocusCheck(object s, EventArgs e)
{
    if(GetFore......){ onTop = true; }
}


回答3:

If your window inherits form, you can check Form.Topmost property



回答4:

A good solution is given by this answer to an identical question: https://stackoverflow.com/a/7162873/386091

/// <summary>Returns true if the current application has focus, false otherwise</summary>
public static bool ApplicationIsActivated()
{
    var activatedHandle = GetForegroundWindow();
    if (activatedHandle == IntPtr.Zero) {
        return false;       // No window is currently activated
    }

    var procId = Process.GetCurrentProcess().Id;
    int activeProcId;
    GetWindowThreadProcessId(activatedHandle, out activeProcId);

    return activeProcId == procId;
}


[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

The currently accepted solution by Euric doesn't work if your program shows a dialog box or has detachable windows (like if you use a windows docking framework).