Click here to Skip to main content
13,861,701 members
Click here to Skip to main content
Add your own
alternative version


15 bookmarked
Posted 13 Jan 2017
Licenced CPOL

Wpf windows on two screens

, 2 Jul 2017
Rate this:
Please Sign up or sign in to vote.
The post shows how to position Wpf window on secondary monitor or show two windows on two monitors.

Source code


The post shows how to position Wpf window on secondary monitor or show two windows on two monitors. The post contains complete code and we discuss how to address several scenario.

There are the following disclaimers:

  1. provided code and conclusions base on empiric results, so could be wrong or describe thing not correctly;
  2. the code was tested on computer with two monitors, so three and more monitors could behave differently;
  3. there are many topics concerning how to show or manipulate by the secondary monitor in Wpf application. The post doesn't include these links, as it may be easily googled.

Original post is published at blog. It contains screenshots from computer with two displays.



Application demonstrates the following features:

  1. output maximized windows on all displays;
  2. window contains list box with sizes of screens from system parameters and Screen class;
  3. using of dependency container.


Solution uses C#6, .Net 4.6.1, Wpf with MVVM pattern, System.Windows.Forms, System.Drawing, NuGet packages Unity and Ikc5.TypeLibrary.


Solution contains one Wpf application project. From the Wpf application all screens are considered as one "virtual" screen. In order to position window it is necessary set window coordinates in "current" screen size. SystemParameters provides physical resolution of the primary screen, but according to Wpf architecture position of elements should not rely on physical dimensions of the display. The main issue is that exact value of "current" screen size depends on various factors. For example, they include text size from Windows' settings, how user connects to computer - by remote access or locally, and so on.

Screen class from System.Windows.Forms library provides useful property Screen[] AllScreens. It allows enumerate all screen and reads their working area. But coordinates of non-primary screen are set according to "current" text size of the primary window.


As windows are created manually, StartupUri should be removed from App.xaml. Method OnStartup executes the following code:

  • init Unity container;
  • calculate current text size of the primary screen as ratio between Screen.PrimaryScreen.WorkingArea and SystemParameters.PrimaryScreen;
  • for each screen create window, position at current screen, show and maximize.
public partial class App : Application
    private void InitContainer(IUnityContainer container)
        container.RegisterType<ILogger, EmptyLogger>();
        container.RegisterType<IMainWindowModel, MainWindowModel>();

    protected override void OnStartup(StartupEventArgs e)

        IUnityContainer container = new UnityContainer();

        var logger = container.Resolve<ILogger>();
        logger.Log($"There are {Screen.AllScreens.Length} screens");

        // calculates text size in that main window (i.e. 100%, 125%,...)
        var ratio = Math.Max(Screen.PrimaryScreen.WorkingArea.Width / SystemParameters.PrimaryScreenWidth,
                            Screen.PrimaryScreen.WorkingArea.Height / SystemParameters.PrimaryScreenHeight);

        var pos = 0;
        foreach (var screen in Screen.AllScreens)
                $"#{pos + 1} screen, size = ({screen.WorkingArea.Left}, {screen.WorkingArea.Top}, {screen.WorkingArea.Width}, {screen.WorkingArea.Height}), " +
                (screen.Primary ? "primary screen" : "secondary screen"));

            // Show automata at all screen
            var mainViewModel = container.Resolve<IMainWindowModel>(
                new ParameterOverride("backgroundColor", _screenColors[Math.Min(pos++, _screenColors.Length - 1)]),
                new ParameterOverride("primary", screen.Primary),
                new ParameterOverride("displayName", screen.DeviceName));

            var window = new MainWindow(mainViewModel);
            if (screen.Primary)
                Current.MainWindow = window;

            window.Left = screen.WorkingArea.Left / ratio;
            window.Top = screen.WorkingArea.Top / ratio;
            window.Width = screen.WorkingArea.Width / ratio;
            window.Height = screen.WorkingArea.Height / ratio;
            window.WindowState = WindowState.Maximized;
        Current.ShutdownMode = ShutdownMode.OnMainWindowClose;

    private readonly Color[] _screenColors =
        Colors.LightGray, Colors.DarkGray, Colors.Gray, Colors.SlateGray, Colors.DarkSlateGray


Main window contains ListView that shows the list of ScreenRectangle models from MainWindowModel view model. In order to show window on expected screen, it should has the following properties:


In addition, we remove caption bar and make window non-resizable


If comment line #45 in App.xaml.cs

window.WindowState = WindowState.Maximized;

then window will occupy whole screen except taskbar.


MainWindowModel class implements IMainWindowModel interface

public interface IMainWindowModel
    /// <summary>
    /// Background color.
    /// </summary>
    Color BackgroundColor { get; }
    /// <summary>
    /// Width of the view.
    /// </summary>
    double ViewWidth { get; set; }
    /// <summary>
    /// Height of the view.
    /// </summary>
    double ViewHeight { get; set; }
    /// <summary>
    /// Set of rectangles.
    /// </summary>
    ObservableCollection<ScreenRectangle> Rectangles { get; }

Background color is used to colorized window and distinct them at different screens. ViewHeight and ViewWidth are bound to attached properties in order to obtain view size in view model (code is taken from Pushing read-only GUI properties back into ViewModel). ScreenRectangle class looks like derived class from Tuple<string, Rectangle> that implements NotifyPropertyChanged interface:

public class ScreenRectangle : BaseNotifyPropertyChanged
    protected ScreenRectangle()
        Name = string.Empty;
        Bounds = new RectangleF();

    public ScreenRectangle(string name, RectangleF bounds)
        Name = name;
        Bounds = bounds;

    public ScreenRectangle(string name, double left, double top, double width, double height)
        : this(name, new RectangleF((float)left, (float)top, (float)width, (float)height))

    public ScreenRectangle(string name, double width, double height)
        : this(name, new RectangleF(0, 0, (float)width, (float)height))

    #region Public properties

    private string _name;
    private RectangleF _bounds;

    public string Name
        get { return _name; }
        set { SetProperty(ref _name, value); }

    public RectangleF Bounds
        get { return _bounds; }
        set { SetProperty(ref _bounds, value); }

    #endregion Public properties

    public void SetSize(double width, double height)
        Bounds = new RectangleF(Bounds.Location, new SizeF((float)width, (float)height));


Update 1

The sample application was updated. Now it shows more system parameters and some sizes and dimensions are commented.

The main changes was done in the constructor of MainWindowModel class.

public MainWindowModel(Color backgroundColor, bool primary, string displayName)
	BackgroundColor = backgroundColor;

	_rectangles = new ObservableCollection<screenrectangle>(new[]
		new ScreenRectangle(ScreenNames.View, ViewWidth, ViewHeight,
			"View uses border with BorderThickness='3', and its size is lesser than screen size at 6px at each dimension")
	if( primary)
		_rectangles.Add(new ScreenRectangle(ScreenNames.PrimaryScreen,
			(float)SystemParameters.PrimaryScreenWidth, (float)SystemParameters.PrimaryScreenHeight,
			"'Emulated' screen dimensions for Wpf applications"));
		_rectangles.Add(new ScreenRectangle(ScreenNames.FullPrimaryScreen,
			(float) SystemParameters.FullPrimaryScreenWidth, (float) SystemParameters.FullPrimaryScreenHeight,
			"Height difference with working area height depends on locale"));
		_rectangles.Add(new ScreenRectangle(ScreenNames.VirtualScreen,
			(float) SystemParameters.VirtualScreenLeft, (float) SystemParameters.VirtualScreenTop,
			(float) SystemParameters.VirtualScreenWidth, (float) SystemParameters.VirtualScreenHeight));
		_rectangles.Add(new ScreenRectangle(ScreenNames.WorkingArea,
			SystemParameters.WorkArea.Width, SystemParameters.WorkArea.Height,
			"40px is holded for the taskbar height"));
		_rectangles.Add(new ScreenRectangle(ScreenNames.PrimaryWorkingArea,
			Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top,
			Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height));

	foreach (var screeen in Screen.AllScreens)
		if (!primary && !Equals(screeen.DeviceName, displayName))
		_rectangles.Add(new ScreenRectangle($"Screen \"{screeen.DeviceName}\"", screeen.WorkingArea,
			"Physical dimensions"));

Update 2

Recently we faced up with the issue when fixed size dialog in wpf application at Windows 7/10 English works well, but when user uses Windows 7 Chinese some controls are cut or not shown. There exists the solution for WinForm applications, but it is not suitable for Wpf applications, as they use another scaling approach. The issue was fixed by two steps:

  • Fixed size was replaced by desired size that is calculated by UserControl.Measuze() method;
  • It was noticed that Full primary screen size is less than Work area size, but difference depends on locale. Let localeDelta = SystemParameters.WorkArea.Height - SystemParameters.FullPrimaryScreenHeight. Then:
    • for Windows 7/10 English locale localeDelta == 13.14, and it depends a little from screen dimensions,
    • for Windows 7 Chinese locale localeDelta == 22.
    Unfortunately I didn't find any info about origin of this value, but it was enough to increase height of dialog window by localeDelta.


  • 2017.01.14 - write initial post;
  • 2017.05.23 - add working area size to window;
  • 2017.07.02 - add comments to shown sizes, update Git repository.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Illya Reznykov
Software Developer (Senior)
Ukraine Ukraine
• As Software Architect I have 10+ years experience in the full cycle of ERP system developing, 5+ years experience in the integration between processing and technological data systems. This experience bases on strong knowledge of all stages of data processing systems creating: planning the n-tier architecture, coding thin or/and thick clients, developing and implementing database tier, and deploying in the production environment. May lead a developer team of 3-5 persons.
• As Mathematician I interested much in the theory of automata, computer algebra and huge calculations. May carry on scientific research personally or in a team.

You may also be interested in...


Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190214.1 | Last Updated 2 Jul 2017
Article Copyright 2017 by Illya Reznykov
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid