【问题标题】:Windows Forms: Set form Visibility Based on Focus enabled of external windowWindows 窗体:基于启用外部窗口的焦点设置窗体可见性
【发布时间】:2009-09-21 14:33:26
【问题描述】:

我想创建一个 Windows 窗体应用程序,该应用程序在运行时只有在启用/聚焦另一个外部窗口 (notepad.exe) 时才可见。任何提示,我不知道从哪里开始。

如果我的表单正在运行,我希望它在记事本启用时弹出并在记事本失去焦点时消失。

【问题讨论】:

    标签: c# winforms forms


    【解决方案1】:

    您只需使用 API 调用和计时器即可完成此操作。将此行添加到表单的 using 语句中:

    using System.Runtime.InteropServices;
    

    接下来,将这些声明添加到您的表单中:

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(string lpClassName, 
        string lpWindowName); 
    
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    

    最后,在表单上放置一个 Timer,并将其 Enabled 属性设置为 true。在其 Tick 事件中,输入以下代码:

    IntPtr hWndNotepad = FindWindow(null, "Whatever.txt - Notepad");
    IntPtr hWndForegroundWindow = GetForegroundWindow();
    if (this.Handle != hWndForegroundWindow)
    {
        this.Visible = (hWndNotepad == hWndForegroundWindow);
    }
    

    我没有测试过这段代码,但它应该可以工作。该代码正在寻找要在记事本中打开的特定文件;不同的文件会导致标题栏中的文本不同,因此此代码不起作用。我认为,如果您将 FindWindow 调用更改为 FindWindow("notepad", null),它将适用于任何打开的记事本实例(可能是“notepad.exe” - 不确定)。

    更新:如果您希望您的表单在 任何记事本实例打开时可见,您可以将此代码放入您的 Timer's Tick 事件中:

    IntPtr hWndForegroundWindow = GetForegroundWindow();
    bool NotepadIsForeground = false;
    Process[] procs = Process.GetProcessesByName("notepad");
    foreach (Process proc in procs)
    {
        if (proc.MainWindowHandle == hWndForegroundWindow)
        {
            NotepadIsForeground = true;
            break;
        }
    }
    if (this.Handle != hWndForegroundWindow)
    {
        this.Visible = NotepadIsForeground;
    }
    

    你会在你的 using 指令中需要这个:

    using System.Diagnostics;
    

    也没有测试,但我今天做得很好,何必呢?

    【讨论】:

    • 成功了!这是我想要进入的方向。谢谢还有一个问题?如果我单击我的表单,它会不断闪烁而不是保持专注(在它和记事本之间交替)。我该如何解决。
    • @zion:哎呀,告诉你我没有测试它。发生的情况是,一旦您单击表单, 就变成了前台窗口,因此下次计时器关闭时,您的表单再次变得不可见。我修复了代码示例。
    • @zion:好的,我刚刚意识到,从您提出问题的方式来看,您只希望您的表单在记事本是焦点窗口时可见,所以当您点击 your 表单您会希望您的表单随后变得不可见,因为记事本不再具有焦点。我认为最简单的解决方法是在表单的 Activated 事件中禁用计时器,然后在表单的 Deactivate 事件中重新启用计时器。这听起来对你吗?
    • 是的,逻辑听起来是正确的,我很欣赏响应和代码。
    【解决方案2】:

    您可以尝试查看适用于 C# 的 Windows 自动化 API。有了这些,您应该能够查看所有打开的窗口并找到记事本。我还没有看过一堆 API,但最好的基本场景是你可以处理的窗口会有一个激活/丢失焦点事件。最坏的情况是,您可以每 100 毫秒左右轮询一次,然后查看记事本窗口是否有焦点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 2012-05-31
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多