我有一个WinForm应用程序,其他子窗体(不是mdi)。如果用户按下“Esc”,即使没有焦点,也应关闭最上面的表格。
我可以使用键盘钩子全局捕捉Escape但我还需要关闭表单的句柄。
我想有一种方法可以使用Win32 API来实现,但有没有使用托管代码的解决方案?
答案 0 :(得分:7)
这是获取使用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;
}
答案 1 :(得分:3)
Form GetTopMostForm()
{
return Application.OpenForms
.Cast<Form>()
.First(x => x.Focused);
}
答案 2 :(得分:3)
我知道这是一个4岁的线程,但我遇到了类似的问题,只是提出了一个替代解决方案,以防万一其他人偶然发现这个问题并且不想乱用Win32。
我认为最顶层的表格将是最后一次激活的表格。所以你可以保留一个单独的表单集合,类似于Application.OpenForms,除了这个集合将按最后一次激活时的顺序排序。每当激活表单时,将其移动到集合的第一个项目。每当您看到ESC键时,您将关闭集合[0]并将其删除。
答案 3 :(得分:1)
Application对象使用FormCollection通过OpenForms属性列出应用程序中当前打开的表单
请参阅http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx
然后你可以检查每个表单的TopMost()属性。当你找到最顶层的表格时,你就可以关闭它。
答案 4 :(得分:1)
您可以在最顶层的表单中实现类似单例的模式,并提供一个静态属性,该属性返回自身的一个实例并简单地关闭它。
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();