【问题标题】:Determine Whether Program is the Active Window in .NET确定程序是否是 .NET 中的活动窗口
【发布时间】:2010-10-27 23:28:40
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: c# .net user-interface active-window


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      我在做一个项目时偶然发现了你的问题,基于Reed Copsey's answer,我编写了这个似乎可以很好地完成工作的快速代码。

      代码如下:

      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
      

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

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

      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
      
          [System.Runtime.InteropServices.DllImport("user32.dll")]
          private static extern IntPtr GetForegroundWindow();
      
          ///<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 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);
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-31
          • 2014-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多