为什么SetWinEventHook回调需要表单?

时间:2013-07-17 09:53:28

标签: forms winapi hook

目前,我正在使用功能强大的SetWinEventHook()函数来捕获一些用户界面的操作,例如最小化和最大化计算机上程序运行的其他窗口。

所以我通过使用BrendanMcK在this post上提供的代码来启发自己,它确实有效(我的意思是:当事件发生时调用回调函数)直到行

MessageBox.Show("Something")

存在。但是我不想在这个程序中使用任何形式或窗口。

some research之后,我发现这种钩子需要一个消息循环来允许重定向来自其他窗口句柄的消息。显然,使用Application.Run()should do the trick调用线程,但我更喜欢C#对象本身更清洁的东西。

所以我的问题是:是否可以在对象的方法中创建一个消息循环?

http://bytes.com/topic/c-sharp/answers/557342-thread-message-loop-c

1 个答案:

答案 0 :(得分:1)

不,该功能不需要窗口句柄,因此不需要“表单”。但该函数的MSDN文档非常明确:

  

调用SetWinEventHook的客户端线程必须有一个消息循环才能接收事件。

在任何希望接收由其他进程或线程在外部生成的通知的程序中,消息循环是通用的。这是producer-consumer problem的通用解决方案。显然,任何GUI应用程序都需要这样的解决方案,Windows消息由操作系统生成。它与SetWinEventHook()没有区别,可访问性事件源自其他程序。没有干净的机制来“中断”一个线程并让它运行其他代码,导致的重入问题极难处理。线程必须合作,它必须处于空闲状态并准备好接收通知以安全地处理它。消息循环解决了这个问题。

在方法中抽取消息循环(调用Application.Run)当然是可能的。但请记住,在使用Application.ExitThread显式停止循环之前,该方法不会返回。因此,通常只有一个适合该调用的好地方,即程序的Main()方法。

使用Winforms或WPF项目模板启动项目是实现这一目标的一种非常好的方法。你不需要实际创建一个窗口,在调用SetWinEventHook之后调用不带参数的Application.Run()。