关于 c:如何在 Windows 8.1/10 上可靠地窃取/重新获得 MFC/桌面应用程序的焦点?

How to reliably steal/regain focus for MFC/desktop app on Windows 8.1/10?

好吧,我明白了:窃取焦点是邪恶的。或者至少是 99.9% 的时间。但我确实需要在 Windows 8 上可靠地窃取焦点,而到目前为止,我被一大群坚持窃取焦点总是邪恶的人所挫败。

场景:我们在运行 Windows 8.1(即将成为 Windows 10)的普通 PC 上运行自定义应用程序。屏幕、键盘和鼠标位于离地面大约 5m 的一些楼梯上,叉车操作员确实不应该爬上这些楼梯。他们拥有的一个输入设备是延长电缆上的数字键盘,位于他们的水平。他们需要做的所有事情都可以通过该键盘完成......只要某些恶意程序没有窃取我们应用程序的焦点,或者某个远程用户没有注销并离开另一个应用程序的焦点。

该应用程序本质上是一个最大化的桌面应用程序 - 它填满屏幕(但严格来说不是"全屏"或"最顶部"应用程序),因此允许其他应用程序在需要时出现在其前面.但是当鼠标空闲时,我们希望这个应用程序在所有其他应用程序前面恢复其"正常"位置,以便它获得焦点并且数字键盘输入将可靠地工作。

在 Windows 7 上,使用 SetForegroundWindow()(由 AllowSetForegroundWindow() 启用可以正常工作 - 应用程序可以回到前面并恢复焦点。在 Windows 8 上,SetForegroundWindow() 只会导致任务栏图标闪烁,但应用程序没有重新获得焦点,迫使我们的用户爬楼梯......全键盘和鼠标太诱人了,他们不应该按下他们不应该按下的按钮,并且通常会出现混乱。

所以请先生:一旦鼠标空闲 1 分钟,我们的(MFC,桌面)应用程序能否夺回焦点,因为它或多或少是唯一应该正常运行的应用程序。如果允许,我们如何可靠地窃取它?


在数字小键盘 (RegisterHotKey) 上配置热键。

按下注册的热键给你Raymond Chen的前台激活之爱

After you call the RegisterHotKey function to register a hotkey, the
window manager will send you a WM_HOTKEY message when the user presses
that hotkey, and along with it, you will get the foreground love. If
you call SetForegroundWindow from inside your hotkey handler, the
foreground window will change according to your instructions.


可能的解决方案(有很大的限制):什么都不做;等等。

我们的一位服务技术人员观察到,在第三次或第四次尝试使用 AllowSetForegroundWindow()SetForegroundWindow() 重新获得焦点时,Windows 8 最终允许我们的应用程序重新获得焦点。目前尚不清楚使这项工作的条件是什么,或者它是否可靠地工作,但我们现在已经观察到我们的应用程序从 Chrome 下方、另一个(自行开发的)MFC 应用程序下方以及第三方应用程序下方重新获得焦点- 所有桌面应用程序。在将焦点交还给我们的(桌面)应用程序之前,每种情况都需要大约 3-4 分钟。

但是,我们没有目睹它从 Metro 应用程序下方重新获得焦点,我们也没有预料到它(例如,按下 Windows 键并让系统停留在"开始"屏幕上)。

在我们(??受限)的情况下,我们愿意冒险保证我们的用户不会启动会遮盖我们桌面应用程序的 Metro 应用程序,至少在不恢复我们的应用程序的情况下不会,因为他们的业务依赖于它。我们主要担心的是,我们的一位忙碌的服务技术人员会远程登录,分心,并且不小心将我们的桌面实用程序之一留在焦点上。等待 3-4 分钟似乎是解决此特定情况的方法。


我会这样尝试:

  • 在您的应用程序中设置一个计时器。定期检查 GetForegroundWindow
  • 如果 GetForgroundWindow 不属于您的进程 (GetWindowThreadProcessId)
  • 如果一个不同的进程在前台窗口上使用 AttachThreadInput 并将您的输入队列附加到另一个进程的输入队列。
  • 现在使用 SetForegoundWindow 并再次分离线程输入。
  • 现在您可以根据需要使用 SetFocus 来控制程序的输入焦点。