-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMainWindow.Fullscreen.cs
151 lines (127 loc) · 5.26 KB
/
MainWindow.Fullscreen.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace WpfWindowTest
{
/*
* This part of the code makes sure that the window expands correctly if it goes into fully maximized (Fullscreen) mode.
* Without these modifications, the position of the upper left corner is negative (something like [-2;-2]) and the window is stretched below the taskbar (bottom bar of windows).
*/
public partial class MainWindow
{
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
((HwndSource)PresentationSource.FromVisual(this)).AddHook(HookProc);
}
/// <summary>
/// This needs to be called in OnStateChanged - for fullscreen size to correctly work.
/// </summary>
private void RefreshMaxHeight()
{
if (WindowState == WindowState.Maximized)
{
// se the MaxHeight to the size of WorkingArea, where the window is
var windowHandle = new WindowInteropHelper(this).Handle;
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
// FullScreen is then limited by this and will not go behind the taskbar
using (var g = Graphics.FromHwnd(windowHandle))
{
this.MaxHeight = screen.WorkingArea.Height / (g.DpiY / 96.0f);
this.MaxWidth = screen.WorkingArea.Width / (g.DpiX / 96.0f);
}
}
else
{
// reset MaxHeight
this.MaxHeight = double.PositiveInfinity;
this.MaxWidth = double.PositiveInfinity;
}
}
private IntPtr HookProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_GETMINMAXINFO)
{
// We need to tell the system what our size should be when maximized. Otherwise it will cover the whole screen,
// including the task bar.
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
// Adjust the maximized size and position to fit the work area of the correct monitor
IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor != IntPtr.Zero)
{
MONITORINFO monitorInfo = new MONITORINFO();
monitorInfo.cbSize = Marshal.SizeOf(typeof(MONITORINFO));
GetMonitorInfo(monitor, ref monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
RECT rcMonitorArea = monitorInfo.rcMonitor;
// this can be outside the working area
var originalX = mmi.ptMaxPosition.X;// eg. -6
var originalY = mmi.ptMaxPosition.Y;// eg. -6
// do the position correction
mmi.ptMaxPosition.X = Math.Abs(rcWorkArea.Left - rcMonitorArea.Left);
mmi.ptMaxPosition.Y = Math.Abs(rcWorkArea.Top - rcMonitorArea.Top);
var difX = originalX - mmi.ptMaxPosition.X;
var difY = originalY - mmi.ptMaxPosition.Y;
// Do the size correction based on original Position
mmi.ptMaxSize.X += 2 * difX;
mmi.ptMaxSize.Y += 2 * difY;
}
Marshal.StructureToPtr(mmi, lParam, true);
}
return IntPtr.Zero;
}
private const int WM_GETMINMAXINFO = 0x0024;
private const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
[DllImport("user32.dll")]
private static extern IntPtr MonitorFromWindow(IntPtr handle, uint flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool GetMonitorInfo(IntPtr hmonitor, ref MONITORINFO info);
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack=4)]
public struct MONITORINFO
{
public int cbSize;
public RECT rcMonitor;
public RECT rcWork;
public int dwFlags;
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
}
}
}