如何在Windows中查询主显示器的本机硬件分辨率?

6
我需要在Windows下找到连接的LCD显示器的“最佳”或本机分辨率(然后我将以编程方式设置并知道如何做)。请注意,我不需要当前的Windows分辨率,也不需要担心CRT /投影仪。
我已经看到这个程序可以工作,所以我知道尽管有否定者,这是可能的: http://www.entechtaiwan.com/util/moninfo.shtm 最好直接与显示器交流并查询EDID信息。但是,我已经看到它被缓存在注册表中,并且不会有问题从HKLM \ SYSTEM \ CurrentControlSet \ Enum \ DISPLAY中挖掘它,但无法弄清楚如何将数据与当前主显示器匹配。
我在这里找到了一个C程序: http://www.tech-archive.net/Archive/Development/microsoft.public.development.device.drivers/2004-08/0294.html 还有一个类似的Python程序: http://www.koders.com/python/fid7FCCE3C908F376DC62F06CAD9B11C6D7C1CFA78F.aspx 不幸的是,我很难将C程序转换为Python,因为相关代码似乎不在win32all模块中。我会尝试编译它,但是我没有足够的磁盘空间来安装大型编译器,而且我已经好几年没用过C语言了。我对ctypes也不是很熟悉。
我的备选方案是使用EnumDisplaySettings()函数查找最大分辨率值,并将其设置为该值。在我尝试过的电脑上,它可以给出正确的分辨率,但仍可能存在问题。

我希望用Python编写一个解决方案,但也许有人可以帮我修改C程序,以便输出分辨率并编译它。提前感谢。

更新:

我找到了一个潜在的解决方案。现在我正在读取WMI以查找可用(不脱机)的监视器,获取其PNP设备ID,并从具有该ID值的子键中的注册表中读取EDID。然后我解析数据以获取第38和39个字节并进行计算。这不是很干净,但我得到了结果。如果这是一个合理的方法,我将关闭此问题,谢谢。


还有一些非常小的编译器,比如Pelles C和DevCpp。 - Prof. Falken
不要关闭问题,你可以在一个新的答案中回答自己。如果你想的话,明天甚至可以接受你自己的答案。这很有趣。 - Prof. Falken
1个回答

2

决定放弃直接与显示器交流,而是解析缓存在注册表中的EDID信息。这段代码不完美,但可以使用:

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

'wmiquery' 库在哪里?我似乎找不到它。 - soren121
抱歉,我试图从我的代码中提取信息时漏掉了一两个部分。那是我创造的一个名称,因为 API 的名称很可怕。现在加上了。 - Gringo Suave
只需使用以下代码: c = wmi.WMI() wql = "SELECT * FROM Win32_DesktopMonitor" for item in c.query(wql): - jaques-sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接