Determine if current application is activated (has focus)
Asked Answered
N

7

52

Note: There's a very similar question, but it's WPF-specific; this one is not.

How can I determine if the current application is activated (i.e. has focus)?

Nonattendance answered 23/8, 2011 at 14:41 Comment(4)
Are you talking about your personal windowsform application or arbitrary?Dyun
like this? #2184041Celebrant
Personal -- hence "current application" ;-)Nonattendance
@Code Monkey: Yes, except that I didn't want to have to intercept messages or add event listeners if possible (also, I think the accepted answer for that question would not work if there are two windows on different threads (with neither owning the other), but part of the same application -- and yes, I need to deal with that)Nonattendance
N
87

This works:

/// <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);

It has the advantage of being thread-safe, not requiring the main form (or its handle) and is not WPF or WinForms specific. It will work with child windows (even independent ones created on a separate thread). Also, there's zero setup required.

The disadvantage is that it uses a little P/Invoke, but I can live with that :-)

Nonattendance answered 23/8, 2011 at 14:43 Comment(5)
This may 'work with' child windows but it does not differentiate between them and their parents.Godchild
@Chris: Yes, that's the point. A child window is still part of the application. I guess by 'current application' I really meant 'current process'.Nonattendance
Reference "System.Runtime.InteropServices" for DllImportAvicenna
And "using System.Diagnostics; "Hardiman
Doesn't work if the application is a child process of the window owning process, e.g. if a console app is invoked without creating a new window for it (i.e. not using start). Walking up the ancestor chain is non-trivial but at least you don't have to worry about parents having terminated. If they have then either the current process would inherit the window handle from the now dead previous owner (great, now it works) or you likely have 2 processes reading the same console input buffer which is a bigger problem than not correctly determining if your application has focus.Miasma
D
14

The solution I found which requires neither native calls nor requires handling events is to check Form.ActiveForm. In my tests, that was null when no window in the application was focused and otherwise non-null.

var windowInApplicationIsFocused = Form.ActiveForm != null;

Ah, this is specific to winforms. But that applies to my situation ;-).

Dogface answered 26/10, 2017 at 23:27 Comment(1)
This is an interesting one. An app I'm editing had code to steal focus from its own tool window on mouse-over of its main window, but this apparently occasionally also made it steal focus from other applications. Checking Form.ActiveForm looks like a promising way to prevent this.Westonwestover
T
11

since it's likely that some element in your UI has contain focus for the form to be active try:

this.ContainsFocus

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.containsfocus(v=vs.110).aspx

Taphouse answered 4/9, 2014 at 4:44 Comment(1)
This only works if you have a single form (and no dialog boxes, etc.).Nonattendance
U
5

You can subscribe to Main Window's Activated event

Umont answered 23/8, 2011 at 14:43 Comment(0)
O
2

First get the handle either using:

IntPtr myWindowHandle;

myWindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;

or

HwndSource source = (HwndSource)HwndSource.FromVisual(this);
myWindowHandle = source.Handle;

Then compare whethers it is the ForeGroundWindow:

if (myWindowHandle == GetForegroundWindow()) 
{
  // Do stuff!

}

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
Ordinary answered 23/8, 2011 at 14:47 Comment(3)
What if a child window is the foreground window? The application still has focus, but not the main window.Nonattendance
@cameron, true but you figured that much, so sad about the downvote :-) doesn't the criticism apply to the other suggested answers as well?Ordinary
I didn't down- or up-vote anyone, but the "activated" answers would work as long as the main window is a parent (or grand-parent) of all the others.Nonattendance
H
1

Handle the Activated event of your main application Form.

Hydrophilic answered 23/8, 2011 at 14:44 Comment(0)
B
1

In WPF the easiest way to check if a window is active is:

if(this.IsActive)
{
 //the window is active
}
Blanca answered 25/8, 2017 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.