简体   繁体   English

如何获取 WinForm 应用程序中最顶层窗体的句柄?

[英]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).我有一个 WinForm 应用程序,它有其他孩子 forms(不是 mdi)。 If the user presses "Esc" the topmost form should be closed even if it doesn't have the focus.如果用户按下“Esc”,最顶层的表单应该关闭,即使它没有焦点。

I can use a keyboard hook to globally catch the Escape but I also need the handle of the form to be closed.我可以使用键盘挂钩全局捕获 Escape,但我还需要关闭窗体的句柄。

I guess there is a way to do that using Win32 API, but is there a solution using managed code?我想有一种方法可以使用 Win32 API 来做到这一点,但是是否有使用托管代码的解决方案?

Here is one way to get the topmost form that uses Win32 (not very elegant, but it works):这是获得使用 Win32 的最顶层表单的一种方法(不是很优雅,但它有效):

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;
}

How about this using Application.Openforms这个如何使用Application.Openforms

Form GetTopMostForm()
{
    return Application.OpenForms
        .Cast<Form>()
        .First(x => x.Focused);
}

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.我知道这是一个已有 4 年历史的线程,但我遇到了类似的问题,只是想出了一个替代解决方案,以防其他人偶然发现这个问题并且不想乱用 Win32 调用。

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.因此,您可以保留一个单独的 forms 集合,类似于 Application.OpenForms,但该集合将按每个集合最后一次激活的时间排序。 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.每当您看到 ESC 键时,您将关闭 collection[0] 并将其删除。

FormCollection is used by the Application object to list the currently open forms in an application through the OpenForms property FormCollection被Application object使用,通过OpenForms属性列出一个应用程序中当前打开的forms

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

Then you could check TopMost() property of each form.然后你可以检查每个表单的 TopMost() 属性。 And when you find a topmost form, you close it.当您找到最顶层的表格时,您将其关闭。

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.您可以在最顶层的表单中实现类似单例的模式,并提供一个 static 属性,该属性返回其自身的一个实例并简单地关闭它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM