Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Enumerate displays and read EDID on Windows using C, WinAPI, and luck 🍀

License

NotificationsYou must be signed in to change notification settings

w23/wonitors

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Once upon a time I had an impossible to ignore urge to read EDIDs of all connected displays on Windows. In bare C and WinAPI only.

Expectation: There's a function likeGetEdidForMonitor(HMONITOR)

Reality: One does not simply. There are no officially documented ways to do this, no fully working code examples, and no, LLMs couldn't conjure one up either (although they did provide valuable research pointers).

A brief sequence of events

  1. CallEnumDisplayMonitors() (масло масляное) to receive a bunch ofHMONITOR handles for each connected display.
  2. GetMonitorInfo() to getMONITORINFOEX.szDevice will contain display device name like\\.\DISPLAY14.
  3. UseEnumDisplayDevices(szDevice, EDD_GET_DEVICE_INTERFACE_NAME) to getDISPLAY_DEVICE.DeviceID containing device path like\\?\DISPLAY#LKG001A#5&272c5422&0&UID513#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
  4. UseSetupDiGetClassDevs(GUID_DEVINTERFACE_MONITOR, DIGCF_DEVICEINTERFACE) to request a set of all monitor-class devices interfaces.
  5. Enumerate the set usingSetupDiEnumDeviceInterfaces(set, GUID_DEVINTERFACE_MONITOR, index), gettingSP_DEVICE_INTERFACE_DATA
  6. For each interface retrieveSP_INTERFACE_DEVICE_DETAIL_DATA usingSetupDiGetDeviceInterfaceDetail(set, iface_data). It's a three-step process. First, get the detail struct size, then allocate it, then call the function again to fill the detail data. Also, use this function to readSP_DEVINFO_DATA.
  7. Comparedetail.DevicePath with the device pathDISPLAY_DEVICE.DeviceID from step 3. Note that they will have different case, so case-insensitive comparison is needed. If they match, then you've found associated interface for theHMONITOR from step 1.
  8. UseSetupDiOpenDevRegKey(set, devinfo_data) to open registry key. (Yes, the regedit-registry. No, it's not practical to guess the key, it's something likeHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\CMN152A\5&272c5422&0&UID512\Device Parameters and seems unstable)
  9. UseRegQueryValueEx(key, "EDID") to read EDID value data into buffer of 128 bytes. No, it won't read past 128 bytes to get extensions, e.g. for CEC.
  10. If nothing failed, you're done. Time to cleanup all this mess. Maybe the real treasure was all the handles we created and memory we allocated along the way.

Bonus One

The example code also reads monitor positions and current modes, so that there's association between EDID and virtual display geometry.

No, I haven't found an easy read monitor names (e.g. vendor, model). I haven't really looked, though.

Bonus Two

This repo contains some cmake configuration to manifest this app into a DPI-aware world. Without this, the bonus one code would read dpi-unaware (scaled) monitor positions, which might be not what you want.

Appendix

How to read EDID in X11:

  1. XRRGetScreenResources() to get resources.
  2. For eachresources->output[i]: useXRRGetOutputProperty(output, XInternAtom("EDID")), done.

About

Enumerate displays and read EDID on Windows using C, WinAPI, and luck 🍀

Topics

Resources

License

Stars

Watchers

Forks


[8]ページ先頭

©2009-2025 Movatter.jp