views:

1000

answers:

2

Hi,

I've been trying to get my WPF application to span multiple monitors for some time now, and nearly have it working.

The problem seems to arise when I set the following line:

win1.WindowState = WindowState.Maximized

This causes the application to span only the primary screen.

My code is as follows:

public partial class App : Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        Window1 win1 = new Window1();
        win1.WindowStartupLocation = WindowStartupLocation.Manual;
        win1.Width = 2560;
        win1.Height = 1024;
        win1.Left = 0;
        win1.Top = 0;
        win1.Topmost = true;
        win1.Background = new SolidColorBrush(Colors.Black);
        win1.WindowStyle = WindowStyle.None;
        win1.Show();
        win1.Focus();
    }
}

And inside of Window 1:

public partial class Window1 : Window
{
    public Window1()
    {

    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        WindowState = WindowState.Maximized;
    }
}

This example works, but the window is not Maximized and the application borders are still visible.

Including the Maximized deceleration in Application_Startup makes the monitor maximize to the primary monitor.

I'm confused as to why this is. Any ideas?

Cheers, MiG

A: 

If you can always assume that your secondary monitor is at the same resolution as the primary, you could implement something like this:

// Use this is you are concerned about the taskbar height
Rect workArea = SystemParameters.WorkArea;
this.Width = SystemParameters.PrimaryScreenWidth * 2;
this.Height = workArea.Bottom;
this.Left = 0;
this.Top = 0;

Or:

// Use this is you don't care about the taskbar height
this.Width = SystemParameters.PrimaryScreenWidth * 2;
this.Height = SystemParameters.PrimaryScreenHeight;
this.Left = 0;
this.Top = 0;
Brent
+3  A: 

First note that the concept of "Maximized" is tied to a single monitor, so you cannot truly have a maximized window on multiple monitors. Of course in WPF you can create your own window frame and draw anything you like in it, so if you want you can certainly make the user think the window is maximized and spanning multiple screens.

Also note that it is possible to span two monitors with a single rectangular window in only two cases:

  1. The two monitors have the same height and are configured to be side by side, or
  2. The two monitors have the same width and are configured to be above and below.

Otherwise you will need to use two separate windows to cover the entire surfaces of both monitors, or use a large window that includes areas that aren't covered by any monitor.

Ok, here's how to get the information you'll need to position your window(s):

WPF itself does not provide a way to ask about your monitor count, resolutions, or relative positions. Fortunately we can call Win32 directly using [DllImport]. To get monitor resolutions and layouts, just:

  1. Declare the MONITORINFO struct as a struct in C#
  2. Declare DllImports for EnumDisplayMonitors and GetMonitorInfo, both found in User32.dll
  3. Write a method that calls EnumDisplayMonitors and passes a delegate that gets the monitor info and returns it in a list.

Here is the basic idea:

List<MONITORINFO> GetAllMonitorInfo()
{
  var result = List<MONITORINFO>();
  EnumDisplayMonitors(null, null,
    (hMonitor, hdcMonitor, lprcMonitor, dwData) =>
    {
      var info = new MONITORINFO { cbSize = Marshall.Sizeof(typeof(MONITORINFO)) };
      GetMonitorInfo(hMonitor, ref info);
      result.Add(info);
    }, null);
  return result;
}

Once you have the monitor coordinates, use an algorithm of your choice to select how many window(s) you want to create and what coordinates you want for each one. Then create the windows using explicit size(s) and location(s).

Note that you'll probably want to use rcWork as opposed to rcMonitor so you don't overwrite the start menu, etc.

Also note that in many cases some of the coordinates returned will be negative, for example if the secondary monitor is to the left of the primary monitor. This is not a problem: Just use the coordinates as given and your windows will appear in the correct places.

Ray Burns
Ok, i'll use multiple windows to span the multiple monitors as I can't guarantee the monitors the user will have.Also, I think you can use the System.Windows.Forms.Screens namespace to access screen information.Cheers,MiG
MiG
Yes, it is better to use the System.Windows.Forms.Screen class than to call the native methods directly.
Ray Burns