【发布时间】:2009-09-21 14:33:26
【问题描述】:
我想创建一个 Windows 窗体应用程序,该应用程序在运行时只有在启用/聚焦另一个外部窗口 (notepad.exe) 时才可见。任何提示,我不知道从哪里开始。
如果我的表单正在运行,我希望它在记事本启用时弹出并在记事本失去焦点时消失。
【问题讨论】:
我想创建一个 Windows 窗体应用程序,该应用程序在运行时只有在启用/聚焦另一个外部窗口 (notepad.exe) 时才可见。任何提示,我不知道从哪里开始。
如果我的表单正在运行,我希望它在记事本启用时弹出并在记事本失去焦点时消失。
【问题讨论】:
您只需使用 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;
也没有测试,但我今天做得很好,何必呢?
【讨论】:
您可以尝试查看适用于 C# 的 Windows 自动化 API。有了这些,您应该能够查看所有打开的窗口并找到记事本。我还没有看过一堆 API,但最好的基本场景是你可以处理的窗口会有一个激活/丢失焦点事件。最坏的情况是,您可以每 100 毫秒左右轮询一次,然后查看记事本窗口是否有焦点。
【讨论】: