Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the handle of the topmost form in a WinForm app?

I have a WinForm app that has other child forms (not mdi). If the user presses "Esc" the topmost form should be closed even if it doesn't have the focus.

I can use a keyboard hook to globally catch the Escape but I also need the handle of the form to be closed.

I guess there is a way to do that using Win32 API, but is there a solution using managed code?

like image 237
tzup Avatar asked Jun 16 '09 11:06

tzup


People also ask

How do I change my winform name?

To change the name of your form, select it in the solution explorer and press F2. Then type in the new name for that form (don't forget the '. cs'!) and when you press enter it'll ask you if you want Visual Studio to update all references to that form. Click Yes, and you're done.

How do I create a control over form?

Add the control by drawingSelect the control by clicking on it. In your form, drag-select a region. The control will be placed to fit the size of the region you selected.

What is topmost in C#?

Gets or sets a value that indicates whether a window appears in the topmost z-order. public: property bool Topmost { bool get(); void set(bool value); }; C# Copy.

How do you use topmost?

1. We couldn't reach the apples on the topmost branches. 2. The topmost branches were full of birds.


2 Answers

Here is one way to get the topmost form that uses Win32 (not very elegant, but it works):

public const int GW_HWNDNEXT = 2; // The next window is below the specified window
public const int GW_HWNDPREV = 3; // The previous window is above

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

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindow", SetLastError = true)]
public static extern IntPtr GetNextWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int wFlag);

/// <summary>
/// Searches for the topmost visible form of your app in all the forms opened in the current Windows session.
/// </summary>
/// <param name="hWnd_mainFrm">Handle of the main form</param>
/// <returns>The Form that is currently TopMost, or null</returns>
public static Form GetTopMostWindow(IntPtr hWnd_mainFrm)
{
    Form frm = null;

    IntPtr hwnd = GetTopWindow((IntPtr)null);
    if (hwnd != IntPtr.Zero)
    {
        while ((!IsWindowVisible(hwnd) || frm == null) && hwnd != hWnd_mainFrm)
        {
            // Get next window under the current handler
            hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);

            try
            {
                frm = (Form)Form.FromHandle(hwnd);
            }
            catch
            {
                // Weird behaviour: In some cases, trying to cast to a Form a handle of an object 
                // that isn't a form will just return null. In other cases, will throw an exception.
            }
        }
    }

    return frm;
}
like image 119
tzup Avatar answered Sep 21 '22 12:09

tzup


How about this using Application.Openforms

Form GetTopMostForm()
{
    return Application.OpenForms
        .Cast<Form>()
        .First(x => x.Focused);
}
like image 23
Simon Avatar answered Sep 23 '22 12:09

Simon