是否有办法找出哪个线程接收了最后一个输入

Is there any way to find out, which thread received the last input?

本文关键字:线程 输入 最后一个 是否      更新时间:2023-10-16

我目前正在诊断窗口激活的问题,调用SetForegroundWindow失败,尽管我相信它是从前台线程调用的。当输入来自触摸数字化仪时,这个问题也会重现。

是否有办法找出哪个线程接收了最后一个输入?我尝试在GetForegroundWindow返回的句柄上调用GetWindowThreadProcessId。然而,这似乎返回过时的信息,就在输入激活窗口之后1)

由于这只是用于诊断问题,如果公共接口不可用,我很乐意使用未记录的接口的解决方案。如果这很重要,目标平台是Windows 7 64位。


1) GetForegroundWindow返回相同的句柄,无论输入是来自触摸数字化仪还是指向设备。当输入来自指向设备时,随后对SetForegroundWindow的调用成功,但对于触摸输入失败。

由于这只是用于诊断问题,如果公共接口不可用,我很高兴使用未记录的接口的解决方案。

你可以尝试用SetWindowsHookEx为WH_GETMESSAGE安装系统范围钩子,并监控WM_SETFOREGROUND等有趣的消息。Ie。在调用原始版本之前记录有趣的内容。

另一个想法是挂钩SetForegroundWindow API,与MHOOK或Detours。正如您在这里https://superuser.com/questions/18383/preventing-applications-from-stealing-focus所看到的,使用mhook看起来非常简单。

GetWindowThreadProcessId是否返回最后接收窗口输入的线程。它告诉您哪个线程创建了窗口,因此应该处理输入。

你必须知道Windows输入是通过消息工作的。这些消息被传递到一个线程消息队列。这直接解释了为什么每个窗口都有一个相关联的线程:这是消息被传递到的线程。

在一个正常的应用程序中,所有的窗口都是由单个"前台"或"UI"线程创建的。因此,问题"哪个线程接收了最后一个输入"是总是"前台线程"。后台线程根本不接收窗口消息。

很少有应用程序在多个线程上创建多个窗口,即使这是允许的。在这些情况下,两个线程可以同时接收消息,这使得"最后输入"的概念无效。在这种情况下,每个线程都有自己的"最后输入"。

回到你所说的问题,SetForegroundWindow没有记录的线程限制。特别是,没有限制它必须从前台线程调用。实际上,文档指出它可以是另一个进程(当然表示另一个线程)。

你特别提到了"最后一次输入",但限制只提到在进程上下文中:"进程只能设置前台窗口,如果…

这并没有回答这个问题,但是解决了导致这个问题的根本问题:

SetForegroundWindow API对哪个线程可以成功调用它施加了几个限制。先决条件之一是调用线程的

进程收到最后一个输入事件。

不幸的是,在Windows 7上不包括触摸输入。进程没有资格调用SetForegroundWindow来响应WM_TOUCH。直到系统合成了相应的兼容性鼠标输入事件,进程才最终获得前台激活权限。

这已经改变了,从Windows 8开始,触摸输入算作一级输入,调用SetForegroundWindow成功响应WM_TOUCH消息。