【问题标题】:Allow background application to set foreground window of different process允许后台应用程序设置不同进程的前台窗口
【发布时间】:2014-05-17 18:59:51
【问题描述】:

首先,我知道这是一个有争议的讨论,但我希望我们可以保持技术性。

我有一个在后台启动的应用程序,我希望它能够激活/使窗口聚焦在不同的进程中。但是,即使我要激活其窗口的进程调用了 AllowSetForegroundWindow(ASFW_ANY),调用 SetForegroundWindow 总是会失败。

原因是(IMO)启动应用程序是后台进程,并且由于它没有收到输入,因此不允许设置前台窗口。所以一切都出现在任务列表中,但没有显示出来。

所以我尝试创建一个虚拟窗口来接收立即关闭的输入,之后能够成功调用 SetForegroundWindow。但即使是我显示的虚拟窗口也显示在背景中。

但是,如果我打电话

AttachThreadInput(
    GetWindowThreadProcessId(GetForegroundWindow(), NULL),
    GetCurrentThreadId(), TRUE);

在创建虚拟窗口之前,该窗口确实是在前台创建的,我可以之后在不同的进程中为不同的 HWND 调用 SetForegroundWindow。

但是:如果我不创建虚拟窗口,尽管我使用 AttachThreadInput,但 SetForegroundWindow 仍然返回零。

我不明白为什么如果我创建一个自己的窗口(然后为其他窗口成功),为什么 AttachThreadInput hack 会成功,但如果我不先创建自己的窗口则不成功。

我的后台进程如何在不同进程中的不同窗口上调用 SetForegroundWindow而不创建虚拟窗口?

[*] 后台应用程序实际上是 gpg-agent.exe,它在请求密码时调用 pinentry.exe(我的应用程序)。 pinentry.exe(作为后台进程运行)必须向另一个正在运行的应用程序请求密码,因此它必须将其窗口置于前台...

【问题讨论】:

  • 不,在我看来不是,因为我不想创建自己的虚拟窗口。即使使用 AttachThreadInput,其他窗口/进程的 SetForegroundWindow 也不起作用;当我创建自己的(虚拟)窗口时,它可以工作。
  • 你做不到。如果你没有焦点,你就不能放弃它。正如雷蒙德所说,“你不能放弃不属于你的东西”。这是 Windows 中一个非常深思熟虑的设计决定。 blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx
  • 正如开头提到的,我希望我们可以保持这个讨论的技术性。所以在这种情况下,它必须是可能的,因为我的后台应用程序可以做它想做的任何事情(直到将自己注入到不同的进程中)。正如我所提到的:当我创建一个虚拟窗口时它也可以工作。问题是:什么是侵入性最小的方式?
  • 什么是后台进程?

标签: winapi setforegroundwindow


【解决方案1】:

AttachThreadInput()documentation 为您提供线索:

在不同线程中创建的窗口通常会相互独立地处理输入。即它们有自己的输入状态(焦点、活动、捕获窗口、按键状态、队列状态等),它们的输入处理与其他线程的输入处理并不同步。通过使用 AttachThreadInput 函数,一个线程可以将其输入处理机制附加到另一个线程。两个线程接收到的键盘和鼠标事件由 idAttachTo 参数指定的线程处理,直到通过第二次调用 AttachThreadInput 并为 fAttach 参数指定 FALSE 来分离线程。 这还允许线程共享它们的输入状态,因此它们可以调用 SetFocus 函数将键盘焦点设置到不同线程的窗口。这还允许线程获取键状态信息。 p>

SetForegroundWindow()documentation 告诉您调用进程需要满足哪些条件才能设置前景窗口:

系统限制哪些进程可以设置前台窗口。只有满足以下条件之一,进程才能设置前台窗口:

进程是前台进程。
进程由前台进程启动。
进程收到最后一个输入事件。
没有前台进程。
正在调试进程。
前台进程不是现代应用程序或开始屏幕。
前景未锁定(请参阅 LockSetForegroundWindow)。
前台锁定超时已过期(请参阅 SystemParametersInfo 中的 SPI_GETFOREGROUNDLOCKTIMEOUT)。
没有菜单处于活动状态。

仅仅自己创建一个虚拟窗口并不能保证你会成为前台进程。将您的窗口线程附加到当前前台窗口的线程允许您共享其输入状态,如果前台线程有权这样做,您就有更好的机会获得设置前台窗口的权限。

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多