【问题标题】:How to reliably steal/regain focus for MFC/desktop app on Windows 8.1/10?如何可靠地窃取/重新获得 Windows 8.1/10 上 MFC/桌面应用程序的焦点?
【发布时间】:2019-02-16 12:29:53
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • @omatai 您可以尝试在上述 Windows 8.1 机器上将 HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout 设置为 0
  • 我敢打赌这是一个 X/Y 问题:叉车操作员可能正在使用条形码扫描仪,通过键盘提供输入?出于这个原因,这几乎总是糟糕的设计选择。扫描仪是否有其他接口,如串口?它确实更容易,更易于维护,与其他软件更兼容(即使你的应用程序被使用了 99% 的时间,仍然有 1%)。我必须同意你试图避免的事情——不要这样做。
  • @zzxyz 如何以编程方式将焦点传递给我选择的应用程序是一个编程问题。这也可能是一个 su 问题。他有一个过去可以工作的 API,现在不再工作了。
  • @Yakk-AdamNevraumont - 我完全同意你所说的,并没有试图暗示这个问题在这里是错误的。我试图帮助扩大潜在答案的范围,因为我有一种预感——可能是错的——更多的人知道如何通过管理而不是编程解决这个问题(需要继续像以前一样运行的旧应用程序等)
  • 太棒了:如果我可以做任何我想做的事,我想抢占焦点 :-) 我该怎么做那个

标签: c++ windows winapi mfc windows-8.1


【解决方案1】:

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

Pressing a registered hotkey gives you the foreground activation love by Raymond Chen

调用RegisterHotKey函数注册热键后, 当用户按下时,窗口管理器将向您发送 WM_HOTKEY 消息 那个热键,伴随着它,你会得到前景的爱。如果 您从热键处理程序内部调用 SetForegroundWindow, 前景窗口将根据您的指示进行更改。

【讨论】:

  • 这看起来令人鼓舞,特别是如果一个人可以合成一个热键并发送它......这感觉像是一种合法的作弊形式。太忙了,现在没时间尝试,也可以通过什么都不做得到一个可以接受的解决方案......
  • 似乎 chromium 项目也在使用这种技术:cs.chromium.org/chromium/src/ui/base/win/…
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    我会这样尝试:

    1. 在您的应用程序中设置计时器。定期检查GetForegroundWindow
    2. 如果GetForgroundWindow不属于你的进程(GetWindowThreadProcessId
    3. 如果前台窗口有不同的进程,请使用AttachThreadInput 并将您的输入队列附加到其他进程的输入队列。
    4. 现在使用SetForegoundWindow 并再次分离线程输入。
    5. 现在您可以根据需要使用SetFocus 来控制程序的输入焦点。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 2011-02-17
    • 2012-07-02
    相关资源
    最近更新 更多