2011-08-22 58 views
6

我有一个.NET应用程序需要能够检测特定窗口何时获得并失去焦点。我感兴趣的特定窗口属于另一个我无法控制的应用程序,虽然我有窗口句柄。.NET/Win32 - 检测属于另一个应用程序的窗口何时获得焦点的事件

我真的是最好的方法来解决这个问题。到目前为止,我可以看到2种可能性:一个计时器使用Win32调用来监视状态的任何变化

  1. 。不是很好,因为它存在缺失状态变化的风险,例如如果窗口变为活动状态,则在定时器间隔内处于非活动状态
  2. 使用挂钩(SetWindowsHookEx)截获到窗口的消息。听起来像它应该工作,但担心a)全局级挂钩不会从.NET代码工作,所以需要本地和b)这可以被视为病毒/键盘记录类型的活动,所以被操作系统阻止?

我敢肯定,还有其他的选择,如果是的话,我很乐意听到他们!

回答

6

最简单的方法很可能是使用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友好。

+2

完美 - 这几乎正是我所期待的。似乎有一个角落的情况(有时)最大化以前最小化的窗口不会触发该窗口的EVENT_SYSTEM_FOREGROUND - 因此侦听EVENT_SYSTEM_MINIMIZEEND也会解决该问题。谢谢,真棒回答 –

+0

当我运行WPF应用程序时,消息循环约束对我来说不是问题。对于任何想要做同样的事情,但是使用控制台应用程序(默认情况下没有消息循环)的人来说,这篇文章是很好的(搜索“在控制台应用程序中处理消息”,如果链接被破坏,则为“Stephen Toub”) - http:// msdn .microsoft.com/EN-US /杂志/ cc163417.aspx –

0

下面是一篇关于在.NET中从MSDN杂志实施windows挂钩的精彩文章:Windows Hooks in the .NET Framework。至于你的第二个问题,我从来没有听说过将这些api调用作为间谍软件行为的防病毒软件。

希望它有帮助!

相关问题