5

当程序用户将活动窗口更改为不同进程的活动窗口时,是否有事件或创建事件的方法?

如果没有这样的事件,那么制作类似的东西的最佳方法是什么?

我目前有一个每 3 秒运行一次 Process.GetCurrentProcess() 的计时器,但我正在寻找更好、更有效的方法,我不想降低间隔,因为有制作程序的风险占用太多资源或花费太多时间来不断检查活动进程。

我知道有很多 Windows 内置函数基本上是隐藏的,我没有足够的知识知道,所以如果有人对这样的事情有任何想法,如果你能帮助我,那就太好了。

4

2 回答 2

7

SetWinEventHook API 正是您在此处寻找的功能您需要做的就是在您的应用程序以正确的选项启动时调用它,并且当用户从当前在桌面上运行的任何进程更改焦点时,您应该开始接收通知。

[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, uint dwflags);
[DllImport("user32.dll")]
internal static extern int UnhookWinEvent(IntPtr hWinEventHook);
internal delegate void WinEventProc(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int      idObject, int idChild, int dwEventThread, int dwmsEventTime);

const uint WINEVENT_OUTOFCONTEXT = 0;
const uint EVENT_SYSTEM_FOREGROUND = 3;
private IntPtr winHook;
private WinEventProc listener;

public void StartListeningForWindowChanges()
{
    listener = new WinEventProc(EventCallback);
    //setting the window hook
    winHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, listener, 0, 0, WINEVENT_OUTOFCONTEXT);
}

public void StopListeningForWindowChanges()
{
    UnhookWinEvent(winHook);
}

private static void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{
    // handle active window changed!
}
于 2013-06-20T20:57:58.390 回答
1

我想说其中一种方法是使用 Windows 挂钩,即 CBT 挂钩。这听起来更接近“老好”的 Win32 API 和通用 C/C++ 人员。同时,据我所知,还有 C# 版本http://msdn.microsoft.com/en-us/magazine/cc188966.aspx#S5

所以想法是每次获得 HCBT_ACTIVATE 类型的钩子事件(要激活的窗口)时检查当前进程,然后检查拥有该窗口的进程。如果它与之前记住的过程不匹配 - 是时候触发你的事件了。唯一要记住的是,您自己的行为也可能触发 CBT 钩子(您必须避免无休止的自行循环!)。

于 2013-06-20T20:29:30.563 回答