From: Bob Altman on
Hi all,

I have two programs (call them A and B). A is the current, visible window
with focus. B may or may not be visible. When a user selects a menu item
on A, A calls a method on B via remoting. The method on B queues the call
to B's UI thread (via Me.BeginInvoke), which then creates and displays a new
window.

The problem is that Windows XP thinks that the user is interacting with A,
so it keeps A's window in front of the new window that B just created.

I could fiddle around with having B make its new windows "top-most", but
that's tacky. I'd rather find a way to tell Windows to allow B's new window
to appear in front of A's window, either by somehow convincing Windows that
the user is no longer interacting with A or by pushing A's window one place
back in the Z-order.

Any suggestions?

TIA - Bob


From: Peter Duniho on
On Tue, 08 Sep 2009 17:29:14 -0700, Bob Altman <rda(a)nospam.nospam> wrote:

> [...]
> I'd rather find a way to tell Windows to allow B's new window
> to appear in front of A's window, either by somehow convincing Windows
> that
> the user is no longer interacting with A or by pushing A's window one
> place
> back in the Z-order.
>
> Any suggestions?

The proper way for doing this is for A and B to coordinate the focus
change. B needs to let A know that B wants to be the foreground window.
Then A can go ahead and set B as the foreground window. Because A is the
current foreground application, it will be permitted to do that, whereas B
not being the current foregound application is not allowed to force itself
there.

If A and B are not tightly integrated enough to do that (which seems
unlikely given the remoting, but I suppose it's possible), then IMHO
you'll just have to live with the current behavior. There are of course
ways to hack around the Windows foreground app rules, but if you do that
you run the risk of introducing user scenarios where the windows are badly
behaved, stealing focus when the user didn't want that to happen.

Pete
From: Colbert Zhou [MSFT] on
Hello Bob,

Thanks for using Microsoft Newsgroup. This is Ji Zhou - MSFT and I will be
working on the issue with you.

Yes, Windows system use a z-order stack to managed the Windows position in
z-axis. But the z-order stack is managed by system as per the default
management approach. There are two ways to change the z-order stack of the
Windows,
1. Manually by user mouse/keyboard input.
2. Programmatically by program automation.

To bring the B application's window in front programmatically, we need to
call SetForegroundWindow API. Before we call application B's function to
create a new window, from application A, we should call SetForegroundWindow
to activate B's main form.

We can get more information about Foreground and Background Windows from
the following documentations,
http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#foreground
http://msdn.microsoft.com/en-us/library/ms633539(VS.85).aspx

For your convenience, I post the important part of documentation here,
-------------------------------------------------
"Each process can have multiple threads of execution, and each thread can
create windows. The thread that created the window with which the user is
currently working is called the foreground thread, and the window is called
the foreground window. All other threads are background threads, and the
windows created by background threads are called background windows.

Each thread has a priority level that determines the amount of CPU time the
thread receives. Although an application can set the priority level of its
threads, normally the foreground thread has a slightly higher priority
level than the background threads. Because it has a higher priority, the
foreground thread receives more CPU time than the background threads. The
foreground thread has a normal base priority of 9; a background thread has
a normal base priority of 7.

The user sets the foreground window by clicking a window, or by using the
ALT+TAB or ALT+ESC key combination. To retrieve a handle to the foreground
window, use the GetForegroundWindow function. To check if your application
window is the foreground window, compare the handle returned by
GetForegroundWindow to that of your application window.

An application sets the foreground window by using the SetForegroundWindow
function.

Windows NT 4.0 and earlier, Windows 95: If the new foreground window is a
top-level window, the system activates it; otherwise, it activates the
associated top-level window.

Windows 98/Me/2000/XP: 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 foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT
in SystemParametersInfo).
Windows 2000/XP: No menus are active.
Windows 2000/XP: A process that can set the foreground window can enable
another process to set the foreground window by calling the
AllowSetForegroundWindow function, or by calling the BroadcastSystemMessage
function with the BSF_ALLOWSFW flag. The foreground process can disable
calls to SetForegroundWindow by calling the LockSetForegroundWindow
function.
"
----------------------------------------------------------------

If you have any future questions or concerns, please feel free to let me
know. Have a nice day!


Best regards,
Ji Zhou
Microsoft Online Support Team



From: Bob Altman on
> [A] should call SetForegroundWindow to activate B's main form.

That's my problem. B's main form is hidden.

I guess I could modify B so that the remoted functions that tell B to create
new windows would return the handle to the newly created window. A could
then call SetForegroundWindow to activate that new window. But I'd rather
not do that because that would require quite a bit of new plumbing in B.
This is why I was fishing for a solution that A could implement without
intimate knowledge of B's windows.

At least now I have a good explanation for how the mysterious
foreground/background windows management thing works
(http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#foreground).
I'm guessing that my only option will be for A to get its hands on B's newly
created window handle so that A can make B's new window a foreground window.

Bob

From: Bob Altman on
> I'm guessing that my only option will be for A to get its hands on B's
> newly created window handle so that A can make B's new window a
> foreground window.

I did that and it works like a champ. Thanks for pointing me in the right
direction...

Bob