我目前正在诊断窗口激活的问题,即{I-}}的调用失败,即使我相信它是从前台线程调用的。当输入来自触摸数字化仪时,该问题是可重现的。
有没有办法找出哪个线程收到了最后一个输入?我尝试在SetForegroundWindow返回的句柄上调用GetWindowThreadProcessId。但是,在输入激活窗口 1)之后,这似乎会返回过时的信息。
由于这仅用于诊断问题,如果公共接口不可用,我对使用未记录的接口的解决方案感到满意。如果这很重要,目标平台是Windows 7 64位。
<小时/> 1)
GetForegroundWindow
返回相同的句柄,无论输入来自触摸数字化仪还是指针设备。当输入来自指点设备时,对SetForegroundWindow
的后续调用成功,但触摸输入失败。
答案 0 :(得分:1)
由于这仅用于诊断问题,如果公共接口不可用,我对使用未记录的接口的解决方案感到满意。
您可以尝试使用SetWindowsHookEx为WH_GETMESSAGE安装系统范围的挂钩,并监视WM_SETFOREGROUND等有趣的消息。 IE浏览器。在调用原始版本之前记录有趣的东西。
另一个想法是使用MHOOK或Detours挂钩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
消息。