multiple monitors

Share your advanced PureBasic knowledge/code with the community.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

multiple monitors

Post by blueznl »

spent some more time trying to figure out ms's logic (or lack of)

here's another sample how to detect multiple monitors, commented and all
can some of you run this on your system and tell me if the results are correct? (anything win98 or better should work, win95 WILL not work, some early versions of NT MIGHT not work)

Code: Select all

; purebasic survival guide
; multi_monitor_2.pb - 30.12.2003 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/pure1.htm
;
; - how to detect multiple monitors and their relative position to each other
; - EndumDisplayMonitors_()
; - EnumDisplayDevices_()
; - EnumDisplaySettings_()
; - MonitorFromPoint_()
; - GetMonitorInfo_()
;
; constants / structs for multi monitor handling
;
#SM_XVIRTUALSCREEN        = 76        ; x-coordinate of left upper corner of total display area
#SM_YVIRTUALSCREEN        = 77        ; same for y
#SM_CXVIRTUALSCREEN       = 78        ; width
#SM_CYVIRTUALSCREEN       = 79        ; height
#SM_CMONITORS             = 80        ; number of monitors
#SM_SAMEDISPLAYFORMAT     = 81        ; identical sizing of all screens
;
#MONITOR_DEFAULTTONULL    = 0
#MONITOR_DEFAULTTOPRIMARY = 1
#MONITOR_DEFAULTTONEAREST = 2
;
#SM_XVIRTUALSCREEN        = 76        ; x-coordinate of left upper corner of total display area
#SM_YVIRTUALSCREEN        = 77        ; same for y
#SM_CXVIRTUALSCREEN       = 78        ; width
#SM_CYVIRTUALSCREEN       = 79        ; height
#SM_CMONITORS             = 80        ; number of monitors
#SM_SAMEDISPLAYFORMAT     = 81        ; identical sizing of all screens
;
#DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = $1
#DISPLAY_DEVICE_MULTI_DRIVER        = $2
#DISPLAY_DEVICE_PRIMARY_DEVICE      = $4
#DISPLAY_DEVICE_MIRRORING_DRIVER    = $8
#DISPLAY_DEVICE_VGA_COMPATIBLE      = $10
#DISPLAY_DEVICE_REMOVABLE           = $20
#DISPLAY_DEVICE_MODESPRUNED         = $8000000
#DISPLAY_DEVICE_REMOTE              = $4000000
#DISPLAY_DEVICE_DISCONNECT          = $2000000
#DISPLAY_DEVICE_ACTIVE              = $1
#DISPLAY_DEVICE_ATTACHED            = $2
;
#CCHDEVICENAME = 32
#CCHFORMNAME = 32
;
#ENUM_CURRENT_SETTINGS = -1
#ENUM_REGISTRY_SETTINGS = -2
;
#MONITOR_DEFAULTTONULL    = 0
#MONITOR_DEFAULTTOPRIMARY = 1
#MONITOR_DEFAULTTONEAREST = 2
;
Structure MONITORINFO                     ; used to retrieve monitor info
  cb.l                                    ; size of structure (fill before using)
  m_x1.l                                  ; rectangle, monitor coords x1/y1/x2/y2
  m_y1.l
  m_x2.l
  m_y2.l
  w_x1.l                                  ; rectangle, work area coords (?)
  w_y1.l
  w_x2.l
  w_y2.l
  flags.l
EndStructure
;
Structure MONITORINFOEX                   ; superset of MONITORINFO with added  string for devicename
  cb.l  
  m_x1.l
  m_y1.l
  m_x2.l
  m_y2.l
  w_x1.l
  w_y1.l
  w_x2.l
  w_y2.l
  flags.l
  name.b[32]                              ; #CCHDEVICENAME = 32
EndStructure
;
Structure DISPLAY_DEVICE                  ; used to retrieve monitor and device info
  cb.l                                    ; length of struct
  DeviceName.b[32]
  DeviceString.b[128]
  StateFlags.l
  DeviceID.b[128]
  DeviceKey.b[128]
EndStructure
;  
Structure x_monitorinfo                   ; used to store monitor info
  n.l                                     ; sequential number
  hnd.l                                   ; handle
  x.l                                     ; x-position
  y.l                                     ; y-position
  w.l                                     ; width
  h.l                                     ; height
  d.l                                     ; colour depth (bits)
  f.l                                     ; frequency  
  name.s                                  ; devicename (i want my fixed length strings!)
  flags.l                                 ; status of the device
EndStructure
;
x_monitor_n.l = 0                         ; number of monitors is... zero? :-)
NewList x_monitor.x_monitorinfo()         ; info on monitors
x_desktop.x_monitorinfo                   ; info on desktop

Procedure x_monitor_monitorenumproc(WindowID, Message, WPARAM, LPARAM) 
  ;
  ; store on each call the monitor handle in the x_monitor() list
  ; called by windows in callback as set up in x_monitor_detect() by the api EnumDisplayMonitors_()
  ; also known as MonitorEnumProc
  ;
  AddElement(x_monitor())
  x_monitor()\hnd = WindowID
  ; 
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

Procedure.l x_monitor_detect()
  Protected info.MONITORINFOEX, device.DISPLAY_DEVICE, n.l
  Global x_retval.l, x_monitor_n.l, x_desktop.x_monitorinfo
  Global x_monitor_samedisplayformat.l
  ;
  ; *** detect number of screens and retrieve their properties
  ; 
  ; in:
  ; retval:
  ; out:    x_monitor_n.l    - number of screens
  ;         x_desktop_w.l    - desktop width
  ;         x_desktop_h.l    - desktop height
  ;
  ; GetSystemMetrics_()
  ;
  ; provides quite a bit info on display adapters, screens etc. but does not provide info
  ; per monitor / device on multi monitor setups
  ;
  ; x_monitor_n = GetSystemMetrics_(#SM_CMONITORS)
  ; x_monitor_samedisplayformat.l = GetSystemMetrics_(#SM_SAMEDISPLAYFORMAT)
  ;
  x_desktop\w = GetSystemMetrics_(#SM_CXVIRTUALSCREEN)
  x_desktop\h = GetSystemMetrics_(#SM_CYVIRTUALSCREEN)
  ;
  ; Debug "same display format on all screens (0 = no)"
  ; Debug x_monitor_samedisplayformat
  ; Debug "counted using getsystemmetrics"
  ; Debug x_monitor_n
  ;
  ; EnumDisplayMonitors()
  ;
  ; returns monitors overlapping a given rectangle, including pseudo / mirror monitors!
  ; after the call, for each monitor a handle will be stored in x_monitor()\hnd
  ; this can be used to obtain more information using GetMonitorInfo_()
  ; flags returned are different from EnumDisplayDevices()
  ;
  ; ClearList(x_monitor())
  ; EnumDisplayMonitors_(0,0,@x_monitor_monitorenumproc(),0)      ; call the function
  ; info.MONITORINFOEX                                            ; create a struct for GetMonitorInfo_()
  ; info\cb = SizeOf(info)                                        ; length of struct (important for MONITORINFO vs. MONITORINFOEX)
  ; x_monitor_n = 0                                               ; nr. of monitors  
  ; ResetList(x_monitor())                                        ; reset and...
  ; While NextElement(x_monitor())                                ; go through the list    
  ;   x_monitor_n = x_monitor_n+1
  ;   x_monitor()\n = x_monitor_n                                 ; sequential number
  ;   GetMonitorInfo_(x_monitor()\hnd,@info)                      ; get info on the monitor
  ;   x_monitor()\x = info\m_x1
  ;   x_monitor()\y = info\m_y1
  ;   x_monitor()\w = info\m_x2 - info\m_x1
  ;   x_monitor()\h = info\m_y2 - info\m_y1
  ;   x_monitor()\name = PeekS(@info\name,32)                     ; i want my fixed length strings!
  ; Wend  
  ; ;
  ; Debug "counted using enumdisplaymonitors"
  ; Debug x_monitor_n
  ;
  ; EnumDisplayDevices()
  ;
  ; walks through all available devices, retrieve names and flags
  ; by using the returned flags all 'non-real' monitors can be filtered out
  ;
  device.DISPLAY_DEVICE                                         ; to store results from EnumDisplayDevices_()
  device\cb = SizeOf(DISPLAY_DEVICE)
  settings.DEVMODE                                              ; to store results from EnumDisplaySettings_()
  settings\dmSize = SizeOf(settings)                            ; DEVMODE is declared in purebasic itself
  settings\dmDriverExtra = 0
  ;
  ClearList(x_monitor())
  n.l = 0
  x_monitor_n = 0       
  While EnumDisplayDevices_(0,n,@device,0) > 0      ; check all devices
    n = n+1
    ;
    ; the StateFlags field in the filled struct contains information on the device / monitor
    ; some values to check with (not all cards / drivers support all functions):
    ;
    ; #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP - in use and part of the desktop
    ; #DISPLAY_DEVICE_PRIMARY_DEVICE      - primary device
    ; #DISPLAY_DEVICE_VGA_COMPATIBLE      - none reported
    ; #DISPLAY_DEVICE_MULTI_DRIVER        
    ; #DISPLAY_DEVICE_ACTIVE              
    ; #DISPLAY_DEVICE_ATTACHED            
    ;
    If device\StateFlags & #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP      ; check if it's part of the desktop
      ;
      ; if a device is part of the desktop, additional information can be retrieved using
      ; EnumDisplaySettings_() with the device name
      ;
      If EnumDisplaySettings_(@device\DeviceName,#ENUM_CURRENT_SETTINGS,@settings) > 0
        ;
        ; first store some info found via EnumDisplayDevices_()
        ;
        AddElement(x_monitor())                                    
        x_monitor_n = x_monitor_n+1
        x_monitor()\n = x_monitor_n
        x_monitor()\name = PeekS(@device\DeviceName,32)             ; i want my fixed length strings!
        x_monitor()\flags = device\StateFlags
        ;
        ; and more stuff found via EnumDisplaySettings_()
        ;
        x_monitor()\f = settings\dmDisplayFrequency
        x_monitor()\d = settings\dmBitsPerPel
        x_monitor()\w = settings\dmPelsWidth
        x_monitor()\h = settings\dmPelsHeight
        x_monitor()\x = settings\dmOrientation+settings\dmPaperSize<<16       ; the default definition in purebasic didn't include the onion, well, this works as well
        x_monitor()\y = settings\dmPaperLength+settings\dmPaperWidth<<16
        ;
        ; still, the handle is missing, so find that one using a point that is somewhere on the monitor
        ;
        x_monitor()\hnd = MonitorFromPoint_(x_monitor()\x,x_monitor()\y,#MONITOR_DEFAULTTONULL)
        ;    
      EndIf
    EndIf
  Wend
  ;
  ; Debug "counted using enumdisplaydevices"
  ; Debug x_monitor_n
  ;
  x_retval = x_monitor_n
  ProcedureReturn x_retval
EndProcedure

x_monitor_detect()

ResetList(x_monitor())
While NextElement(x_monitor())
  Debug ""
  Debug "monitor  "+Str(x_monitor()\n)
  If x_monitor()\flags & #DISPLAY_DEVICE_PRIMARY_DEVICE
    Debug "primary display"
  EndIf
  Debug "name    "+x_monitor()\name
  Debug "handle  "+Str(x_monitor()\hnd)
  Debug "pos x   "+Str(x_monitor()\x)
  Debug "pos y   "+Str(x_monitor()\y)
  Debug "width   "+Str(x_monitor()\w)
  Debug "height  "+Str(x_monitor()\h)
  Debug "depth   "+Str(x_monitor()\d)
  Debug "refresh "+Str(x_monitor()\f)
Wend

 
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

correct results here (win2k). good work
quidquid Latine dictum sit altum videtur
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

Works here except second monitor :
pos y -65816

Win 98 SE
ATI Radeon 7500 (catalyst 03.9)

Bests.

Stan.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

stan, what kind of monitor setup do you have? that is, is monitor 2 LEFT of monitor 1? could you post the results?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

blueznl,

What do you mean by monitor 2 is left of 1 ?
Physically, monitor 2 (the one attached to the DVI output), is to the right of monitor 1 and when going from 1 to 2 I drag windows to my right as well.

This is what I get :
monitor 1
primary display
name \\. \Display1\Unit0
handle 4514
pos x 0
pos y 0
width 1280
height 1024
depth 32
refresh 0

monitor 2
name \\. \Display1\Unit1
handle 4576
pos x 1280
pos y -65816
width 1024
height 768
depth 32
refresh 0

Bests.

Stan.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

could be a wrap, can you replace the correcponding section of the code with this?

Code: Select all

; and more stuff found via EnumDisplaySettings_()
        ;
        x_monitor()\f = settings\dmDisplayFrequency
        x_monitor()\d = settings\dmBitsPerPel
        x_monitor()\w = settings\dmPelsWidth
        x_monitor()\h = settings\dmPelsHeight
        x_monitor()\x = PeekL(@settings\dmOrientation)              ; the default definition in purebasic didn't include the onion, well, this works as well
        x_monitor()\y = PeekL(@settings\dmPaperLength)

( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

Hi,

It's better I get :

This is what I get :
monitor 1
primary display
name \\. \Display1\Unit0
handle 4514
pos x 0
pos y 0
width 1280
height 1024
depth 32
refresh 0

monitor 2
name \\. \Display1\Unit1
handle 4576
pos x 1280
pos y - 280 ; INSTEAD OF -65816
width 1024
height 768
depth 32
refresh 0

Bests.

Stan.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

hmm... how did you arrange your monitors? it appears as if the one on the right is slightly higher located than the one on the left, is that correct? (check out the relative positions of the screens in display properties under windows)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

Hi blueznl,

You're perfectly right ! My right monitor was higher than the left one (I didn't know that you could move them in the display properties, I thought it was just a symbolic representation of the screens ...).
Your program now runs perfectly !!! (and may I add that you're a real wizard being able to solve that kind of things remotely ...)

Bests.

Stan.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

not a wizard, just logic and deduction (though i'm blushing now :-))
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Post by fsw »

Is there a way to get the real size of the monitor like 15", 17", 19", 21" :?:

Let's say you want to draw a rectangle with a certain physical size, and this physical size should always be the same on a 15" or 21" even if both have the same resolution (1024x768).


Thanks in advance
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

mmmm... theoretically: no, as one could connect any type of monitor and fool the system, however....

most devices are recognized and identified by windows, i dunno if it is possible (it is, but i don't know how :-)) to read that information from windows (ie. determine what windows thinks what kind of hardware devices are attached)

that's, obviously, not foolproof, as the user may have selected a totally different driver compared with his actual monitor, but it is better than nothing

ps. some more vb samples of multi monitor programming here http://www.vbaccelerator.com/home/VB/Ti ... rticle.asp
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Post by fsw »

Actually, I thought that it would be nice if a monitor could send some information to the graphic card and tell him his physical size.

Because it would make sense to set the view of a wordprocessor to 100% and the width of the page would be 8.5" (us letter size).

Or to have a picture from a digital camera on screen and have the picture 6"x4" (like the real picture).
PB&J Lover
Enthusiast
Enthusiast
Posts: 212
Joined: Fri Apr 22, 2005 2:07 pm
Location: U.S.A.
Contact:

monitor program

Post by PB&J Lover »

Add this to the bottom and you can make compile it as a stand-alone.

Code: Select all

x_monitor_detect() 
OpenConsole()
ResetList(x_monitor()) 
While NextElement(x_monitor()) 
  PrintN("") 
  PrintN("monitor  "+Str(x_monitor()\n)) 
  If x_monitor()\flags & #DISPLAY_DEVICE_PRIMARY_DEVICE 
    PrintN("primary display") 
  EndIf 
  PrintN("name    "+x_monitor()\name) 
  PrintN("handle  "+Str(x_monitor()\hnd)) 
  PrintN("pos x   "+Str(x_monitor()\X)) 
  PrintN("pos y   "+Str(x_monitor()\Y)) 
  PrintN("width   "+Str(x_monitor()\w)) 
  PrintN("height  "+Str(x_monitor()\h)) 
  PrintN("depth   "+Str(x_monitor()\d)) 
  PrintN("refresh "+Str(x_monitor()\f)) 
Wend  

Input() : End
Good job!
-- DB

Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius — and a lot of courage — to move in the opposite direction.

Albert Einstein
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Quickly changed the example so it works on PB4


WARNING! Only works with unicode exe disabled WARNING!

Code: Select all

; purebasic survival guide
; multi_monitor_2.pb - 30.12.2003 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/pure1.htm
;
; - how to detect multiple monitors and their relative position to each other
; - EndumDisplayMonitors_()
; - EnumDisplayDevices_()
; - EnumDisplaySettings_()
; - MonitorFromPoint_()
; - GetMonitorInfo_()
;
; constants / structs for multi monitor handling
;
#SM_XVIRTUALSCREEN        = 76        ; x-coordinate of left upper corner of total display area
#SM_YVIRTUALSCREEN        = 77        ; same for y
#SM_CXVIRTUALSCREEN       = 78        ; width
#SM_CYVIRTUALSCREEN       = 79        ; height
#SM_CMONITORS             = 80        ; number of monitors
#SM_SAMEDISPLAYFORMAT     = 81        ; identical sizing of all screens
;
#MONITOR_DEFAULTTONULL    = 0
#MONITOR_DEFAULTTOPRIMARY = 1
#MONITOR_DEFAULTTONEAREST = 2
;
#SM_XVIRTUALSCREEN        = 76        ; x-coordinate of left upper corner of total display area
#SM_YVIRTUALSCREEN        = 77        ; same for y
#SM_CXVIRTUALSCREEN       = 78        ; width
#SM_CYVIRTUALSCREEN       = 79        ; height
#SM_CMONITORS             = 80        ; number of monitors
#SM_SAMEDISPLAYFORMAT     = 81        ; identical sizing of all screens
;
#DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = $1
#DISPLAY_DEVICE_MULTI_DRIVER        = $2
#DISPLAY_DEVICE_PRIMARY_DEVICE      = $4
#DISPLAY_DEVICE_MIRRORING_DRIVER    = $8
#DISPLAY_DEVICE_VGA_COMPATIBLE      = $10
#DISPLAY_DEVICE_REMOVABLE           = $20
#DISPLAY_DEVICE_MODESPRUNED         = $8000000
#DISPLAY_DEVICE_REMOTE              = $4000000
#DISPLAY_DEVICE_DISCONNECT          = $2000000
#DISPLAY_DEVICE_ACTIVE              = $1
#DISPLAY_DEVICE_ATTACHED            = $2
;
#CCHDEVICENAME = 32
#CCHFORMNAME = 32
;
#ENUM_CURRENT_SETTINGS = -1
#ENUM_REGISTRY_SETTINGS = -2
;
#MONITOR_DEFAULTTONULL    = 0
#MONITOR_DEFAULTTOPRIMARY = 1
#MONITOR_DEFAULTTONEAREST = 2
;
Structure MONITORINFO                     ; used to retrieve monitor info
  cb.l                                    ; size of structure (fill before using)
  m_x1.l                                  ; rectangle, monitor coords x1/y1/x2/y2
  m_y1.l
  m_x2.l
  m_y2.l
  w_x1.l                                  ; rectangle, work area coords (?)
  w_y1.l
  w_x2.l
  w_y2.l
  flags.l
EndStructure
;
Structure MONITORINFOEX                   ; superset of MONITORINFO with added  string for devicename
  cb.l 
  m_x1.l
  m_y1.l
  m_x2.l
  m_y2.l
  w_x1.l
  w_y1.l
  w_x2.l
  w_y2.l
  flags.l
  name.b[32]                              ; #CCHDEVICENAME = 32
EndStructure
;
 
Structure x_monitorinfo                   ; used to store monitor info
  n.l                                     ; sequential number
  hnd.l                                   ; handle
  x.l                                     ; x-position
  y.l                                     ; y-position
  w.l                                     ; width
  h.l                                     ; height
  d.l                                     ; colour depth (bits)
  f.l                                     ; frequency 
  name.s                                  ; devicename (i want my fixed length strings!)
  flags.l                                 ; status of the device
EndStructure
;
NewList x_monitor.x_monitorinfo()         ; info on monitors
x_desktop.x_monitorinfo                   ; info on desktop

Procedure x_monitor_monitorenumproc(WindowID, Message, WPARAM, LPARAM)
 Shared x_monitor()
  ;
  ; store on each call the monitor handle in the x_monitor() list
  ; called by windows in callback as set up in x_monitor_detect() by the api EnumDisplayMonitors_()
  ; also known as MonitorEnumProc
  ;
  AddElement(x_monitor())
  x_monitor()\hnd = WindowID
  ;
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure.l x_monitor_detect()
  Protected info.MONITORINFOEX, device.DISPLAY_DEVICE, n.l,settings.DEVMODE
  Protected x_retval.l, x_monitor_n.l
  Shared x_desktop,x_monitor()
  Protected x_monitor_samedisplayformat.l
  ;
  ; *** detect number of screens and retrieve their properties
  ;
  ; in:
  ; retval:
  ; out:    x_monitor_n.l    - number of screens
  ;         x_desktop_w.l    - desktop width
  ;         x_desktop_h.l    - desktop height
  ;
  ; GetSystemMetrics_()
  ;
  ; provides quite a bit info on display adapters, screens etc. but does not provide info
  ; per monitor / device on multi monitor setups
  ;
  ; x_monitor_n = GetSystemMetrics_(#SM_CMONITORS)
  ; x_monitor_samedisplayformat.l = GetSystemMetrics_(#SM_SAMEDISPLAYFORMAT)
  ;
  x_desktop\w = GetSystemMetrics_(#SM_CXVIRTUALSCREEN)
  x_desktop\h = GetSystemMetrics_(#SM_CYVIRTUALSCREEN)
  ;
  ; Debug "same display format on all screens (0 = no)"
  ; Debug x_monitor_samedisplayformat
  ; Debug "counted using getsystemmetrics"
  ; Debug x_monitor_n
  ;
  ; EnumDisplayMonitors()
  ;
  ; returns monitors overlapping a given rectangle, including pseudo / mirror monitors!
  ; after the call, for each monitor a handle will be stored in x_monitor()\hnd
  ; this can be used to obtain more information using GetMonitorInfo_()
  ; flags returned are different from EnumDisplayDevices()
  ;
  ; ClearList(x_monitor())
  ; EnumDisplayMonitors_(0,0,@x_monitor_monitorenumproc(),0)      ; call the function
  ; info.MONITORINFOEX                                            ; create a struct for GetMonitorInfo_()
  ; info\cb = SizeOf(info)                                        ; length of struct (important for MONITORINFO vs. MONITORINFOEX)
  ; x_monitor_n = 0                                               ; nr. of monitors 
  ; ResetList(x_monitor())                                        ; reset and...
  ; While NextElement(x_monitor())                                ; go through the list   
  ;   x_monitor_n = x_monitor_n+1
  ;   x_monitor()\n = x_monitor_n                                 ; sequential number
  ;   GetMonitorInfo_(x_monitor()\hnd,@info)                      ; get info on the monitor
  ;   x_monitor()\x = info\m_x1
  ;   x_monitor()\y = info\m_y1
  ;   x_monitor()\w = info\m_x2 - info\m_x1
  ;   x_monitor()\h = info\m_y2 - info\m_y1
  ;   x_monitor()\name = PeekS(@info\name,32)                     ; i want my fixed length strings!
  ; Wend 
  ; ;
  ; Debug "counted using enumdisplaymonitors"
  ; Debug x_monitor_n
  ;
  ; EnumDisplayDevices()
  ;
  ; walks through all available devices, retrieve names and flags
  ; by using the returned flags all 'non-real' monitors can be filtered out
  ;
                                      ; to store results from EnumDisplayDevices_()
  device\cb = SizeOf(DISPLAY_DEVICE)
                                                ; to store results from EnumDisplaySettings_()
  settings\dmSize = SizeOf(settings)                            ; DEVMODE is declared in purebasic itself
  settings\dmDriverExtra = 0
  ;
  ClearList(x_monitor())
  n.l = 0
  x_monitor_n = 0       
  While EnumDisplayDevices_(0,n,device,0) > 0      ; check all devices
    n = n+1
    ;
    ; the StateFlags field in the filled struct contains information on the device / monitor
    ; some values to check with (not all cards / drivers support all functions):
    ;
    ; #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP - in use and part of the desktop
    ; #DISPLAY_DEVICE_PRIMARY_DEVICE      - primary device
    ; #DISPLAY_DEVICE_VGA_COMPATIBLE      - none reported
    ; #DISPLAY_DEVICE_MULTI_DRIVER       
    ; #DISPLAY_DEVICE_ACTIVE             
    ; #DISPLAY_DEVICE_ATTACHED           
    ;
    If (device\StateFlags & #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) = #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP     ; check if it's part of the desktop
      ;
      ; if a device is part of the desktop, additional information can be retrieved using
      ; EnumDisplaySettings_() with the device name
      ;
      If EnumDisplaySettings_(PeekS(@device\devicename,32),#ENUM_CURRENT_SETTINGS,settings) > 0
        ;
        ; first store some info found via EnumDisplayDevices_()
        ;
        AddElement(x_monitor())                                   
        x_monitor_n = x_monitor_n+1
        x_monitor()\n = x_monitor_n
        x_monitor()\name = PeekS(@device\DeviceName,32)             ; i want my fixed length strings!
        x_monitor()\flags = device\StateFlags
        ;
        ; and more stuff found via EnumDisplaySettings_()
        ;
        x_monitor()\f = settings\dmDisplayFrequency
        x_monitor()\d = settings\dmBitsPerPel
        x_monitor()\w = settings\dmPelsWidth
        x_monitor()\h = settings\dmPelsHeight
        x_monitor()\x = settings\dmOrientation+settings\dmPaperSize<<16       ; the default definition in purebasic didn't include the onion, well, this works as well
        x_monitor()\y = settings\dmPaperLength+settings\dmPaperWidth<<16
        ;
        ; still, the handle is missing, so find that one using a point that is somewhere on the monitor
        ;
        x_monitor()\hnd = MonitorFromPoint_(x_monitor()\x,x_monitor()\y,#MONITOR_DEFAULTTONULL)
        ;   
      EndIf
    EndIf
  Wend
  ;
  ; Debug "counted using enumdisplaydevices"
  ; Debug x_monitor_n
  ;
  x_retval = x_monitor_n
  ProcedureReturn x_retval
EndProcedure

x_monitor_detect()

ResetList(x_monitor())
While NextElement(x_monitor())
  Debug ""
  Debug "monitor  "+Str(x_monitor()\n)
  If x_monitor()\flags & #DISPLAY_DEVICE_PRIMARY_DEVICE
    Debug "primary display"
  EndIf
  Debug "name    "+x_monitor()\name
  Debug "handle  "+Str(x_monitor()\hnd)
  Debug "pos x   "+Str(x_monitor()\x)
  Debug "pos y   "+Str(x_monitor()\y)
  Debug "width   "+Str(x_monitor()\w)
  Debug "height  "+Str(x_monitor()\h)
  Debug "depth   "+Str(x_monitor()\d)
  Debug "refresh "+Str(x_monitor()\f)
Wend

x_monitor_detect()
OpenConsole()
ResetList(x_monitor())
While NextElement(x_monitor())
  PrintN("")
  PrintN("monitor  "+Str(x_monitor()\n))
  If x_monitor()\flags & #DISPLAY_DEVICE_PRIMARY_DEVICE
    PrintN("primary display")
  EndIf
  PrintN("name    "+x_monitor()\name)
  PrintN("handle  "+Str(x_monitor()\hnd))
  PrintN("pos x   "+Str(x_monitor()\X))
  PrintN("pos y   "+Str(x_monitor()\Y))
  PrintN("width   "+Str(x_monitor()\w))
  PrintN("height  "+Str(x_monitor()\h))
  PrintN("depth   "+Str(x_monitor()\d))
  PrintN("refresh "+Str(x_monitor()\f))
Wend 

Input() : End
Post Reply