7

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

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).

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.

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.

However, if I call

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

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.

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

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.

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

[*] 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 ...

divB
  • 896
  • 1
  • 11
  • 28
  • Possible duplicate of http://stackoverflow.com/questions/688337/how-do-i-force-my-app-to-come-to-the-front-and-take-focus – nobody May 17 '14 at 19:08
  • No, not in my opinion because I do not want to create an own dummy window. SetForegroundWindow for a different window/process does not work even with AttachThreadInput; when I create my own (dummy) window it works. – divB May 17 '14 at 19:17
  • You can't do it. If you don't *have* focus, you can't give it away. As Raymond says, "you can't give away something that isn't yours". This is a very deliberate design decision in Windows. http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx – nobody May 17 '14 at 19:21
  • As mentioned in the beginning, I hope we can keep this discussion technical. So in this case it *must* be possible because my background app can do whatever it wants (up to injecting itself in a different process). And as I mentioned: It also works when I create a dummy window. The questions is: What is the least invasive way? – divB May 17 '14 at 19:23
  • Or rephrased the question: What does the AttachThreadInput hack let me focus a Window that I created on my own but still fails for other windows? – divB May 17 '14 at 19:24
  • 1
    What is a background process? – David Heffernan May 17 '14 at 21:01
  • To my definition it is just a process running in background with no window and therefore no mouse/keyboard input. (For example, a simple TCP server just listening for connections) – divB May 18 '14 at 00:54

1 Answers1

1

The documentation for AttachThreadInput() gives you a clue:

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.

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:

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770