Bring a window to the front in WPF
Solution 1
Well I figured out a work around. I'm making the call from a keyboard hook used to implement a hotkey. The call works as expected if I put it into a BackgroundWorker with a pause. It's a kludge, but I have no idea why it wasn't working originally.
void hotkey_execute()
{
IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(delegate
{
Thread.Sleep(10);
SwitchToThisWindow(handle, true);
});
bg.RunWorkerAsync();
}
Solution 2
myWindow.Activate();
Attempts to bring the window to the foreground and activates it.
That should do the trick, unless I misunderstood and you want Always on Top behavior. In that case you want:
myWindow.TopMost = true;
Solution 3
I have found a solution that brings the window to the top, but it behaves as a normal window:
if (!Window.IsVisible)
{
Window.Show();
}
if (Window.WindowState == WindowState.Minimized)
{
Window.WindowState = WindowState.Normal;
}
Window.Activate();
Window.Topmost = true; // important
Window.Topmost = false; // important
Window.Focus(); // important
Solution 4
In case you need the window to be in front the first time it loads then you should use the following:
private void Window_ContentRendered(object sender, EventArgs e)
{
this.Topmost = false;
}
private void Window_Initialized(object sender, EventArgs e)
{
this.Topmost = true;
}
Or by overriding the methods:
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
Topmost = false;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
Topmost = true;
}
Solution 5
I know this question is rather old, but I've just come across this precise scenario and wanted to share the solution I've implemented.
As mentioned in comments on this page, several of the solutions proposed do not work on XP, which I need to support in my scenario. While I agree with the sentiment by @Matthew Xavier that generally this is a bad UX practice, there are times where it's entirely a plausable UX.
The solution to bringing a WPF window to the top was actually provided to me by the same code I'm using to provide the global hotkey. A blog article by Joseph Cooney contains a link to his code samples that contains the original code.
I've cleaned up and modified the code a little, and implemented it as an extension method to System.Windows.Window. I've tested this on XP 32 bit and Win7 64 bit, both of which work correctly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;
namespace System.Windows
{
public static class SystemWindows
{
#region Constants
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;
#endregion
/// <summary>
/// Activate a window from anywhere by attaching to the foreground window
/// </summary>
public static void GlobalActivate(this Window w)
{
//Get the process ID for this window's thread
var interopHelper = new WindowInteropHelper(w);
var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);
//Get the process ID for the foreground window's thread
var currentForegroundWindow = GetForegroundWindow();
var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);
//Attach this window's thread to the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);
//Set the window position
SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
//Detach this window's thread from the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);
//Show and activate the window
if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
w.Show();
w.Activate();
}
#region Imports
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
#endregion
}
}
I hope this code helps others who encounter this problem.
Related videos on Youtube
Comments
-
Factor Mystic over 2 years
How can I bring my WPF application to the front of the desktop? So far I've tried:
SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true); SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);
None of which are doing the job (
Marshal.GetLastWin32Error()
is saying these operations completed successfully, and the P/Invoke attributes for each definition do haveSetLastError=true
).If I create a new blank WPF application, and call
SwitchToThisWindow
with a timer, it works exactly as expected, so I'm not sure why it's not working in my original case.Edit: I'm doing this in conjunction with a global hotkey.
-
Todd White over 15 yearsHave you verified that MainWindow is the window you want? From MSDN: MainWindow is automatically set with a reference to the first Window object to be instantiated in the AppDomain.
-
Factor Mystic over 15 yearsGood thought, but it is the only Window in the application.
-
Todd White over 15 yearsCan you give a bit more context code?
-
-
Factor Mystic over 15 yearsGood point. The purpose of the code was in conjunction with a global hotkey, though, and other applications do it somehow.
-
Bermo over 14 yearsI was simply using myWindow.Show() and sometimes it wasn't on top. I placed a call to myWindow.Activate() immediately afterwards and it worked.
-
Simon D. over 14 yearsJust interested: Did you try Window.Activate (as suggested by Morten) and the other suggestions? They seem less hacky than this admitted kludge.
-
Factor Mystic over 14 yearsThis has been quite awhile ago, but yes, at the time I did try that
-
Lex Li over 13 yearsHave to use PInvoke in C# to emulate what is described in this article, codeproject.com/Tips/76427/…
-
Lex Li over 13 yearsActivate does not work on Windows XP sometimes. I recommend @Matthew Xavier 's answer.
-
Lex Li over 13 yearsIf you develop something similar to Launchy (launchy.net) in C#, you should notice this answer is almost useless.
-
Lex Li over 13 yearsThis does not work on my Windows XP. I recommend @Matthew Xavier 's answer.
-
aruno over 13 yearsthen why do expression blends error popup dialogs stay visible when I switch to visual studio sometimes? :-/
-
Matthew Xavier over 13 yearsSimon, I suspect that the error popups you see are "topmost" windows (a design decision of which I disapprove). There is a difference between the foreground window (which receives user input) and a "topmost" window in the Z-order. Any window can make itself "topmost", which places it atop all non-topmost windows, but doesn't give the window keyboard focus, etc. the way becoming the foreground window does.
-
Lex Li over 13 yearsThe trick fails for a few special windows. Visual Studio and command prompt windows must have something that prevents other window becoming the foreground window.
-
greenoldman almost 13 yearsA bit odd, since by default ShowActivated is on.
-
stijn over 12 years+1 this is the only answer that was useful for me. I have an application with one master and several floating slave windows. Upon activating any of these, all other windows should be brought to front as well. But not activated/gain focus as most answers suggest: that is a disaster as it makes the window currently clicked on unclickable since suddenly another window gains focus.
-
gsb over 11 yearsGreat hint! TopMost makes the magic happen on Windows 7 if the window is already open, but below the other windows.
-
Jen almost 11 yearsThis did the trick for me too. Thanks to gsb for the additional comment about what looks like a strange use of TopMost!
-
code4life almost 10 yearsThanks - the fix was short and sweet.
-
virious almost 10 yearsIn my case Window.Activate() and Window.Focus() were sufficient. Setting Window.TopMost is unnecessary.
-
Jonathan Perry almost 10 yearsThe first answer is good, thanks for that! But the second line of code, using the
Topmost
property is a bad practice since it can obscure other popup dialogs and have unexpected behavior. -
Oleg Ignatov over 9 yearsIt doesn't work on Windows 7 if the window is already open, but below other windows
-
Sriram Sakthivel over 9 yearsAny reason for not using
process.MainWindowHandle
? -
jdnew18 over 9 yearsYour addition of 'Window.Focus();' made me realize that I needed it in my own code! Thanks!
-
tobriand about 9 yearsIn my case, I didn't want the main window, but agreed, there's other ways of getting an
hWnd
. FWIW anHwndSource
object worked well. -
mdiehl13 almost 9 yearsHey lookie there! I've been struggling with this for months! This works for both my situations. Awesome! (Windows 7 x64)
-
mdiehl13 almost 9 yearsActually, it only seems to work if I do this: App.mainWindow.Show(); SystemWindows.GlobalActivate(App.mainwindow); // When I remove the first .show() it does not bring to front
-
prettyvoid over 8 years+1 for SetWindowPos(), I was looking for a way to only bring my Window to front without interrupting other apps or stealing focus. this.Activate() steals focus.
-
Contango about 8 yearsDo not use
Window.Focus()
. This will grab the focus away from what the user is currently typing in a text box, which is insanely frustrating for end users. The code above works just fine without it. -
Contango about 8 yearsSpeaking of the comment above, we have an old VB6 program which calls Window.Focus() when showing an alert. It pops up 5 alerts every 10 minutes, and every time, it grabs the focus away, and the user loses whatever they were typing, and they have to use the mouse to put the cursor back where it was. It drives hundreds of user crazy.
-
demo.b about 8 yearsTopmost = true; was what i was looking for. Thank you
-
Raven almost 8 yearsThis did it for me, and it my case the whole point was to steal focus, as it happend when a user interacted with certain element. so Thanks alot this seems to work consistent! just calling
this.Activate()
only seems to work some times. -
Nicolas Fall over 7 yearsin my use case,
window.Focus()
is useful, used because other windows in the same app may have opened that are supposed to be background windows, and this is only used at app startup. For an example of doing this afterShowDialog()
see gist.github.com/ImaginaryDevelopment/… -
dyasta over 7 yearsThat is a clever solution, I wonder if Microsoft 'fixed' it later, as it violates their intended 'protection' of bringing windows to the front by your toggle of the 'topmost' attribute.
-
r41n about 7 yearsWon't restore minimized windows. You'll need to store the last state of the window and restore that or use the Topmost hack.
-
r41n about 7 yearsActually it can be done with this:
if (myWindow.WindowState == WindowState.Minimized) myWindow.WindowState = WindowState.Normal;
Oddly it will also preserve any Maximized windows and not revert them to a Normal state. -
dev1998 almost 7 yearsI got this to work by calling it in the Window Loaded event. It was not working for me in the constructor.
-
Noel Widmer almost 7 yearsHi Mike. You are answering this question quite late. Can you explain in your answer why this approach is different (and perhaps better) from the very good answers that were already posted for this question?
-
Mike almost 7 yearsOnly late as I just needed to do this, and I came across this and wanted to share how i solved the problem encase others wanted to use it.
-
Noel Widmer almost 7 yearsSure, I was choosen to review your post and wanted to make you aware. It is always good to provide a new answer if you think it is a good contribution to the community.
-
Brian Reichle almost 7 yearsThis question was specifically about WPF, but your solution is for WinForms.
-
Kryptos over 5 years"Enterprise level code" and a few lines later
catch (Exception) { }
. Yeah right... And it uses code that isn't even shown in the answer like_dialogService
orShiftWindowOntoScreenHelper
. Plus asking to create the window in viewmodel side (which basically breaks the whole MVVM pattern)... -
Contango over 5 years@Kryptos This is enterprise level code. I typed it out from memory, and this exact technique is used in a large FTSE100 company. Real life is somewhat less pristine compared to the perfect design patterns that we are all aiming for.
-
Igor Meszaros about 5 yearsI don't like the fact that we keep an instance of the window in the view model myself, as Kryptos mentioned that breaks the whole point of mvvm, maybe it could have been done in codebehind instead?
-
Contango about 5 years@Igor Meszaros Agreed. Now that I have more experience, if I had to do it again, it I would add a Behavior, and control it using a
Func<>
that is bound to the ViewModel. -
Lightness Races in Orbit over 4 years"Title of Your app WITHOUT FIRST LETTER" Oof, hacky hacky hacky. Why not use
IndexOf
properly, instead? -
nam almost 4 years@MortenChristiansen My main window has a data grid that is loaded from constructor of the window. When the main window is opened from another window (that updates the data) the datagrid gets refreshed with updated data. Your solution did not refresh the datagrid with the updated data. This solution from
@Jader Dias
worked for me. However, your solution probably suits better in some other scenarios such as the oneOP
asked. -
SiL3NC3 almost 4 yearsWorks for me with splash screen showing before. Thank you.
-
Cogent about 3 yearsThank you. This worked when most other methods I've tried failed (I haven't tried every suggestion in this question).
-
Gabe Halsmer over 2 yearsSeveral years ago I found the top-rated answer (Activate/TopMost) worked and up-voted it. But now today in Windows 10, I have repeatable examples were it does not work. This answer fortunately DOES work in those edge cases.