Skip to content

Instantly share code, notes, and snippets.

@talyian
Created September 30, 2017 00:30
Show Gist options
  • Save talyian/6dccaf523c9a9cda9a32ab73d76e98e7 to your computer and use it in GitHub Desktop.
Save talyian/6dccaf523c9a9cda9a32ab73d76e98e7 to your computer and use it in GitHub Desktop.
WinGDI Get All supported Monitor Resolutions
#nowarn "9"
open System
open System.Runtime.InteropServices
[<StructLayout(LayoutKind.Sequential)>]
type DEVMODEInfo = struct
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)>]
[<DefaultValue>] val mutable dmDeviceName : string
[<DefaultValue>] val mutable dmSpecVersion: int16;
[<DefaultValue>] val mutable dmDriverVersion: int16;
[<DefaultValue>] val mutable dmSize: int16;
[<DefaultValue>] val mutable dmDriverExtra: int16;
[<DefaultValue>] val mutable dmFields: int;
// [<DefaultValue>] val mutable dmOrientation: int16;
// [<DefaultValue>] val mutable dmPaperSize: int16;
// [<DefaultValue>] val mutable dmPaperLength: int16;
// [<DefaultValue>] val mutable dmPaperWidth: int16;
// [<DefaultValue>] val mutable dmScale: int16;
// [<DefaultValue>] val mutable dmCopies: int16;
// [<DefaultValue>] val mutable dmDefaultSource: int16;
// [<DefaultValue>] val mutable dmPrintQuality: int16;
[<DefaultValue>] val mutable dmPositionX: int;
[<DefaultValue>] val mutable dmPositionY: int;
[<DefaultValue>] val mutable dmDisplayOrientation: int;
[<DefaultValue>] val mutable dmDisplayFixedOutput: int;
[<DefaultValue>] val mutable dmColor: int16;
[<DefaultValue>] val mutable dmDuplex: int16;
[<DefaultValue>] val mutable dmYResolution: int16;
[<DefaultValue>] val mutable dmTTOption: int16;
[<DefaultValue>] val mutable dmCollate: int16;
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)>]
[<DefaultValue>] val mutable dmFormName : string;
[<DefaultValue>] val mutable dmLogPixels: int16;
[<DefaultValue>] val mutable dmBitsPerPel: int16;
[<DefaultValue>] val mutable dmPelsWidth: int;
[<DefaultValue>] val mutable dmPelsHeight: int;
[<DefaultValue>] val mutable dmDisplayFlags: int;
[<DefaultValue>] val mutable dmDisplayFrequency: int;
[<DefaultValue>] val mutable dmICMMethod: int;
[<DefaultValue>] val mutable dmICMIntent: int;
[<DefaultValue>] val mutable dmMediaType: int;
[<DefaultValue>] val mutable dmDitherType: int;
[<DefaultValue>] val mutable dmReserved1: int;
[<DefaultValue>] val mutable dmReserved2: int;
[<DefaultValue>] val mutable dmPanningWidth: int;
[<DefaultValue>] val mutable dmPanningHeight: int;
new (device: string, form: string) = { }
end
[<StructLayout(LayoutKind.Sequential)>]
type DisplayDeviceInfo = struct
static member size = Marshal.SizeOf<DisplayDeviceInfo>()
[<DefaultValue>] val mutable cb: int;
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)>]
[<DefaultValue>] val mutable deviceName : string
[<MarshalAs(UnmanagedType.ByValArray, SizeConst=128)>]
[<DefaultValue>] val mutable deviceString : char[]
[<DefaultValue>] val mutable stateFlags: int;
[<MarshalAs(UnmanagedType.ByValArray, SizeConst=128)>]
[<DefaultValue>] val mutable deviceID : char[]
[<MarshalAs(UnmanagedType.ByValArray, SizeConst=128)>]
[<DefaultValue>] val mutable deviceKey : char[]
end
[<DllImport("User32.dll")>]
extern bool EnumDisplaySettings(string displayName, int mode, DEVMODEInfo& output);
[<DllImport("User32.dll")>]
extern bool EnumDisplayDevices(string device, int devNum, DisplayDeviceInfo& displayDevice, int flags);
let getdevice name i =
let mutable device = DisplayDeviceInfo(cb=DisplayDeviceInfo.size)
match EnumDisplayDevices(name, i, &device, 1) with | false -> None | _ -> Some(device)
[<Flags>]
type MonitorFlags =
| Active = 1
| MultiDriver = 2
| Primary = 4
| MirroringDriver = 8
| VGACompatible = 16
| Removable = 32
| ModesPruned = 0x8000000
| Remote = 0x4000000
| Disconnect = 0x2000000
type DisplayOrientation =
| Default = 0
| Rotate90 = 1
| Rotate180 = 2
| Rotate270 = 3
type DisplayFixedOutput =
| Default = 0
| Stretch = 1
| Center = 2
type DisplayMode(dm : DEVMODEInfo) =
member val Name = dm.dmDeviceName
member val Height = dm.dmPelsHeight
member val Width = dm.dmPelsWidth
member val BitsPerPel = dm.dmBitsPerPel
member val FPS = dm.dmDisplayFrequency
member val Orientation : DisplayOrientation = enum dm.dmDisplayOrientation
member val FixedOutput : DisplayFixedOutput = enum dm.dmDisplayFixedOutput
override this.ToString() =
String.concat ", " [for p in typeof<DisplayMode>.GetProperties() -> sprintf "%s: %O" p.Name (p.GetValue(this, null))]
let getDisplayInfo display index =
let mutable dm =
DEVMODEInfo(
dmDeviceName = String.replicate 30 " ",
dmFormName = String.replicate 30 " ",
dmSize = int16 sizeof<DEVMODEInfo>)
match EnumDisplaySettings(display, index, &dm) with | false -> None | _ -> Some(DisplayMode(dm))
type Monitor(name, flags) =
member val Name : string = name
member val Flags : MonitorFlags = enum flags
type DisplayDevice(name, flags) =
member val Name : string = name
member val Flags : MonitorFlags = enum flags
member this.Monitors
with get () = List.unfold (fun i -> getdevice name i |> Option.map (fun dw -> (Monitor(dw.deviceName, dw.stateFlags), i + 1))) 0
member this.Modes
with get() = List.unfold (fun i -> getDisplayInfo name i |> Option.map (fun dw -> (dw, i + 1))) 0
static member All
with get() = List.unfold (fun i -> getdevice null i |> Option.map (fun dw -> (DisplayDevice(dw), i + 1))) 0
new(info : DisplayDeviceInfo) = DisplayDevice(info.deviceName, info.stateFlags)
for dv in DisplayDevice.All do
printfn "%O %A" dv.Name dv.Flags
for m in dv.Monitors do
printfn " %A %A" m.Name m.Flags
for m in dv.Modes do
printfn "%O" m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment