Finding physical screen size from HMONITOR using EDID
It turns out that getting the physical size of a monitor (centimeter or inches instead of pixels) isn’t that simple. There are several ways to get the size but not all of them are reliable. Finding out which size belongs to which monitor is also not so easy. In this blog post I will provide a way to find the physical size of a monitor in millimeters and a way to match this to a given HMONITOR.
Although I will provide a full solution with comments, I will not discuss the different ways that exists to get the screen sizes. For this you can read this blog post, which together with its update, provided me with most of the information required to fulfil my task. To match the HMONITOR and HDEVINFO, I however took a different approach. Instead of a partial match between two strings, I found a device id that is identical in both parts of the code, except for the case (one string is a lowercase version).
Disclaimer: although this code has been tested on multiple computers with multiple types of monitors, I do not guarantee that the code will work for all cases.
In order to find the screen sizes, we will use the SetupAPI to extract the EDID block from the registry. Every digital monitor is supposed to provide this EDID and I haven’t personally encountered a monitor where the size can’t be found using this method. It may however be a good idea to provide an alternative in case there is no EDID, the EDID can’t be accessed or if matching the id with HMONITOR ends up not working.
The following helper function will extract the width and height in millimeter for all monitors. It returns the size for each device id.
Getting the same device id from the HMONITOR also requires quite some work. The first step is to call GetMonitorInfo and get the szDevice member from MONITORINFOEX, but this only gets us halfway. The device name returned by GetMonitorInfo isn’t the same as the device id that we got with the SetupAPI, so we will define another helper function that finds a mapping between these device names and ids.
Now it is time to put the pieces together. We get the device name from the HMONITOR, we look it up in the map returned by getDeviceNamesToIdMap to get the device id, we look that up in the map from ‘findMonitorSizesFromEDID’ and then we are done. The only remaining caveat is that the device id that comes from SetupDiGetDeviceInterfaceDetail seems to be a lowercase version of the id that we got via DisplayConfigGetDeviceInfo, so we must compare the strings as case-insensitive.
I left out the implementation of caseInsensitiveComparison in this blog post, but the full code can be found in this gist.