Repository navigation
Expand file tree
/
Copy pathNative.cs
More file actions
202 lines (162 loc) · 6.88 KB
/
Copy pathNative.cs
File metadata and controls
202 lines (162 loc) · 6.88 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace TaskbarMarker;
internal static class Native
{
public const int WS_EX_LAYERED = 0x00080000;
public const int WS_EX_TRANSPARENT = 0x00000020;
public const int WS_EX_TOOLWINDOW = 0x00000080;
public const int WS_EX_NOACTIVATE = 0x08000000;
public const int ULW_ALPHA = 0x02;
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
public static readonly IntPtr HWND_TOPMOST = new(-1);
public const uint SWP_NOSIZE = 0x0001;
public const uint SWP_NOMOVE = 0x0002;
public const uint SWP_NOACTIVATE = 0x0010;
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y) { X = x; Y = y; }
}
[StructLayout(LayoutKind.Sequential)]
public struct SIZE
{
public int Cx;
public int Cy;
public SIZE(int cx, int cy) { Cx = cx; Cy = cy; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public readonly Rectangle ToRectangle() =>
Rectangle.FromLTRB(Left, Top, Right, Bottom);
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(
IntPtr hwnd, IntPtr hdcDst, ref POINT pptDst, ref SIZE psize,
IntPtr hdcSrc, ref POINT pptSrc, int crKey, ref BLENDFUNCTION pblend, int dwFlags);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyIcon(IntPtr hIcon);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindow(string? lpClassName, string? lpWindowName);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsZoomed(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
private static readonly string[] ShellWindowClasses =
{
"Shell_TrayWnd", "Shell_SecondaryTrayWnd", "WorkerW", "Progman", "Windows.UI.Core.CoreWindow",
};
/// <summary>
/// Returns the monitor covered by the foreground window when it is genuinely full-screen.
/// Maximized windows are excluded explicitly because their rect overhangs the screen edges by
/// the resize border. Checked directly instead of via SHQueryUserNotificationState, which also
/// reports "busy" for Do Not Disturb / focus sessions.
/// </summary>
public static Rectangle? GetForegroundFullScreenMonitorBounds()
{
IntPtr foreground = GetForegroundWindow();
if (foreground == IntPtr.Zero || IsZoomed(foreground))
return null;
var className = new StringBuilder(64);
if (GetClassName(foreground, className, className.Capacity) > 0 &&
Array.IndexOf(ShellWindowClasses, className.ToString()) >= 0)
{
return null;
}
if (!GetWindowRect(foreground, out RECT raw))
return null;
Rectangle rect = raw.ToRectangle();
if (rect.Width <= 0 || rect.Height <= 0)
return null;
Rectangle monitorBounds = Screen.FromRectangle(rect).Bounds;
return rect.Contains(monitorBounds) ? monitorBounds : null;
}
public static string DescribeForegroundWindow()
{
IntPtr foreground = GetForegroundWindow();
if (foreground == IntPtr.Zero)
return "(none)";
var className = new StringBuilder(128);
GetClassName(foreground, className, className.Capacity);
var title = new StringBuilder(256);
GetWindowText(foreground, title, title.Capacity);
GetWindowRect(foreground, out RECT raw);
return $"hwnd=0x{foreground.ToInt64():X} zoomed={IsZoomed(foreground)} " +
$"class={className} rect={raw.ToRectangle()} title={title}";
}
/// <summary>Returns the primary taskbar plus every secondary-monitor taskbar.</summary>
public static List<IntPtr> FindTaskbars()
{
var taskbars = new List<IntPtr>();
IntPtr primary = FindWindow("Shell_TrayWnd", null);
if (primary != IntPtr.Zero)
taskbars.Add(primary);
var buffer = new StringBuilder(64);
EnumWindows((hWnd, _) =>
{
buffer.Clear();
if (GetClassName(hWnd, buffer, buffer.Capacity) > 0 &&
buffer.ToString() == "Shell_SecondaryTrayWnd")
{
taskbars.Add(hWnd);
}
return true;
}, IntPtr.Zero);
return taskbars;
}
}