8

I want to bring to front a window(from other application). Currently I'm using:

::SetWindowPos(hwnd, GetForegroundWindow(), 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);

It works fine, but in some (unknown to me) cases, it makes the window always on top. According to MSDN, I should use HWND_NOTOPMOST in the place of GetForegroundWindow() but it doesn't work—the window stays under other (not always on top) windows.

How can I bring a window to the front without activating it?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
SathOkh
  • 826
  • 2
  • 12
  • 24
  • The documentation says that `HWND_NOTOPMOST` "has no effect if the window is already a non-topmost window". – Cody Gray - on strike Mar 10 '11 at 10:03
  • Some alternatives here: http://stackoverflow.com/questions/916259/win32-bring-a-window-to-top – Sedat Kapanoglu Mar 10 '11 at 10:05
  • *None* of the proposed answers to the other question are a good solution. That entire question is just a mess. David's got your answer here. – Cody Gray - on strike Mar 10 '11 at 10:09
  • I think I can't use that alternatives - all of them(I think) activate window, and I can't do this. – SathOkh Mar 10 '11 at 10:09
  • I've deleted my answer. It doesn't work. I don't think you can do this without taking over the input focus. I think the window manager is designed to let users decide which window is on top rather than programs. – David Heffernan Mar 10 '11 at 10:44
  • @Cody I just don't think it can be done, but I'm not sure enough to post that as an answer! – David Heffernan Mar 10 '11 at 11:03
  • Ah, I missed the part of the question where it says a window from *another application*. Yeah, you can't do this for windows that live in another process. – Cody Gray - on strike Mar 10 '11 at 11:04
  • Make it a topmost first with `HWND_TOPMOST`, and then a second call with `HWND_NOTOPMOST` to make it not so? – Sertac Akyuz Mar 10 '11 at 11:38
  • 1
    Thanks, looks like it works! :) `::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); ::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);` – SathOkh Mar 10 '11 at 12:53
  • @Sath - You're welcome! Promoted the comment to an answer. – Sertac Akyuz Mar 10 '11 at 13:55

1 Answers1

13

The other application's window can be made temporarily 'top-most' to bring it to front without activating it, first by specifying HWND_TOPMOST as 'hWndInsertAfter' in a SetWindowPos call and then by specifying HWND_NOTOPMOST in a second call (both calls with SWP_NOACTIVATE in 'uFlags'). If there's a risk of removing the top-most style of a window which is already top-most as a consequence of the operation, the WS_EX_TOPMOST ex-style can be tested beforehand with a call to GetWindowLong[Ptr].

If there's a particular window that the other application's window need to be in front (as opposed to being in front of all windows), that window's owner can be set, again temporarily, to the window it needs to be in front. GetWindowLong[Ptr] with GWL_HWNDPARENT can be used to store the window's original owner, then a call to SetWindowLong[Ptr] to set the temporary owner, followed by a call to SetWindowPos with HWND_TOP, and then restoring the original owner with again SetWindowLong[Ptr].

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169