2
votes

By now everyone writing for Windows probably knows that applications cannot (officially) steal focus from foreground processes, and why. But I have just managed to steal focus, inadvertently, and don't understand how this is even possible.

I have a Delphi app that user brings up with a hotkey (or by a mouse click, or by Alt+Tab), selects a piece of text and hits Enter. My app then minimizes (hides to the tray, even), and pastes the text user just selected into the active window. Nothing new here, plenty of similar projects out there - clipboard extenders, glossaries, macro programs, etc.

What is puzzling to me is that after doing all the above and then sleeping for 1500 ms, I restore my main form and it gets the focus back! It becomes the foreground window, even though it wasn't 1500 ms ago (tested; Windows 7 32-bit.).

In fact, I don't want this at all, so before restoring my main form I record which window has foreground and I give it back to that window after it's been given to me. I'm just curious why my app gets to be in the foreground when by rules it should not. Maybe I don't understand the rules as fully as I thought I did?

1
It doesn't have anything to do with your program sleeping for 1500 msec, it depends on how long the user is asleep. Apps can steal the foreground if the user isn't generating any input events. - Hans Passant
The Sleep is just to give all windows time to get their stuff in order. It's the minimizing and the hiding of the main form that should take the focus away from me (and they do; GetForegroundWindow returns a window other than my own). So there is a point at which I'm certain my window does not have focus, and yet it gets it back on Restore. I didn't know about the dependency on input events - that sounds like an answer if you post it as one. Can you say more? Can any process make itself foreground after the user hasn't touched the keyboard or mouse for a while? - Marek Jedliński

1 Answers

2
votes

If you look at the documentation for SetForegroundWindow you see a list of conditions for the call to succeed, one of them is "The process received the last input event." So if the user does not do anything after pressing enter in your app you still have the right to steal focus. I don't know if Delphi calls SetForegroundWindow for you when the window is restored but it might be something to look into.

I don't know how you restore your window but using SW_SHOWNOACTIVATE with ShowWindow might help...