我有一個WinForm應用程序有其他子窗體(不是mdi)。如果用戶按下「Esc」,即使沒有焦點,最頂端的表格也應該關閉。如何獲取WinForm應用程序中最頂層窗體的句柄?
我可以使用鍵盤鉤來全局捕捉逃逸,但我也需要關閉窗體的句柄。
我想有一種方法可以做到這一點使用Win32 API,但有沒有使用託管代碼的解決方案?
我有一個WinForm應用程序有其他子窗體(不是mdi)。如果用戶按下「Esc」,即使沒有焦點,最頂端的表格也應該關閉。如何獲取WinForm應用程序中最頂層窗體的句柄?
我可以使用鍵盤鉤來全局捕捉逃逸,但我也需要關閉窗體的句柄。
我想有一種方法可以做到這一點使用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;
}
的FormCollection是由應用程序對象通過OpenForms屬性列出在應用程序中當前打開的形式
見http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx
然後,你可以檢查每一個最頂層的形式()屬性。當你找到最頂層的表單時,你可以關閉它。
您可以在最頂端的窗體中實現一個類似於單例的模式,並提供一個靜態屬性,該靜態屬性返回它自己的一個實例並簡單地關閉它。
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();
這樣如何使用Application.Openforms
Form GetTopMostForm()
{
return Application.OpenForms
.Cast<Form>()
.First(x => x.Focused);
}
我知道這是一個4歲的線程,但我有一個類似的問題,只是想出了一個替代解決方案,以防其他人絆倒在這個問題上,不想搞亂Win32調用。
我假設最上面的窗體將是上次激活的窗體。所以你可以保留一個單獨的表單集合,類似於Application.OpenForms,除了這個集合將在每個上次被激活時排序。每當表單被激活時,將其移動到集合的第一個項目。每當看到ESC鍵時,您都會關閉收集[0]並將其刪除。
不幸的是,Form.TopMost屬性獲取或設置一個值,該值指示窗體是否應顯示爲最頂層窗體。這並不能告訴我表單是否最重要。 – tzup 2009-06-17 08:11:56