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

前端 未结 5 1930
耶瑟儿~
耶瑟儿~ 2020-12-06 02:52

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 u

相关标签:
5条回答
  • 2020-12-06 03:21

    I know this is a 4 yr old thread, but I had a similar problem and just came up with an alternative solution just in case anyone else stumbles on this question and doesn't want to mess around with Win32 calls.

    I assume the top-most form will be the one that was last activated. So you could keep a separate collection of forms, similar to Application.OpenForms, except this collection would be ordered by when each was last activated. Whenever a form is activated, move it to the first item of the collection. Whenever you see the ESC key, you would close collection[0] and remove it.

    0 讨论(0)
  • 2020-12-06 03:28

    FormCollection is used by the Application object to list the currently open forms in an application through the OpenForms property

    See http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx

    Then you could check TopMost() property of each form. And when you find a topmost form, you close it.

    0 讨论(0)
  • 2020-12-06 03:36

    You could implement a singleton-like pattern in your topmost form, and provide a static property that returns the one instance of itself and simply close it.

       public class MainForm : Form
       {
          private static MainForm mainForm;
    
          public static MainForm { get { return mainForm; } }
    
          public MainForm()
          {
             mainForm = this;
          }
       }
    
    
       // When the ESC key is pressed...
       MainForm.MainForm.Close();
    
    0 讨论(0)
  • 2020-12-06 03:46

    How about this using Application.Openforms

    Form GetTopMostForm()
    {
        return Application.OpenForms
            .Cast<Form>()
            .First(x => x.Focused);
    }
    
    0 讨论(0)
  • 2020-12-06 03:47

    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;
    }
    
    0 讨论(0)
提交回复
热议问题