Determine Whether Program is the Active Window in .NET

泄露秘密 提交于 2019-11-28 13:59:32

You could P/Invoke into GetForegroundWindow(), and compare the HWND returned to the application's form.Handle property.

Once you have the handle, you can also P/Invoke GetAncestor() to get the root owner window. This should be the handle of your application's main, startup window, if this is in your application.

Alex Essilfie

I stumbled upon your question while working on a project and based on Reed Copsey's answer, I wrote this quick code which seems to do the job well.

Here's the code:

Public Class Form1
    '''<summary>
    '''Returns a handle to the foreground window.
    '''</summary>
    <Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function GetForegroundWindow() As IntPtr
    End Function

    '''<summary>
    '''Gets a value indicating whether this instance is foreground window.
    '''</summary>
    '''<value>
    '''<c>true</c> if this is the foreground window; otherwise, <c>false</c>.
    '''</value>
    Private ReadOnly Property IsForegroundWindow As Boolean
        Get
            Dim foreWnd = GetForegroundWindow()
            Return ((From f In Me.MdiChildren Select f.Handle).Union(
                    From f In Me.OwnedForms Select f.Handle).Union(
                    {Me.Handle})).Contains(foreWnd)
        End Get
    End Property
End Class

I didn't have too much time to convert it to C# as I'm working on a project with a deadline in 2 days but I believe you can quickly do the conversion.

Here is the C# version of the VB.NET code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

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

    ///<summary>Gets a value indicating whether this instance is foreground window.</summary>
    ///<value><c>true</c> if this is the foreground window; otherwise, <c>false</c>.</value>
    private bool IsForegroundWindow
    {
        get
        {
            var foreWnd = GetForegroundWindow();
            return ((from f in this.MdiChildren select f.Handle)
                .Union(from f in this.OwnedForms select f.Handle)
                .Union(new IntPtr[] { this.Handle })).Contains(foreWnd);
        }
    }
}

It seems like the biggest reason this is tricky is because the popup loses focus before the main form is deactivated, so the active window will always be in the application at the time of this event. Really, you want to know whether it will still be the active window after the event is over.

You could set up some kind of scheme where you remember that a popup is losing focus, set aside the fact that you will need to close it, and in the LostFocus or Deactivate event of the application's main form cancel the note that tells you you need to close it; but the problem is when will you process the note?

I'm thinking it might be easier, at least if the popup is a direct child of the main form (which I suspect in your case it may be) to hook the Focus or maybe even Click event of the main form and use it close the popup if it is open (perhaps by scanning its list of child forms for any that implement an ICloseOnLostFocus interface, so that the popup will have a chance to participate in the decision and do anything else it needs to do).

I wish I knew of a better document explaining what all these events actually mean and how they are sequenced with respect to one another, MSDN leaves a lot to be desired in describing them.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!