C# 确定程序是否为.NET中的活动窗口
我有一个C/.NET应用程序,我想实现以下行为: 我有一个弹出菜单。每当用户单击应用程序中不是弹出菜单的任何内容时,我希望弹出菜单关闭 但是,每当用户不在应用程序中时,我不希望发生任何事情 我试图通过LostFocus事件来管理它,但是我在确定我的应用程序是否是活动窗口时遇到了问题。代码看起来像这样C# 确定程序是否为.NET中的活动窗口,c#,.net,user-interface,active-window,C#,.net,User Interface,Active Window,我有一个C/.NET应用程序,我想实现以下行为: 我有一个弹出菜单。每当用户单击应用程序中不是弹出菜单的任何内容时,我希望弹出菜单关闭 但是,每当用户不在应用程序中时,我不希望发生任何事情 我试图通过LostFocus事件来管理它,但是我在确定我的应用程序是否是活动窗口时遇到了问题。代码看起来像这样 private void Button_LostFocus(object sender, System.EventArgs e) { if (InActiveWind
private void Button_LostFocus(object sender, System.EventArgs e)
{
if (InActiveWindow()) {
CloseMenu()
}
else {
// not in active window, do nothing
}
}
我需要知道的是如何实现InActiveWindow方法 您可以p/Invoke到,并将返回的HWND与应用程序的form.Handle属性进行比较
获得句柄后,还可以p/Invoke来获取根所有者窗口。这应该是应用程序的主启动窗口的句柄,如果它在应用程序中的话。这似乎是最棘手的原因,因为在主窗体被停用之前弹出窗口会失去焦点,所以在发生此事件时,活动窗口将始终在应用程序中。实际上,您想知道事件结束后它是否仍然是活动窗口 您可以设置某种方案,记住弹出窗口正在失去焦点,将需要关闭它的事实放在一边,并在应用程序主窗体的LostFocus或Deactivate事件中取消通知您需要关闭它的注释;但问题是你什么时候处理这张便条 我认为这可能会更容易,至少如果弹出窗口是主窗体的直接子窗体,我怀疑在您的情况下,它可能是挂接焦点,或者甚至可能是单击主窗体的事件,并在打开时使用它关闭弹出窗口,可能是通过扫描其子窗体列表以查找任何实现ICloseOnLostFocus界面的子窗体,这样弹出窗口将有机会参与决策并执行它需要执行的任何其他操作
我希望我能知道一个更好的文档来解释所有这些事件的实际含义以及它们之间的顺序,MSDN在描述它们时留下了许多不尽如人意的地方。我在一个项目中偶然发现了你的问题,基于此,我编写了这段快速代码,似乎做得很好 代码如下: 我没有太多的时间将其转换为C,因为我正在进行一个项目,期限为2天,但我相信您可以很快完成转换 以下是VB.NET代码的C版本: 公共部分类Form1:Form { 公共表格1 { 初始化组件; } [System.Runtime.InteropServices.DllImportuser32.dll] 私有静态外部IntPtr getforegroundindow; ///获取一个值,该值指示此实例是否为前台窗口。 ///如果这是前景窗口,则为true;否则为false。 私人住宅 { 收到 { var Forward=GetForegroundWindow; 在此.mdi子项中从f返回选择f.句柄 .Unionfrom f在此.OwnedForms中选择f.Handle .Unionnew IntPtr[]{this.Handle}.containsforewn; } } }
Public Class Form1
'''<summary>
'''Returns a handle to the foreground window.
'''</summary>
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetForegroundWindow() As IntPtr
End Function
'''<summary>
'''Gets a value indicating whether this instance is foreground window.
'''</summary>
'''<value>
'''<c>true</c> if this is the foreground window; otherwise, <c>false</c>.
'''</value>
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