I need to find the "best" or native resolution for an attached LCD monitor under Windows (which I'll then set programmatically and know how to do.) Let me repeat that I do not need the Current Windows resolution, nor need to worry about CRTs/projectors.
I've seen it work with this program, so I know it is possible despite the naysayers: http://www.entechtaiwan.com/util/moninfo.shtm
It would be best to talk directly to the monitor and query the EDID info. However, I've seen that it is cached in the registry and wouldn't have a problem digging it out from HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY but can't figure out how to match the data with the current primary monitor.
I did find this C program at: http://www.tech-archive.net/Archive/Development/microsoft.public.development.device.drivers/2004-08/0294.html and a similar python program: http://www.koders.com/python/fid7FCCE3C908F376DC62F06CAD9B11C6D7C1CFA78F.aspx
Unfortunately, I'm having a lot of trouble converting the C program to python, as the relevant code doesn't seem to be in the win32all modules. I'd try to compile it but don't have disk space for a big compiler and haven't used C for years. I'm a bit out of my element with ctypes as well.
My plan B will be to use EnumDisplaySettings() to find the largest value for resolution and set it to that. On the PC's I've tried it gives the correct res, but it could still be problematic.
I'd prefer a solution in python, but perhaps someone could help me modify the C program to spit out the resolution and compile it. Thanks in advance.
Update:
I've found a potential solution. I am now reading WMI to find a monitor that is available (not offline), grabbing its PNP device id, and reading EDID from the registry in the subkey with the id value. Then I parse the data for bytes 38 and 39 and calculate. Not very clean, but am getting results. If this is a reasonable way to do it I'll close this question, thanks.
Decided to give up talking directly to the monitor and instead parsing EDID information cached in the registry. This code isn't perfect, but it works:
import win32api as api, win32con as con, pywintypes
import win32com.client
_objWMIService = win32com.client.Dispatch('WbemScripting.SWbemLocator')
_objSWbemServices = _objWMIService.ConnectServer('.', 'root\\cimv2')
wmiquery = _objSWbemServices.ExecQuery
# get_regval(regkey) is simple registry reading function.
def get_monitor_res():
dtd = 54 # start byte of detailed timing desc.
try: # get PNP id to find EDID in registry
for monitor in wmiquery('Select * from Win32_DesktopMonitor'):
# http://msdn.microsoft.com/en-us/library/aa394122%28VS.85%29.aspx
if monitor.Availability in (3, 7, 13, 14, 15, 16): # connected
curres = (monitor.ScreenWidth, monitor.ScreenHeight)
print 'DEBUG: Current monitor resolution from WMI: %s' % (curres,)
regkey = ('HKLM\\SYSTEM\\CurrentControlSet\\Enum\\' +
monitor.PNPDeviceID + '\\Device Parameters\\EDID')
edid = get_regval(regkey)
if edid:
print 'DEBUG: EDID Version: %s.%s' % (edid[18], edid[19])
# upper nibble of byte x 2^8 combined with full byte
hres = ((edid[dtd+4] >> 4) << 8) | edid[dtd+2]
vres = ((edid[dtd+7] >> 4) << 8) | edid[dtd+5]
print 'DEBUG: EDID DTD0: ' + str((hres, vres))
res = (hres, vres)
break # give up on first success
else:
raise RuntimeError, 'EDID not found in registry'
except (RuntimeError, Exception) as err:
print 'ERROR: %s.' % err
return res
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With