WPF mutli-monitor problem - WindowState - wpf

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.
Why is this?

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:
The two monitors have the same height and are configured to be side by side, or
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:
Declare the MONITORINFO struct as a struct in C#
Declare DllImports for EnumDisplayMonitors and GetMonitorInfo, both found in User32.dll
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.

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;

Related

How to make my WPF application full screen

I have been building a small WPF application that includes a media player. I am almost finished except for one part, Making the player full screen. I have gotten to the point to where I have the Windows Taskbar hidden, and the player is covering everything, except where the taskbar was. So the player is full screen except for where the taskbar would normally be, you just see a part of the desktop background.
private void Full_Click(object sender, RoutedEventArgs e)
{
this.WindowStyle = WindowStyle.None;
this.ResizeMode = ResizeMode.NoResize;
this.WindowState = WindowState.Maximized;
Taskbar.Hide();
player.Stretch = Stretch.Fill;
controlPanel.Visibility = Visibility.Collapsed;//hides media controls
player.Height = System.Windows.SystemParameters.PrimaryScreenHeight + 200;//I tried to set the height to fill the entire screen
Full.Visibility = Visibility.Hidden;//hides full screen control //Im aware that may be too large of an increase but I
CloseFull.Visibility = Visibility.Visible;//shows exit control //wanted to see if it would work at all
}
Why do you want to hide the taskbar ?
This should be enough:
WindowStyle = WindowStyle.None;
ResizeMode = ResizeMode.NoResize;
WindowState = WindowState.Maximized;
Topmost = true;

How to open a WPF window that has a Windows Form parent at mouse position?

I have a windows forms window application. Inside the application we want to open a WPF window that is positioned at a location relative to the mouse position. Let's say, that the window center may be displayed at the mouse coordinates, or another case, that the top left corner of the window may be set as being the mouse coordinates.
I've looked at posts like http://www.formatexception.com/2008/09/wpf-and-mouseposition/
but this does not help me, as I don't have a WPF control open before my window. I only have the windows forms, so the folllowing line is not usable in my case
Point mousePoint = Mouse.GetPosition(this);
since you have a winforms control available, you can use Control.MousePosition
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.mouseposition.aspx
Are you showing the wpf window from a winforms form? I wrote a quick test that had a Form with a button. When clicking the button it opened a wpf window at the cursor location. This worked fine and i did not create or show any WPF controls before the button click.
I tried with and without setting WindowStartupLocation and they both worked, but it might be worth a try for you to add it. Here's an example:
private void button1_Click(object sender, EventArgs e)
{
Window w = new Window();
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Left = Control.MousePosition.X;
w.Top = Control.MousePosition.Y;
w.Show();
}
Though, if the above code sample doesn't work for you then perhaps you could describe your scenario a little bit further and include some code examples?
Building on Bill Tarbell's answer, you may need to account for DPI scaling:
private Point GetScalingFactor(Window window)
{
var zeroPoint = window.PointToScreen(new Point(0, 0));
var hundredPoint = window.PointToScreen(new Point(100, 100));
return new Point(
100.0 / (hundredPoint.X - zeroPoint.X),
100.0 / (hundredPoint.Y - zeroPoint.Y));
}
private void ShowAtCursor(Window parent, Window toShow)
{
var point = parent.PointToScreen(System.Windows.Input.Mouse.GetPosition(parent));
var scaling = GetScalingFactor(parent);
toShow.Left = point.X * scaling.X;
toShow.Top = point.Y * scaling.Y;
toShow.WindowStartupLocation = WindowStartupLocation.Manual;
toShow.Show();
}
Bill Tarbell's answer was not working on my WPF program.
I could not include "using System.Windows.Forms;" somehow...
Could be different project type..
But his answer was very helpful so I put one up vote to him.
and below is the modified code that worked for me.
private void button1_Click(object sender, EventArgs e)
{
Point pointToScreen = PointToScreen(Mouse.GetPosition(this));
Window w = new Window();
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Left = pointToScreen.X;
w.Top = pointToScreen.Y;
w.Show();
}

Dynamically Set Out Of Browser Height and Width

I have a Silverlight 5 Application that we run Out Of Browser. I would like to know if there is some way to set the Out Of Browser Window Height and Width dynamically in code.
Everyone has a different size monitor. I don’t want the people with the larger monitors to be limited to the screen of the smallest size monitor.
I would either base it on the Users Id or if possible detecting the monitor dimensions.
This may help,
private void Application_Startup(object sender, StartupEventArgs e) { MyForm = new MyForm();
this.RootVisual = startupWindow;
this.MainWindow.Width = startupWindow.Width; this.MainWindow.Height = startupWindow.Height; }

Ensuring WPF Window is inside screen bounds

I restore coordinates of Window on application startup. In good-old-Windows-Forms I used System.Windows.Forms.Screen collection. Is there anything similar in WPF world?
I did notice PrimaryScreen*, VirtualScreen* parameters in System.Windows.SystemParameters. However they left me hanging since it seems to be impossible to detect whether Window is inside bounds in cases when monitors are not same size.
System.Windows.Forms.Screen works perfectly well within WPF, so I think the designers of WPF saw no advantage in replacing it with a WPF-specific version.
You'll have to do a coordinate transformation of course. Here's an easy class to do the conversion:
public class ScreenBoundsConverter
{
private Matrix _transform;
public ScreenBoundsConverter(Visual visual)
{
_transform =
PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice;
}
public Rect ConvertBounds(Rectangle bounds)
{
var result = new Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height);
result.Transform(_transform);
return result;
}
}
Example usage:
var converter = new ScreenBoundsConverter(this);
foreach(var screen in System.Windows.Forms.Screen.AllScreens)
{
Rect bounds = converter.ConvertBounds(screen.Bounds);
...
}

How to autosize User control when it's shown

I have a Winforms project with a bunch of User controls. I'd like the user control to move itself to be at the 1,1 position relative to its container (whether it's a form or a Panel control). And resize itself to be able to fit half the container.
What event can I respond to in the UserControl to be able to do this without any code having to be written in the container (e.g. the form or panel).
You could use the basic Load event.
The code could be like this:
private void UserControl1_Load(object sender, EventArgs e)
{
Control parent = this.Parent;
if (parent != null)
{
this.Location = new Point(1, 1);
this.Width = (parent.Width / 2);
this.Height = (parent.Height / 2);
}
}
The Paint event should work, unless I'm missing something.

Resources