Visual Basic Enumeration/Callback Routines
EnumDisplayDevices: Enumerating System Display Devices
     
Posted:   Friday March 29, 2002
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   Windows 98 or greater, Windows 2000 or greater
Author:   VBnet - Randy Birch
     

Related:  

ChangeDisplaySettings: Change Display Resolution
EnumDisplaySettings: Enumerate Available Display Resolutions
EnumDisplayDevices: Enumerating System Display Devices

EnumDisplayMonitors: Enumerating System Monitor Info
       
 Prerequisites
Windows 98 and later, Windows 2000 and later.

EnumDisplayDevices provides information about the display devices in a system, and can be used in two ways.

The call to EnumDisplayDevices passes four parameters:

  • lpDevice - the device name.
  • iDevNum - the index value that specifies the display device of interest. The operating system identifies each display device with an index value. The index values are consecutive integers, starting at 0. If a system has three display devices, for example, they are specified by the index values 0, 1, and 2.
  • lpDisplayDevice - a DISPLAY_DEVICE structure that receives information about the display device specified by iDevNum, and
  • dwFlags - currently not used and should be set to zero.

To enumerate devices - aka adapters, the lpDevice member of the EnumDisplayDevices, which normally would point to a device name, is passed as 0&. The iDevNum member, is incremented in successive calls to the API until the call returns 0.  On each call, the DISPLAY_DEVICE structure passed is filled with appropriate information about the device (as shown by the Device info in the illustration).

When you want to retrieve information about the physical monitor attached to a specific device, the iDevNum member is not used and is passed as 0&, whereas the lpDevice member of EnumDisplayDevices is passed containing the device name of interest (i.e. \\.\DISPLAY1), where DISPLAY_DEVICE structure is filled with appropriate information about the monitor (as shown by the Accoc Monitor info in the illustration).

This demo shows building that loop, calling the API to retrieve the device info, extracting the device name, and calling again to retrieve the monitor info for the device (if available).

 BAS Module Code
None.

 Form Code
Add a listview (LV) and a command button to a form. To the listview, add five column headers as indicated, and set the style to report mode. Add the following to the form:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'for listview column auto-resizing
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SETCOLUMNWIDTH As Long = (LVM_FIRST + 30)
Private Const LVSCW_AUTOSIZE As Long = -1
Private Const LVSCW_AUTOSIZE_USEHEADER As Long = -2

Private Declare Function SendMessage Lib "user32" _
   Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   lParam As Any) As Long

'EnumDisplayDevices Requirements
'  Windows NT/2000/XP: Included in Windows 2000 and later.
'  Windows 95/98/Me:   Included in Windows 98 and later.
Private Type DISPLAY_DEVICE
   cb As Long
   DeviceName(0 To 31) As Byte
   DeviceString(0 To 127) As Byte
   StateFlags As Long
   DeviceID(0 To 127) As Byte
   DeviceKey(0 To 127) As Byte
End Type

Private Const DD_ATTACHED_TO_DESKTOP As Long = &H1
Private Const DD_MULTI_DRIVER        As Long = &H2
Private Const DD_PRIMARY_DEVICE      As Long = &H4
Private Const DD_MIRRORING_DRIVER    As Long = &H8
Private Const DD_VGA_COMPATIBLE      As Long = &H10
Private Const DD_REMOVABLE           As Long = &H20
Private Const DD_DISCONNECT          As Long = &H2000000 'WINVER >= 5
Private Const DD_REMOTE              As Long = &H4000000 'WINVER >= 5
Private Const DD_MODESPRUNED         As Long = &H8000000 'WINVER >= 5

Private Declare Function EnumDisplayDevices Lib "user32" _
   Alias "EnumDisplayDevicesA" _
  (ByVal lpDevice As Any, _
   ByVal iDevNum As Long, _
   lpDisplayDevice As DISPLAY_DEVICE, _
   ByVal dwFlags As Long) As Long
   


Private Sub Form_Load()

   With ListView1
      .ListItems.Clear
      .View = lvwReport
      .Sorted = False
      .ColumnHeaders.Clear
      .ColumnHeaders.Add , , "DisplayDevice Member"
      
      .ListItems.Add , , "Device Name"
      .ListItems.Add , , "Device String"
      .ListItems.Add , , "Device StateFlags:"
      .ListItems.Add , , "  - part of desktop"
      .ListItems.Add , , "  - primary device"
      .ListItems.Add , , "  - pseudo device"
      .ListItems.Add , , "  - VGA compatible"
      .ListItems.Add , , "  - removable (cannot be primary)"
      .ListItems.Add , , "  - more modes than output device"
      .ListItems.Add , , "Assoc Monitor Name"
      .ListItems.Add , , "Assoc Monitor String"
      .ListItems.Add , , "Assoc Monitor StateFlags:"
      .ListItems.Add , , "  - multi-driver"
   
   End With

   Command1.Caption = "EnumDisplayDevices"

End Sub


Private Sub Command1_Click()

   Call EnumSystemDisplayDevices
   Call lvAutosizeControl(ListView1)
   
End Sub


Private Sub EnumSystemDisplayDevices()
        
   Dim iDevNum As Long
   Dim thiscol As Long
   Dim sDeviceName As String 'required in 3 places
   Dim dev As DISPLAY_DEVICE
   
  'Query all display devices in the system by
  'calling EnumDisplayDevices in a loop, starting
  'with iDevNum set to 0, and incrementing until
  'the function fails (call returns non-zero if
  'true or 0 if false).
  
   dev.cb = Len(dev)
   iDevNum = 0
   
   Do While EnumDisplayDevices(0&, iDevNum, dev, 0&)

     'for each display device returned,
     'add a new column to the listview
     'and populate its data
      With ListView1
      
         sDeviceName = TrimNull(StrConv(dev.DeviceName, vbUnicode))
          
         .ColumnHeaders.Add , , sDeviceName
         thiscol = (.ColumnHeaders.Count - 1)
                   
         .ListItems(1).SubItems(thiscol) = sDeviceName
         .ListItems(2).SubItems(thiscol) = TrimNull(StrConv(dev.DeviceString, vbUnicode))
         .ListItems(3).SubItems(thiscol) = dev.StateFlags
         
         If dev.StateFlags And DD_ATTACHED_TO_DESKTOP Then
            .ListItems(4).SubItems(thiscol) = "Yes"
         End If
            
         If dev.StateFlags And DD_PRIMARY_DEVICE Then
            .ListItems(5).SubItems(thiscol) = "Yes"
         End If
         
         If dev.StateFlags And DD_MIRRORING_DRIVER Then
            .ListItems(6).SubItems(thiscol) = "Yes"
         End If
         
         If dev.StateFlags And DD_VGA_COMPATIBLE Then
            .ListItems(7).SubItems(thiscol) = "Yes"
         End If
         
         If dev.StateFlags And DD_REMOVABLE Then
            .ListItems(8).SubItems(thiscol) = "Yes"
         End If
         
         If dev.StateFlags And DD_MODESPRUNED Then
            .ListItems(9).SubItems(thiscol) = "Yes"
         End If
      
        'When null was passed as lpDevice above,
        'information about the display device (adapter)
        'was returned. By calling the API once again,
        'this time specifying lpDevice=dev.devicename and
        'iDevNum=0, the same call returns information about
        'the monitor connected to the specified device.
         If EnumDisplayDevices(sDeviceName, 0, dev, 0&) <> 0 Then
         
            .ListItems(10).SubItems(thiscol) = TrimNull(StrConv(dev.DeviceName, vbUnicode))
            .ListItems(11).SubItems(thiscol) = TrimNull(StrConv(dev.DeviceString, vbUnicode))
            .ListItems(12).SubItems(thiscol) = dev.StateFlags
         
            If dev.StateFlags And DD_MULTI_DRIVER Then
               .ListItems(13).SubItems(thiscol) = "Yes"
            End If
         
         End If
   
      End With

      iDevNum = iDevNum + 1
   
   Loop

End Sub


Private Sub lvAutosizeControl(lv As ListView)

   Dim col2adjust As Long

  'Size each column based on the maximum of
  'either the ColumnHeader text width, or,
  'if the items below it are wider, the
  'widest list item in the column
  
   lv.Visible = False
   For col2adjust = 0 To lv.ColumnHeaders.Count - 1
   
      Call SendMessage(lv.hwnd, _
                       LVM_SETCOLUMNWIDTH, _
                       col2adjust, _
                       ByVal LVSCW_AUTOSIZE_USEHEADER)

   Next
   lv.Visible = True
   
End Sub


Private Function TrimNull(item As String)

    Dim pos As Integer
   
   'double check that there is a chr$(0) in the string
    pos = InStr(item, Chr$(0))
    If pos Then
       TrimNull = Left$(item, pos - 1)
    Else
       TrimNull = item
    End If
  
End Function
 Comments

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter