有没有办法找出哪个线程收到了最后一个输入?

时间:2015-08-24 19:37:42

标签: c++ c winapi input

我目前正在诊断窗口激活的问题,即{I-}}的调用失败,即使我相信它是从前台线程调用的。当输入来自触摸数字化仪时,该问题是可重现的。

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

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

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

3 个答案:

答案 0 :(得分:1)

  

由于这仅用于诊断问题,如果公共接口不可用,我对使用未记录的接口的解决方案感到满意。

您可以尝试使用SetWindowsHookEx为WH_GETMESSAGE安装系统范围的挂钩,并监视WM_SETFOREGROUND等有趣的消息。 IE浏览器。在调用原始版本之前记录有趣的东西。

另一个想法是使用MHOOKDetours挂钩SetForegroundWindow API。正如你在https://superuser.com/questions/18383/preventing-applications-from-stealing-focus看到的那样,使用mhook看起来很简单。

答案 1 :(得分:0)

GetWindowThreadProcessId 会返回上次收到窗口输入的线程。它告诉你哪个胎面创建了窗口,因此应该处理输入。

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

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

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

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

你特别提到“最后一个输入”,但是这些限制只提到了进程上下文:“只有当进程收到最后一个输入事件时,进程才能设置前台窗口。”

答案 2 :(得分:0)

这不回答问题,但解决导致这个问题的根本问题:

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

  

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

不幸的是,在Windows 7上,这不包括触摸输入。某个流程无法响应SetForegroundWindow致电WM_TOUCH。直到系统合成了相应的兼容性鼠标输入事件,该过程才最终获得前台激活权限。

此后发生了变化,从Windows 8开始,触摸输入计为第一类输入,调用SetForegroundWindow成功响应WM_TOUCH消息。