views:

733

answers:

3

I'm making another app's window topmost to ensure that a click in my app brings the other's dialog into views. The problem I'm having is that I don't get focus back to my app after the call. If the other app has more windows one of them ends up with focus, and otherwise no window (looking at the taskbar only) gets focus. Where should I start investigating the issue?

My code for making the other app topmost is:

Process p = Process.GetProcessById(trackedProcessID);
IntPtr h = p.MainWindowHandle;
uint TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS;
SetWindowPos(h, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);

with constants as

public static readonly uint SWP_NOMOVE = 0x0002;
public static readonly uint SWP_NOSIZE = 0x0001;
public static readonly uint SWP_ASYNCWINDOWPOS = 0x4000;
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
+2  A: 

Related: Unexpected behaviour of Process.MainWindowHandle

Basically MainWindowHandle gives you the current top-most window of the process despite what the documentation says.

That explains why the main window of your other process doesn't necessarily get focus.

Your other problem is because you are not returning focus to your app after giving it away.

Actually, the correct term for what you are doing is establishing z-order.

Instead of trying to control z-order - which cannot be guaranteed - you might be better off sending messages to the other process.

Ed Guiness
Very interesting! But even if my second app only has one visible window (again, from taskbar which might not be a good source) I would have expected that once the dialog in the other app closed mine would get focus back. Or?
Oskar
No, not necessarily, you would need to return focus (actually the term here is correctly z-order) to your app.
Ed Guiness
Could I do that by lining up the other app just ahead of mine in the Z-order, or do I have to get the other app to push me up (please tell me I can ...)
Oskar
+2  A: 

Have you tried SWP_NOACTIVATE?

Joel Lucsy
Doesn't seem to have any effect, what would you expect it to do?
Oskar
I would expect it to not activate the other top level window. Without activation, it will not be given focus.
Chris Becke
A: 

[Actual solution used]

So far I'm going with sending the window handle of the calling window to the target app, and getting it to push it back on top when finished. It is a real pain as I will have ~50 windows to deal with, but it seems stable. The next approach, if this turns out to have problems, will be to call back to the calling app and ask it to push the window to the foreground, but I'd rather not as it introduces a possiblity that the user can do something to the calling app while the message is in transit (only a problem if there is a lot of messages comming in on the same transport protocol, which could well happen)

Do not try to use the incoming window handle and set the parent of any window shown in the target app to that handle, it only makes the shown dialog to appear within the bounds of the calling app window, and cropped if necessary - useless

Many thanks for the answers above to the question

Oskar