检测使用C#更改的活动窗口而不进行轮询

检测使用C#更改的活动窗口而不进行轮询,c#,windows,events,winapi,C#,Windows,Events,Winapi,当当前活动窗口更改时,如何调用回调。我已经看到了如何使用CBTProc来实现。但是,全局事件不容易与托管代码挂钩。我想找到一种不需要投票的方式。我更喜欢事件驱动的方法 关于您可以使用SetWinEventHook并收听事件\系统\前台事件。使用WINEVENT\u OUTOFCONTEXT标志以避免全局钩子问题。创建一个新的windows窗体项目,添加一个文本框,使其多行,并将textbox Dock属性设置为fill,将其命名为Log并粘贴到以下代码中(您需要将System.Runtime.I

当当前活动窗口更改时,如何调用回调。我已经看到了如何使用CBTProc来实现。但是,全局事件不容易与托管代码挂钩。我想找到一种不需要投票的方式。我更喜欢事件驱动的方法


关于

您可以使用
SetWinEventHook
并收听
事件\系统\前台
事件。使用
WINEVENT\u OUTOFCONTEXT
标志以避免全局钩子问题。

创建一个新的windows窗体项目,添加一个文本框,使其多行,并将textbox Dock属性设置为fill,将其命名为Log并粘贴到以下代码中(您需要将System.Runtime.InteropServices添加到您的使用中)


我知道这条线很旧,但为了将来使用: 运行代码时,您会在一段时间后注意到崩溃。这是由表单构造函数中的行引起的:

public Form1()
    {
        InitializeComponent();
        WinEventDelegate dele = new WinEventDelegate(WinEventProc);//<-causing ERROR
        IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
    }

…现在一切正常dele的范围需要扩大,以防止该代表被处置。有关更多信息,请参阅上的注释。这似乎不适用于控制台应用程序,有人知道为什么吗?我删除了InitializeComponent()。@AnthonyRaimondo显然“如果您有一个Console.ReadLine处于活动状态,它不会启动”。请参阅以减少互操作调用并稍微清理代码<不需要code>GetForegroundWindow(),因为
WinEventProc
已经以
hwnd
的形式接收前台句柄,该句柄可用于获取标题。最后还应调用。
public Form1()
    {
        InitializeComponent();
        WinEventDelegate dele = new WinEventDelegate(WinEventProc);//<-causing ERROR
        IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
    }
public Form1()
        {
            InitializeComponent();
            dele = new WinEventDelegate(WinEventProc); 
            IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
        }
WinEventDelegate dele = null;