using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using WindowsDisplayAPI.DisplayConfig;
using WindowsDisplayAPI.Exceptions;
using WindowsDisplayAPI.Native;
using WindowsDisplayAPI.Native.DeviceContext;
using WindowsDisplayAPI.Native.DeviceContext.Structures;
using WindowsDisplayAPI.Native.Structures;
namespace WindowsDisplayAPI
{
///
/// Contains information about a display source screen
///
public class DisplayScreen
{
private readonly IntPtr _monitorHandle;
private DisplayScreen(IntPtr monitorHandle)
{
_monitorHandle = monitorHandle;
}
///
/// Gets the source identification number
///
public int SourceId
{
get
{
var name = ScreenName;
if (string.IsNullOrWhiteSpace(name))
{
return 0;
}
var index = ScreenName.IndexOf("DISPLAY", StringComparison.Ordinal);
return index < 0 ? 0 : int.Parse(name.Substring(index + 7));
}
}
///
/// Gets a list of all active screens
///
/// An array of instances.
public static DisplayScreen[] GetScreens()
{
var result = new List();
var callback = new DeviceContextApi.MonitorEnumProcedure(
(IntPtr handle, IntPtr dcHandle, ref RectangleL rect, IntPtr callbackObject) =>
{
result.Add(new DisplayScreen(handle));
return 1;
}
);
return DeviceContextApi.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, callback, IntPtr.Zero)
? result.ToArray()
: null;
}
///
/// Gets a instance representing the screen current settings
///
public DisplaySetting CurrentSetting
{
get => DisplaySetting.GetCurrentFromScreenName(ScreenName);
}
///
/// Gets a instance representing this screen saved settings
///
public DisplaySetting SavedSetting
{
get => DisplaySetting.GetSavedFromScreenName(ScreenName);
}
///
/// Disables and detaches all devices connected to this screen
///
/// Indicating if the changes should be applied immediately, recommended value is false
public void Disable(bool apply)
{
SetSettings(new DisplaySetting(), apply);
}
///
/// Enables and attach all devices connected to this screen
///
/// The display settings that should be applied while enabling the display device
/// Indicating if the changes should be applied immediately, recommended value is false
public void Enable(DisplaySetting displaySetting, bool apply = false)
{
SetSettings(displaySetting, apply);
}
///
/// Changes the display device settings to a new instance
///
/// The display settings that should be applied
/// Indicating if the changes should be applied immediately, recommended value is false
public void SetSettings(DisplaySetting displaySetting, bool apply = false)
{
if (!IsValid)
{
throw new InvalidDisplayException(null);
}
displaySetting.Save(ScreenName, apply);
}
///
/// Get information about the monitor covering the most of a rectangle.
///
/// The rectangle to get the main monitor information for.
/// An instance of .
public static DisplayScreen FromRectangle(Rectangle rectangle)
{
var monitorHandle = DeviceContextApi.MonitorFromRect(
new RectangleL(rectangle),
MonitorFromFlag.DefaultToNearest
);
return monitorHandle == IntPtr.Zero ? null : new DisplayScreen(monitorHandle);
}
///
/// Get information about the monitor containing or the nearest to a point.
///
/// The point to get the main monitor information for.
/// An instance of .
public static DisplayScreen FromPoint(Point point)
{
var monitorHandle = DeviceContextApi.MonitorFromPoint(
new PointL(point),
MonitorFromFlag.DefaultToNearest
);
return monitorHandle == IntPtr.Zero ? null : new DisplayScreen(monitorHandle);
}
///
/// Get information about the screen covering the most of a window.
///
/// The window handle to get the main screen information for.
/// An instance of .
public static DisplayScreen FromWindow(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
{
throw new ArgumentException("Invalid window handle provided.", nameof(hWnd));
}
var monitorHandle = DeviceContextApi.MonitorFromWindow(
hWnd,
MonitorFromFlag.DefaultToNearest
);
return monitorHandle == IntPtr.Zero ? null : new DisplayScreen(monitorHandle);
}
#if !NETSTANDARD
///
/// Returns the corresponding instance
///
/// A instance of Screen object
public System.Windows.Forms.Screen GetWinFormScreen()
{
if (!IsValid)
throw new Exceptions.InvalidDisplayException();
try
{
return System.Windows.Forms.Screen.AllScreens.FirstOrDefault(screen => screen.DeviceName.Equals(ScreenName));
}
catch
{
// ignored
}
return null;
}
#endif
///
/// Get the corresponding instances.
///
/// An array of instances.
public Display[] GetDisplays()
{
return Display.GetDisplays().Where(display => display.ScreenName.Equals(ScreenName)).ToArray();
}
///
/// Gets the bounds of the monitor
///
public Rectangle Bounds
{
get => GetMonitorInfo()?.Bounds.ToRectangle() ?? Rectangle.Empty;
}
///
/// Gets the source name of the screen
///
public string ScreenName
{
get => GetMonitorInfo()?.DisplayName;
}
///
/// Gets a boolean value indicating if this is the primary display
///
public bool IsPrimary
{
get => GetMonitorInfo()?.Flags.HasFlag(MonitorInfoFlags.Primary) ?? false;
}
///
/// Gets a boolean value indicating if this instance contains valid information.
///
public bool IsValid
{
get => GetMonitorInfo() != null;
}
///
/// Gets the working area of the monitor
///
public Rectangle WorkingArea
{
get => GetMonitorInfo()?.WorkingArea.ToRectangle() ?? Rectangle.Empty;
}
///
/// Returns a list of possible display setting for this screen
///
/// An enumerable list of instances
public IEnumerable GetPossibleSettings()
{
if (!IsValid)
{
yield break;
}
var index = -1;
while (true)
{
index++;
var deviceMode = new DeviceMode(DeviceModeFields.None);
if (!DeviceContextApi.EnumDisplaySettings(ScreenName, (DisplaySettingsMode)index, ref deviceMode))
{
break;
}
yield return new DisplayPossibleSetting(deviceMode);
}
}
///
/// Returns the best possible display setting for this screen
///
/// A instance
public DisplayPossibleSetting GetPreferredSetting()
{
return IsValid
? GetPossibleSettings()
.OrderByDescending(setting => (int)setting.ColorDepth)
.ThenByDescending(setting => (ulong)setting.Resolution.Width * (ulong)setting.Resolution.Height)
.ThenByDescending(setting => setting.Frequency)
.FirstOrDefault()
: null;
}
///
/// Returns the corresponding instance
///
/// An instance of , or null
public PathDisplaySource ToPathDisplaySource()
{
return PathDisplaySource
.GetDisplaySources()
.FirstOrDefault(source => source.DisplayName.Equals(ScreenName));
}
private MonitorInfo? GetMonitorInfo()
{
var monitorInfo = MonitorInfo.Initialize();
if (DeviceContextApi.GetMonitorInfo(_monitorHandle, ref monitorInfo))
{
return monitorInfo;
}
return null;
}
}
}