-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWindowManager.cs
120 lines (88 loc) · 4.33 KB
/
WindowManager.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
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BorderlessMinecraft
{
public class WindowManager
{
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private const int GWL_STYLE = -16;
private const int WS_BORDER = 0x00800000;
private const int WS_RESIZE = 0x00040000;
private const int WS_MINIMIZE = 0x00020000;
private const int WS_MAXIMIZE = 0x00010000;
private const int WS_CONTEXTMENU = 0x00800000;
private const int WS_DIALOGUEBOXBORDER = 0x00400000;
private static readonly uint SWP_NOZORDER = 0x0004;
public static readonly Dictionary<int, WindowProperties> windowPropertiesByPID = new Dictionary<int, WindowProperties>();
internal static void ToggleBorderless(IntPtr handle)
{
GetWindowThreadProcessId(handle, out uint processId);
Rect currentPos = GetWindowRect(handle);
if (!(currentPos.Left == 0 && currentPos.Top == 0 && currentPos.Right == Screen.PrimaryScreen.Bounds.Width && currentPos.Bottom == Screen.PrimaryScreen.Bounds.Height))
SetBorderless(handle, (int)processId);
else
UnsetBorderless(handle, (int)processId);
}
internal static void SetBorderless(IntPtr handle, int processId)
{
windowPropertiesByPID[processId] = new WindowProperties
{
OriginalPos = GetWindowRect(handle),
OriginalStyle = GetWindowLong(handle, GWL_STYLE),
};
long currentStyle = GetWindowLong(handle, GWL_STYLE);
currentStyle &= ~(WS_BORDER | WS_RESIZE | WS_MINIMIZE | WS_MAXIMIZE | WS_CONTEXTMENU | WS_DIALOGUEBOXBORDER);
SetWindowLong(handle, GWL_STYLE, (uint)currentStyle);
SetWindowPos(handle, handle, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, SWP_NOZORDER);
SetForegroundWindow(handle);
}
private static void UnsetBorderless(IntPtr handle, int processId)
{
if (windowPropertiesByPID.TryGetValue(processId, out WindowProperties properties))
{
int originalWidth = properties.OriginalPos.Right - properties.OriginalPos.Left;
int originalHeight = properties.OriginalPos.Bottom - properties.OriginalPos.Top;
SetWindowLong(handle, GWL_STYLE, (uint)properties.OriginalStyle);
SetWindowPos(handle, handle, properties.OriginalPos.Left, properties.OriginalPos.Top, originalWidth, originalHeight, SWP_NOZORDER);
SetForegroundWindow(handle);
windowPropertiesByPID.Remove(processId);
}
}
public static Rect GetWindowRect(IntPtr handle)
{
Rect rect;
if (GetWindowRect(handle, out rect))
return rect;
throw new Exception("Failed to get window rect.");
}
public struct Rect
{
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
}
public struct WindowProperties
{
public long OriginalStyle;
public Rect OriginalPos;
}
internal static bool IsFullscreen(IntPtr handle)
{
return GetWindowLong(handle, GWL_STYLE) < 0;
}
}
}