Search code examples
c#wpf

WindowStartupLocation = WindowStartupLocation.CenterScreen doesn't work correctly


property of window : WindowStartupLocation = WindowStartupLocation.CenterScreen doesn't work well. I changed this property in XAML and XAML.cs, but window didn't in the center of screen in runtime. here is code in XAML:

 Title="MainWindow" Height="1080" Width="1920" WindowStyle="None" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" AllowsTransparency="True"

here is code in XAML.cs

public MainWindow()
    {
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        InitializeComponent();
    }

Did I do something wrong? Please give me an advise, thanks in advance Capture of screen in runtime


Solution

  • You might be trying to create a window that’s larger than the screen. Even if your LCD has 1920x1080 pixels, some height is usually consumed by task bar, also you might have DPI scaling > 100%. WPF’s size units aren’t pixels, they’re DPI virtualized units. To check or change DPI scaling, right click on empty space on desktop, “Display settings”, “Scale and layout”, “Change the size of text, apps and other items”.

    Another possible reason is per-monitor DPI awareness. On some multi-monitor systems these size units depend on the monitor containing center of the window, and the scaling changes dynamically as the window is moved. It’s relatively hard to center or maximize WPF’s window on such system, and WPF framework has known bugs Microsoft is neglecting to fix. If that’s your case, query desktop geometry using WinAPI or better Screen.AllScreens from win.forms, then in OnSourceInitialized method call MoveWindow WinAPI to position the window. Both Screen.AllScreens and MoveWindow WinAPI use the same size units, they aren't pixels either but at least they're consistent between the two, i.e. should work (WPF's coordinate scaling is generally different). Here's how to position a WPF window with that WinAPI:

    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Interop;
    
    static class WindowExt
    {
        // http://www.pinvoke.net/default.aspx/user32.movewindow
        [DllImport( "user32.dll", SetLastError = true )]
        static extern bool MoveWindow( IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint );
    
        public static void moveWindow( this Window window, Rectangle rect )
        {
            var wih = new WindowInteropHelper( window );
            IntPtr hWnd = wih.Handle;
            MoveWindow( hWnd, rect.Left, rect.Top, rect.Width, rect.Height, false );
        }
    }
    

    You'll need to compute the rectangle manually, from Screen.WorkingArea.