确定Program是否是.NET中的活动窗口

我有一个C#/。NET应用程序,我想实现以下行为:

我有一个弹出菜单。 每当用户点击应用程序中不是弹出菜单的任何内容时,我都希望关闭弹出菜单。

但是,每当用户不在应用程序中时,我都不希望发生任何事情。

我正试图通过LostFocus事件来管理这个,但是我无法确定我的应用程序是否是活动窗口。 代码看起来像这样。

private void Button_LostFocus(object sender, System.EventArgs e) { if (InActiveWindow()) { CloseMenu() } else { // not in active window, do nothing } } 

我需要知道的是如何实现InActiveWindow()方法。

您可以P / Invoke到GetForegroundWindow() ,并将返回的HWND与应用程序的form.Handle属性进行比较。

获得句柄后,您还可以P / Invoke GetAncestor()来获取root所有者窗口。 这应该是应用程序的主要启动窗口的句柄,如果它在您的应用程序中。

我在制作一个项目时偶然发现了你的问题,根据Reed Copsey的答案 ,我写了这个快速的代码,似乎做得很好。

这是代码:

 Public Class Form1 ''' '''Returns a handle to the foreground window. '''  _ Private Shared Function GetForegroundWindow() As IntPtr End Function ''' '''Gets a value indicating whether this instance is foreground window. ''' ''' '''true if this is the foreground window; otherwise, false. ''' Private ReadOnly Property IsForegroundWindow As Boolean Get Dim foreWnd = GetForegroundWindow() Return ((From f In Me.MdiChildren Select f.Handle).Union( From f In Me.OwnedForms Select f.Handle).Union( {Me.Handle})).Contains(foreWnd) End Get End Property End Class 

我没有太多时间将它转换为C#,因为我正在处理一个截止日期为2天的项目,但我相信你可以快速完成转换。

这是VB.NET代码的C#版本:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); ///Gets a value indicating whether this instance is foreground window. ///true if this is the foreground window; otherwise, false. private bool IsForegroundWindow { get { var foreWnd = GetForegroundWindow(); return ((from f in this.MdiChildren select f.Handle) .Union(from f in this.OwnedForms select f.Handle) .Union(new IntPtr[] { this.Handle })).Contains(foreWnd); } } } 

这似乎是最棘手的原因,因为弹出窗口在主窗体停用之前失去焦点,因此活动窗口将始终在此事件发生时位于应用程序中。 真的,你想知道在事件结束后它是否仍然是活动窗口。

您可以设置某种方案,让您记住弹出窗口正在失去焦点,抛弃您需要关闭它的事实,并在应用程序主窗体的LostFocusDeactivate事件中取消告诉您需要的注释关闭它; 但问题是你什么时候处理这​​个笔记?

我认为它可能更容易,至少如果弹出窗口是主窗体的直接子窗口(我怀疑在你的情况下可能是)挂钩Focus或者甚至是主窗体的Click事件并使用它关闭弹出窗口,如果它是打开的(可能是通过扫描其实现ICloseOnLostFocus接口的子窗体列表,以便弹出窗口有机会参与决策并做任何其他需要做的事情)。

我希望我知道一个更好的文档,解释所有这些事件实际意味着什么以及它们如何相互排序,MSDN在描述它们时还有很多不足之处。