允许后台应用设置不同进程的前台窗口 [英] Allow background application to set foreground window of different process

查看:35
本文介绍了允许后台应用设置不同进程的前台窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

First off, I know this is a controversal discussion but I hope we can keep this technical.

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

I have an application which is started in background and I somehow want it to be able to activate/bring to focus a window in a different process. But calling SetForegroundWindow always fails even if the process whose window I want to activate has called AllowSetForegroundWindow(ASFW_ANY).

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

The reason is (IMO) that the initiating application is a background process and since it has not received the input it is not allowed to set foreground window. So everything appears in the tasklist but it is not shown.

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

So I tried creating a dummy window to receive input which is closed immideately and afterwards be able to call SetForegroundWindow successfully. But even the dummy window I display is displayed in background.

但是,如果我打电话

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

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

before creating the dummy window, the window is indeed created in foreground and I can afterwards call SetForegroundWindow for a different HWND in a different process which works.

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

BUT: If I do not create the dummy window, SetForegroundWindow still returns zero although I use AttachThreadInput.

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

I don't understand why the AttachThreadInput hack is successful if I create an own Window (and successds for other windows afterwards) but is unsuccessful if I do not create an own window first.

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

How can my background process call SetForegroundWindow on a different window in a different process without creating a dummy window?

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

[*] The background application is actually gpg-agent.exe which calls pinentry.exe (my application) whenever a password is requested. pinentry.exe (running as background process) must request the password from another running application, therefore it must bring its window to foreground ...

推荐答案

文档 为您提供了线索:

The documentation for AttachThreadInput() gives you a clue:

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

Windows created in different threads typically process input independently of each other. That is, they have their own input states (focus, active, capture windows, key state, queue status, and so on), and their input processing is not synchronized with the input processing of other threads. By using the AttachThreadInput function, a thread can attach its input processing mechanism to another thread. Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo parameter until the threads are detached by calling AttachThreadInput a second time and specifying FALSE for the fAttach parameter. This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread. This also allows threads to get key-state information.

SetForegroundWindow() 告诉您调用进程需要满足什么条件才能设置前台窗口:

The documentation for SetForegroundWindow() tells you what criteria the calling process needs to meet in order to set a foreground window:

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

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

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

The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The process is being debugged.
The foreground process is not a Modern Application or the Start Screen.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.

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

Simply creating a dummy window by itself does not guarantee that you will become the foreground process. Attaching your window's thread to the current foreground window's thread allows you to share its input state, which gives you a better chance of gaining permission to set a foreground window if the foreground thread has permission to do so.

这篇关于允许后台应用设置不同进程的前台窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆