Home > database >  How to show a window on top of all windows one time in WPF?
How to show a window on top of all windows one time in WPF?

Time:11-01

I have a singletone instance of window in my WPF application (which is not main window). Due to it's structure, this window only closes when the main window is closed; If the user closes this window, it becomes hidden. When I click on some image in main window, I want the following behaviour of second window:

  1. If window is hidden and image was clicked, I want to show it on top of all windows (but NOT by setting Topmost = true, I want just SHOW it on top, rather than fix it on top forever).
  2. If window is shown on top, there is nothing to do.
  3. If window is open, but covered by other window or minimized, I also want to show it on top only ONCE.

What I have at the moment:

// In some application class
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (App.Current.MyWindow == null)
            {
                App.Current.MyWindow = WeightImageWindowView.Instance;
            }
            App.Current.MyWindow.ShowTop();
        }
...
// in MyWindow class
public void ShowTop()
        {
            this.Topmost = true;
            this.Show();
            if (this.WindowState == WindowState.Minimized)
            {
                this.WindowState = WindowState.Normal;
            }
            var a = this.Activate();
            var b = this.Focus();
            this.Topmost = false;
        }

I tried to use all these commands one by one, in pairs and all together, but didn't get the behaviour described above.

CodePudding user response:

WndHelper.BringToFront(this);

Use the helper below and just call bringtofront

public class WndHelper
    {
        [DllImport("User32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
    
        [DllImport("User32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
    
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsIconic(IntPtr hWnd);
    
        public static void HideWindow(Window window)
        {
            var wih = new WindowInteropHelper(window);
            WndHelper.ShowWindow(wih.Handle, 0);
        }
    
        public static void BringToFront(Window window)
        {
            var wih = new WindowInteropHelper(window);
            BringToFront(wih.Handle);
        }
    
        //If the window is minimized, then Restore must be run first
        //Windows that are in the background are enough to set as Foreground
        public static void BringToFront(IntPtr hWnd)
        {
            if (hWnd == IntPtr.Zero)
                return;
            try
            {
                if (WndHelper.IsIconic(hWnd)) //the window is minimized
                {
                    WndHelper.ShowWindow(hWnd, 9);          // SW_RESTORE = 9
                    WndHelper.SetForegroundWindow(hWnd);    // set window to foreground
                }
                else
                    WndHelper.SetForegroundWindow(hWnd);
            }
            catch { }
        }
    }

CodePudding user response:

Thanks @Villiam! I found the following solution:

  1. Set MyWindow.ShowActivated = true;
  2. Rewrite ShowTop method as:
public void ShowTop()
        {
            if (this.WindowState == WindowState.Minimized)
            {
                this.WindowState = WindowState.Normal;
            }
            this.Topmost = true;
            this.Show();
            this.Topmost = false;
        }
  • Related