.NET/Win32 - 用于检测属于另一个应用程序的窗口何时获得焦点的事件

Pau*_*ney 6 .net winapi

我有一个.NET应用程序,需要能够检测特定窗口何时获取并失去焦点.我感兴趣的特定窗口属于另一个我无法控制的应用程序,尽管我有Window Handle.

我真的是追求解决这个问题的最佳方法.到目前为止,我可以看到两种可能性:

  1. 在计时器上使用Win32调用来监视状态的任何变化.不太好,因为它存在丢失状态变化的风险,例如,如果窗口变为活动状态,则在定时器间隔内不活动
  2. 使用钩子(SetWindowsHookEx)拦截到窗口的消息.听起来它应该工作,但担心a)全局级钩子不能从.NET代码工作,所以需要是本机的,并且b)这可能被视为病毒/键盘记录类型活动,因此被操作系统阻止?

我相信还有其他选择,如果有的话,我很乐意听到他们!

Bre*_*McK 8

最简单的方法是使用SetWinEventHook,监听EVENT_SYSTEM_FOREGROUND事件.您需要将它与WINEVENT_OUTOFCONTEXT标志一起使用才能在.net中使用它:当您使用此标志时,Windows会将通知路由回您自己的进程,因此您不需要单独的非托管DLL.但请注意,调用此方法的代码必须运行消息循环.

快速说明这与其他答案中提到的文章有何关联:该文章重点介绍SetWindowsHook API.SetWinEventHook是一个单独的API,但您使用相同的技术来设置P/Invoke调用,并为回调设置委托 - 尽管请注意两个API在API调用本身和回调中使用不同的参数.SetWinEventHook相对于SetWindowsHook的主要优点是,对于某些类型的钩子,SetWindowsHook 需要使用单独的非托管DLL,而不能直接在.net中执行.但是,SetWinEventHook允许任何类型的回调,使用单独的非托管DLL或通知原始进程而不需要DLL,因此更友好.net.

  • 完美 - 这几乎就是我想要的.似乎存在一个极端情况,其中(有时)最大化先前最小化的窗口不会为该窗口触发EVENT_SYSTEM_FOREGROUND - 因此,监听EVENT_SYSTEM_MINIMIZEEND也会绕过它.谢谢,很棒的答案 (2认同)