【问题标题】:EnumDisplayDevices giving two Displays even though I have oneEnumDisplayDevices 提供两个显示器,即使我有一个
【发布时间】:2021-04-13 21:18:51
【问题描述】:

我正在使用 Python 为 Night Light 制作应用程序。我正在使用 Windows API 来使用 Gamma Ramp 来完成我的任务。 我使用 user32.dll 中的 EnumDisplayDevicesW 来获取连接到我的 PC 的显示器的信息和数量。

我只有一台显示器连接到我的桌面,但输出提供了两台显示器的信息。

这是我的代码。我正在使用 Python 并通过 ctypes 模块访问 WinAPI。

import ctypes
from ctypes import wintypes


class DISPLAY_DEVICEW(ctypes.Structure):
    _fields_ = [
        ('cb', wintypes.DWORD),
        ('DeviceName', wintypes.WCHAR * 32),
        ('DeviceString', wintypes.WCHAR * 128),
        ('StateFlags', wintypes.DWORD),
        ('DeviceID', wintypes.WCHAR * 128),
        ('DeviceKey', wintypes.WCHAR * 128)
    ]

if __name__ == '__main__':
    EnumDisplayDevices = ctypes.windll.user32.EnumDisplayDevicesW       # get the function address
    EnumDisplayDevices.restype = ctypes.c_bool                          # set return type to BOOL

    displays = []           # to store display information
    i = 0                   # iteration variable for 'iDevNum'

    while True:
        INFO = DISPLAY_DEVICEW()            # struct object
        INFO.cb = ctypes.sizeof(INFO)       # setting 'cnSize' prior to calling 'EnumDisplayDevicesW'

        if not EnumDisplayDevices(None, i, ctypes.byref(INFO), 0):
            break       # break as soon as False is returned by 'EnumDisplayDevices'

        displays.append(INFO)       # append information to the list
        i += 1

    # display information in a sequential form
    for x in displays:
        print('DeviceName:\t\t', x.DeviceName)
        print("DeviceString:\t", x.DeviceString)
        print("StateFlags:\t\t", x.StateFlags)
        print("DeviceID:\t\t", x.DeviceID)
        print("DeviceKey:\t\t", x.DeviceKey)
        print(), print()

而代码返回的输出如下:-

DeviceName:      \\.\DISPLAY1
DeviceString:    Intel(R) HD Graphics 510
StateFlags:      5
DeviceID:        PCI\VEN_8086&DEV_1902&SUBSYS_D0001458&REV_06
DeviceKey:       \Registry\Machine\System\CurrentControlSet\Control\Video\{C31A4E45-2A30-11EB-953B-92862920CE33}\0000


DeviceName:      \\.\DISPLAY2
DeviceString:    Intel(R) HD Graphics 510
StateFlags:      0
DeviceID:        PCI\VEN_8086&DEV_1902&SUBSYS_D0001458&REV_06
DeviceKey:       \Registry\Machine\System\CurrentControlSet\Control\Video\{C31A4E45-2A30-11EB-953B-92862920CE33}\0001

据我所知,第一个,即\\.\DISPLAY1 是我的,但是为什么需要第二个呢??

我拥有一台配备标准三星显示器的台式电脑。

任何帮助都会非常有帮助。提前致谢!

【问题讨论】:

    标签: python windows api winapi ctypes


    【解决方案1】:

    因此,在进行必要的更改后,以下是让所有显示监视器连接到所有显示适配器的最终代码。

    import ctypes
    from ctypes import wintypes
    
    
    class DISPLAY_DEVICEW(ctypes.Structure):
        _fields_ = [
            ('cb', wintypes.DWORD),
            ('DeviceName', wintypes.WCHAR * 32),
            ('DeviceString', wintypes.WCHAR * 128),
            ('StateFlags', wintypes.DWORD),
            ('DeviceID', wintypes.WCHAR * 128),
            ('DeviceKey', wintypes.WCHAR * 128)
        ]
    
    if __name__ == '__main__':
        EnumDisplayDevices = ctypes.windll.user32.EnumDisplayDevicesW       # get the function address
        EnumDisplayDevices.restype = ctypes.c_bool                          # set return type to BOOL
    
        """    
        the following list 'displays', stores display adapter info in the following Structure:
        
            'List containing Tuple of displayAdapterInfo and list of monitorInfo controlled by the adapter'
            [
                (dispAdapterInfo1, [Monitor1, Monitor2, . . . ]), 
                (dispAdapterInfo2, [Monitor1, Monitor2, . . . ]), 
                . . . .
            ]
            
            Number of dispAdapter depends on the graphics driver, and number of Monitors per adapter depends on 
            number of monitors connected and controlled by adapter.
        """
        displays = []
    
        i = 0                   # iteration variable for 'iDevNum'
        while True:
            DISP_INFO = DISPLAY_DEVICEW()               # struct object for adapter info
            DISP_INFO.cb = ctypes.sizeof(DISP_INFO)     # setting 'cb' prior to calling 'EnumDisplayDevicesW'
    
            if not EnumDisplayDevices(None, i, ctypes.byref(DISP_INFO), 0):
                break       # break as soon as False is returned by 'EnumDisplayDevices'
    
            monitors = []       # stores list of monitors per adapter
            j = 0
            while True:
                MONITR_INFO = DISPLAY_DEVICEW()              # struct object for Monitor info
                MONITR_INFO.cb = ctypes.sizeof(MONITR_INFO)  # setting 'cb' prior to calling 'EnumDisplayDevicesW'
    
                if not EnumDisplayDevices(DISP_INFO.DeviceName, j, ctypes.byref(MONITR_INFO), 0):
                    break  # break as soon as False is returned by 'EnumDisplayDevices'
    
                monitors.append(MONITR_INFO)
                j += 1
    
            displays.append((DISP_INFO, monitors))      # add the tuple (dispAdapterInfo, [MonitorsInfo])
            i += 1
    
    
        for display in displays:
            if display[1]:      # filter out the adapter with no monitor connected, i.e, empty list
                print("Adapter object:", display[0])
                print("List of Monitor objects :", display[1])
                print()
    

    现在,display[0]是适配器对象,可以参考上面的DISPLAY_DEVICEW类来获取信息,display[1]是监视器列表,可以迭代得到监听信息的对象,并通过引用DISPLAY_DEVICEW类获取相关信息。

    【讨论】:

      【解决方案2】:

      我只有一台显示器连接到我的桌面,但输出提供了两台显示器的信息。

      运行此代码不会告诉您有两个“监视器”,而是两个“适配器”。

      根据EnumDisplayDevicesW

      要获取有关显示适配器的信息,请调用 EnumDisplayDevices 并将 lpDevice 设置为 NULL。例如,DISPLAY_DEVICE.DeviceString 包含适配器名称。

      要获取有关显示监视器的信息,首先调用 EnumDisplayDevices 并将 lpDevice 设置为 NULL。然后调用 EnumDisplayDevices 并将 lpDevice 设置为 DISPLAY_DEVICE.DeviceName 从第一次调用 EnumDisplayDevices 并将 iDevNum 设置为零。那么 DISPLAY_DEVICE.DeviceString 就是监视器名称。

      所以如果需要获取监控信息,需要调用:

      EnumDisplayDevices(INFO.DeviceName,j,ctypes.byref(Monitor_INFO),0):
      

      这是一个示例:

      import ctypes
      from ctypes import wintypes
      
      
      class DISPLAY_DEVICEW(ctypes.Structure):
          _fields_ = [
              ('cb', wintypes.DWORD),
              ('DeviceName', wintypes.WCHAR * 32),
              ('DeviceString', wintypes.WCHAR * 128),
              ('StateFlags', wintypes.DWORD),
              ('DeviceID', wintypes.WCHAR * 128),
              ('DeviceKey', wintypes.WCHAR * 128)
          ]
      
      if __name__ == '__main__':
          EnumDisplayDevices = ctypes.windll.user32.EnumDisplayDevicesW       # get the function address
          EnumDisplayDevices.restype = ctypes.c_bool                          # set return type to BOOL
      
          displays = []           # to store display information
          i = 0                   # iteration variable for 'iDevNum'
          j = 0
          while True:
              INFO = DISPLAY_DEVICEW()            # struct object
              INFO.cb = ctypes.sizeof(INFO)       # setting 'cnSize' prior to calling 'EnumDisplayDevicesW'
              Monitor_INFO = DISPLAY_DEVICEW()   
              Monitor_INFO.cb = ctypes.sizeof(Monitor_INFO)  
              if not EnumDisplayDevices(None, i, ctypes.byref(INFO), 0):
                  break       # break as soon as False is returned by 'EnumDisplayDevices'
              #j = 0
              while EnumDisplayDevices(INFO.DeviceName,j,ctypes.byref(Monitor_INFO),0):
                  print("monitor name:\t\t",Monitor_INFO.DeviceName,'\n\n')
                  j+=1
      
              displays.append(INFO)       # append information to the list
              i += 1
      
          # display information in a sequential form
          for x in displays:
              print('DeviceName:\t\t', x.DeviceName)
              print("DeviceString:\t", x.DeviceString)
              print("StateFlags:\t\t", x.StateFlags)
              print("DeviceID:\t\t", x.DeviceID)
              print("DeviceKey:\t\t", x.DeviceKey)
              print(), print()
      

      【讨论】:

      • 天哪!非常感谢你,伙计。你救了我的命。我在玩转适配器,误以为它是我的显示器。非常感谢!
      猜你喜欢
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多