Bring a window to the front in WPF

200,825

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.

Share:
200,825

Related videos on Youtube

Factor Mystic
Author by

Factor Mystic

Hello World

Updated on December 17, 2021

Comments

  • Factor Mystic
    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 have SetLastError=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
      Todd White over 15 years
      Have 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
      Factor Mystic over 15 years
      Good thought, but it is the only Window in the application.
    • Todd White
      Todd White over 15 years
      Can you give a bit more context code?
  • Factor Mystic
    Factor Mystic over 15 years
    Good point. The purpose of the code was in conjunction with a global hotkey, though, and other applications do it somehow.
  • Bermo
    Bermo over 14 years
    I 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.
    Simon D. over 14 years
    Just interested: Did you try Window.Activate (as suggested by Morten) and the other suggestions? They seem less hacky than this admitted kludge.
  • Factor Mystic
    Factor Mystic over 14 years
    This has been quite awhile ago, but yes, at the time I did try that
  • Lex Li
    Lex Li over 13 years
    Have to use PInvoke in C# to emulate what is described in this article, codeproject.com/Tips/76427/…
  • Lex Li
    Lex Li over 13 years
    Activate does not work on Windows XP sometimes. I recommend @Matthew Xavier 's answer.
  • Lex Li
    Lex Li over 13 years
    If you develop something similar to Launchy (launchy.net) in C#, you should notice this answer is almost useless.
  • Lex Li
    Lex Li over 13 years
    This does not work on my Windows XP. I recommend @Matthew Xavier 's answer.
  • aruno
    aruno over 13 years
    then why do expression blends error popup dialogs stay visible when I switch to visual studio sometimes? :-/
  • Matthew Xavier
    Matthew Xavier over 13 years
    Simon, 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
    Lex Li over 13 years
    The 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
    greenoldman almost 13 years
    A bit odd, since by default ShowActivated is on.
  • stijn
    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
    gsb over 11 years
    Great hint! TopMost makes the magic happen on Windows 7 if the window is already open, but below the other windows.
  • Jen
    Jen almost 11 years
    This did the trick for me too. Thanks to gsb for the additional comment about what looks like a strange use of TopMost!
  • code4life
    code4life almost 10 years
    Thanks - the fix was short and sweet.
  • virious
    virious almost 10 years
    In my case Window.Activate() and Window.Focus() were sufficient. Setting Window.TopMost is unnecessary.
  • Jonathan Perry
    Jonathan Perry almost 10 years
    The 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
    Oleg Ignatov over 9 years
    It doesn't work on Windows 7 if the window is already open, but below other windows
  • Sriram Sakthivel
    Sriram Sakthivel over 9 years
    Any reason for not using process.MainWindowHandle?
  • jdnew18
    jdnew18 over 9 years
    Your addition of 'Window.Focus();' made me realize that I needed it in my own code! Thanks!
  • tobriand
    tobriand about 9 years
    In my case, I didn't want the main window, but agreed, there's other ways of getting an hWnd. FWIW an HwndSource object worked well.
  • mdiehl13
    mdiehl13 almost 9 years
    Hey lookie there! I've been struggling with this for months! This works for both my situations. Awesome! (Windows 7 x64)
  • mdiehl13
    mdiehl13 almost 9 years
    Actually, 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
    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
    Contango about 8 years
    Do 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
    Contango about 8 years
    Speaking 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
    demo.b about 8 years
    Topmost = true; was what i was looking for. Thank you
  • Raven
    Raven almost 8 years
    This 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
    Nicolas Fall over 7 years
    in 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 after ShowDialog() see gist.github.com/ImaginaryDevelopment/…
  • dyasta
    dyasta over 7 years
    That 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
    r41n about 7 years
    Won't restore minimized windows. You'll need to store the last state of the window and restore that or use the Topmost hack.
  • r41n
    r41n about 7 years
    Actually 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
    dev1998 almost 7 years
    I got this to work by calling it in the Window Loaded event. It was not working for me in the constructor.
  • Noel Widmer
    Noel Widmer almost 7 years
    Hi 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
    Mike almost 7 years
    Only 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
    Noel Widmer almost 7 years
    Sure, 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
    Brian Reichle almost 7 years
    This question was specifically about WPF, but your solution is for WinForms.
  • Kryptos
    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 or ShiftWindowOntoScreenHelper. Plus asking to create the window in viewmodel side (which basically breaks the whole MVVM pattern)...
  • Contango
    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
    Igor Meszaros about 5 years
    I 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
    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
    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
    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 one OP asked.
  • SiL3NC3
    SiL3NC3 almost 4 years
    Works for me with splash screen showing before. Thank you.
  • Cogent
    Cogent about 3 years
    Thank you. This worked when most other methods I've tried failed (I haven't tried every suggestion in this question).
  • Gabe Halsmer
    Gabe Halsmer over 2 years
    Several 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.