簡體   English   中英

如何獲取 WinForm 應用程序中最頂層窗體的句柄?

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

我有一個 WinForm 應用程序,它有其他孩子 forms(不是 mdi)。 如果用戶按下“Esc”,最頂層的表單應該關閉,即使它沒有焦點。

我可以使用鍵盤掛鈎全局捕獲 Escape,但我還需要關閉窗體的句柄。

我想有一種方法可以使用 Win32 API 來做到這一點,但是是否有使用托管代碼的解決方案?

這是獲得使用 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;
}

這個如何使用Application.Openforms

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

我知道這是一個已有 4 年歷史的線程,但我遇到了類似的問題,只是想出了一個替代解決方案,以防其他人偶然發現這個問題並且不想亂用 Win32 調用。

我假設最頂層的表格將是最后激活的表格。 因此,您可以保留一個單獨的 forms 集合,類似於 Application.OpenForms,但該集合將按每個集合最后一次激活的時間排序。 每當激活一個表單時,將其移動到集合的第一項。 每當您看到 ESC 鍵時,您將關閉 collection[0] 並將其刪除。

FormCollection被Application object使用,通過OpenForms屬性列出一個應用程序中當前打開的forms

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

然后你可以檢查每個表單的 TopMost() 屬性。 當您找到最頂層的表格時,您將其關閉。

您可以在最頂層的表單中實現類似單例的模式,並提供一個 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