mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Upgrade MonitorInfo class
This commit is contained in:
parent
55589f872a
commit
e63941275e
3 changed files with 81 additions and 18 deletions
|
|
@ -1,5 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using Windows.Win32;
|
||||
|
|
@ -11,9 +11,12 @@ namespace Flow.Launcher.Infrastructure;
|
|||
|
||||
/// <summary>
|
||||
/// Contains full information about a display monitor.
|
||||
/// Codes are edited from: <see href="https://github.com/Jack251970/DesktopWidgets3">.
|
||||
/// Inspired from: https://github.com/Jack251970/DesktopWidgets3.
|
||||
/// </summary>
|
||||
internal class MonitorInfo
|
||||
/// <remarks>
|
||||
/// Use this class to replace the System.Windows.Forms.Screen class which can cause possible System.PlatformNotSupportedException.
|
||||
/// </remarks>
|
||||
public class MonitorInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the display monitors (including invisible pseudo-monitors associated with the mirroring drivers).
|
||||
|
|
@ -23,14 +26,14 @@ internal class MonitorInfo
|
|||
{
|
||||
var monitorCount = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CMONITORS);
|
||||
var list = new List<MonitorInfo>(monitorCount);
|
||||
var callback = new MONITORENUMPROC((HMONITOR monitor, HDC deviceContext, RECT* rect, LPARAM data) =>
|
||||
var callback = new MONITORENUMPROC((monitor, deviceContext, rect, data) =>
|
||||
{
|
||||
list.Add(new MonitorInfo(monitor, rect));
|
||||
return true;
|
||||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, (RECT?)null, callback, dwData);
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
|
|
@ -43,11 +46,11 @@ internal class MonitorInfo
|
|||
/// </summary>
|
||||
/// <param name="hwnd">Window handle</param>
|
||||
/// <returns>The display monitor that is nearest to a given window, or null if no monitor is found.</returns>
|
||||
public static unsafe MonitorInfo GetNearestDisplayMonitor(HWND hwnd)
|
||||
public static unsafe MonitorInfo GetNearestDisplayMonitor(nint hwnd)
|
||||
{
|
||||
var nearestMonitor = PInvoke.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
var nearestMonitor = PInvoke.MonitorFromWindow(new(hwnd), MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
MonitorInfo nearestMonitorInfo = null;
|
||||
var callback = new MONITORENUMPROC((HMONITOR monitor, HDC deviceContext, RECT* rect, LPARAM data) =>
|
||||
var callback = new MONITORENUMPROC((monitor, deviceContext, rect, data) =>
|
||||
{
|
||||
if (monitor == nearestMonitor)
|
||||
{
|
||||
|
|
@ -58,7 +61,7 @@ internal class MonitorInfo
|
|||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, (RECT?)null, callback, dwData);
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
|
|
@ -66,17 +69,75 @@ internal class MonitorInfo
|
|||
return nearestMonitorInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary display monitor (the one that contains the taskbar).
|
||||
/// </summary>
|
||||
/// <returns>The primary display monitor, or null if no monitor is found.</returns>
|
||||
public static unsafe MonitorInfo GetPrimaryDisplayMonitor()
|
||||
{
|
||||
var primaryMonitor = PInvoke.MonitorFromWindow(new HWND(IntPtr.Zero), MONITOR_FROM_FLAGS.MONITOR_DEFAULTTOPRIMARY);
|
||||
MonitorInfo primaryMonitorInfo = null;
|
||||
var callback = new MONITORENUMPROC((monitor, deviceContext, rect, data) =>
|
||||
{
|
||||
if (monitor == primaryMonitor)
|
||||
{
|
||||
primaryMonitorInfo = new MonitorInfo(monitor, rect);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
}
|
||||
return primaryMonitorInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display monitor that contains the cursor.
|
||||
/// </summary>
|
||||
/// <returns>The display monitor that contains the cursor, or null if no monitor is found.</returns>
|
||||
public static unsafe MonitorInfo GetCursorDisplayMonitor()
|
||||
{
|
||||
if (!PInvoke.GetCursorPos(out var pt))
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
}
|
||||
var cursorMonitor = PInvoke.MonitorFromPoint(pt, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
MonitorInfo cursorMonitorInfo = null;
|
||||
var callback = new MONITORENUMPROC((monitor, deviceContext, rect, data) =>
|
||||
{
|
||||
if (monitor == cursorMonitor)
|
||||
{
|
||||
cursorMonitorInfo = new MonitorInfo(monitor, rect);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
}
|
||||
return cursorMonitorInfo;
|
||||
}
|
||||
|
||||
private readonly HMONITOR _monitor;
|
||||
|
||||
internal unsafe MonitorInfo(HMONITOR monitor, RECT* rect)
|
||||
{
|
||||
RectMonitor =
|
||||
Bounds =
|
||||
new Rect(new Point(rect->left, rect->top),
|
||||
new Point(rect->right, rect->bottom));
|
||||
_monitor = monitor;
|
||||
var info = new MONITORINFOEXW() { monitorInfo = new MONITORINFO() { cbSize = (uint)sizeof(MONITORINFOEXW) } };
|
||||
GetMonitorInfo(monitor, ref info);
|
||||
RectWork =
|
||||
WorkingArea =
|
||||
new Rect(new Point(info.monitorInfo.rcWork.left, info.monitorInfo.rcWork.top),
|
||||
new Point(info.monitorInfo.rcWork.right, info.monitorInfo.rcWork.bottom));
|
||||
Name = new string(info.szDevice.AsSpan()).Replace("\0", "").Trim();
|
||||
|
|
@ -93,7 +154,7 @@ internal class MonitorInfo
|
|||
/// <remarks>
|
||||
/// <note>If the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.</note>
|
||||
/// </remarks>
|
||||
public Rect RectMonitor { get; }
|
||||
public Rect Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the work area rectangle of the display monitor, expressed in virtual-screen coordinates.
|
||||
|
|
@ -101,7 +162,7 @@ internal class MonitorInfo
|
|||
/// <remarks>
|
||||
/// <note>If the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.</note>
|
||||
/// </remarks>
|
||||
public Rect RectWork { get; }
|
||||
public Rect WorkingArea { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the monitor is the the primary display monitor.
|
||||
|
|
@ -109,7 +170,7 @@ internal class MonitorInfo
|
|||
public bool IsPrimary => _monitor == PInvoke.MonitorFromWindow(new(IntPtr.Zero), MONITOR_FROM_FLAGS.MONITOR_DEFAULTTOPRIMARY);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => $"{Name} {RectMonitor.Width}x{RectMonitor.Height}";
|
||||
public override string ToString() => $"{Name} {Bounds.Width}x{Bounds.Height}";
|
||||
|
||||
private static unsafe bool GetMonitorInfo(HMONITOR hMonitor, ref MONITORINFOEXW lpmi)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ EnumDisplayMonitors
|
|||
MonitorFromWindow
|
||||
GetMonitorInfo
|
||||
MONITORINFOEXW
|
||||
GetCursorPos
|
||||
MonitorFromPoint
|
||||
|
||||
WM_ENTERSIZEMOVE
|
||||
WM_EXITSIZEMOVE
|
||||
|
|
@ -89,4 +91,4 @@ WM_GETTEXT
|
|||
OpenProcess
|
||||
QueryFullProcessImageName
|
||||
EVENT_OBJECT_HIDE
|
||||
EVENT_SYSTEM_DIALOGEND
|
||||
EVENT_SYSTEM_DIALOGEND
|
||||
|
|
@ -293,8 +293,8 @@ namespace Flow.Launcher.Infrastructure
|
|||
}
|
||||
|
||||
var monitorInfo = MonitorInfo.GetNearestDisplayMonitor(hWnd);
|
||||
return (appBounds.bottom - appBounds.top) == monitorInfo.RectMonitor.Height &&
|
||||
(appBounds.right - appBounds.left) == monitorInfo.RectMonitor.Width;
|
||||
return (appBounds.bottom - appBounds.top) == monitorInfo.Bounds.Height &&
|
||||
(appBounds.right - appBounds.left) == monitorInfo.Bounds.Width;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
Loading…
Reference in a new issue