0

I have a window that is shown from a WPF application using the ShowDialog() method. Inside this dialog window, I need to call the native SetForegroundWindow to bring some other app in the foreground, and then I need to call SetForegroundWindow again to bring this window back into the foreground.

The dialog window can be opened using a button (that has a command binding) or a key (KeyUp event is handled and ShowDialog() is called).

Everything works fine when the button is clicked (the dialog is shown -> the other application is brought into the foreground -> the dialog is brought into the foreground again). However, when the key is used, the dialog window is no longer brought into the foreground after SetForegroundWindow is used on the other application and the taskbar is flashing orange (indicating that the window requested foreground, but Windows blocked it because it thought that the dialog window is trying to steal focus).

This is the code that I am using when opening the dialog window:

try
{
  await BringApplicationIntoForegroundAsync(hWnd); // this code brings application into foreground at some point

  // do some work
}
finally
{
  SetForegroundWindow(hWnd);
}

If I send any key or click on the dialog window before calling BringApplicationIntoForegroundAsync(hWnd) everything works fine (even if the dialog was opened using a key).

If the dialog is opened using a key and the user does not interact with it before the first SetForegroundWindow, the second SetForegroundWindow does not work (returns false).

My guess is that when the button is used to open the dialog, somehow the dialog receives input and Windows allows it to call SetForegroundWindow the second time.

  • Sounds like a bug in the Windows API... Maybe simulate a keypress to work around the issue? Someone else had a similar (but different) issue and fixed it that way: https://stackoverflow.com/questions/10740346/setforegroundwindow-only-working-while-visual-studio-is-open – Matthew Watson Aug 30 '21 at 08:20
  • Thanks for help Matthew! Maybe I am doing something wrong since the click event opens the dialog window in the correct state while keyup event doesn't. However, it feels a bit hacky to simulate a keypress on the window to work around this, but if there is no other option, I will use this approach. – Alex Petrescu Aug 30 '21 at 23:05

1 Answers1

0

If your end goal is to ensure that your dialog window is the top-most window, and the other app is the window underneath it, then using SetForegroundWindow twice would not be the right choice because as you stated, when you call SetForegroundWindow a 2nd time, your app no longer has focus (the other app has it) and can therefore not do it.

Instead, try SetWindowPos. This will let you specifically set one window (the other app) behind another window (your dialog window).

Example:

SetWindowPos(OtherAppHandle, DialogWindowHandle, 0, 0, 0, 0, 
    (uint)(NativeMethods.SET_WINDOW_POSITION.SWP_NOSIZE |
    NativeMethods.SET_WINDOW_POSITION.SWP_NOMOVE |
    NativeMethods.SET_WINDOW_POSITION.SWP_NOACTIVATE |
    NativeMethods.SET_WINDOW_POSITION.SWP_NOREDRAW));
Tam Bui
  • 2,940
  • 2
  • 18
  • 27
  • Thank you for help Tam Bui! Unfortunately, my end goal is not to have the other window just behind my dialog window. The first SetForegroundWindow is more like a given. I can't replace it with SetWindowPos. The other application is brought into foreground using SetForegroundWindow and then some custom logic is performed. When everything is finished, I need to bring my dialog window back into foreground (using SetForegroundWindow or something else). – Alex Petrescu Aug 30 '21 at 23:07