EnumDisplayDevices giving two Displays even though I have one

杀马特。学长 韩版系。学妹 提交于 2021-01-27 18:44:04

问题


I was making an application for Night Light using Python. I'm using windows API for use of Gamma Ramp to accomplish my task. I used EnumDisplayDevicesW from user32.dll to get the information and number of displays connected to my PC.

I have only one monitor connected to my desktop, but the output is giving information of two monitors.

Here's my code. I'm using Python and accessing WinAPI through ctypes module.

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()

And the output returned by the code is as follows:-

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

As far as I know, the first one, i.e, \\.\DISPLAY1 is mine one, but why there's a need for a second one??

I own a Desktop PC with standard Samsung monitor.

Any help will be very helpful. Thanks in advance!


回答1:


I have only one monitor connected to my desktop, but the output is giving information of two monitors.

Running this code does not tell you that you have two "monitors", but two "adapters".

According to EnumDisplayDevicesW:

To get information on the display adapter, call EnumDisplayDevices with lpDevice set to NULL. For example, DISPLAY_DEVICE.DeviceString contains the adapter name.

To obtain information on a display monitor, first call EnumDisplayDevices with lpDevice set to NULL. Then call EnumDisplayDevices with lpDevice set to DISPLAY_DEVICE.DeviceName from the first call to EnumDisplayDevices and with iDevNum set to zero. Then DISPLAY_DEVICE.DeviceString is the monitor name.

So if you need to get the monitor information, you need to call:

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

Here is a sample:

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()



回答2:


So, after doing required changes, following is the final code to get all the display monitors connected to all the display adapters.

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()

Now, display[0] is the adapter object, and can be used to get the information by referring the above DISPLAY_DEVICEW class, and display[1] is the list of monitors, which can be iterated over to get the objects of the monitor info, and get the information about it by referring DISPLAY_DEVICEW class.



来源:https://stackoverflow.com/questions/65624377/enumdisplaydevices-giving-two-displays-even-though-i-have-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!