用户更改活动进程时的Fire事件

时间:2013-06-20 20:04:56

标签: c# winforms

当程序用户将活动窗口更改为其他进程的窗口时,是否会发生事件或创建事件的方法?

如果没有这样的事件,做出类似事情的最佳方式是什么?

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

我知道有很多Windows内置的功能基本上是隐藏的,我没有足够的知识可以知道,所以如果有人知道这样的事情,那么如果你能提供帮助就会很棒我出去了。

2 个答案:

答案 0 :(得分:5)

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!
}

答案 1 :(得分:1)

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

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