Yup, I got a dual monitor set up now


So, in short... I have the Monitor's Handle... how to put it to use?

Code: Select all
Procedure.l x_monitor_monitorenumproc(windowid, message, wParam, lParam) ; deprecated
;
; 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() ; find info on (multi) monitor setup and desktop sizes and coords
Protected info.MONITORINFOEX, device.DISPLAY_DEVICE, n.l, x.l
Global x_retval.l, x_monitor_n.l
Global x_monitor_sameformat.l, x_monitor_primary.l
Global x_desktop_x, x_desktop_y, x_desktop_width.l, x_desktop_height.l
;
; *** detect number of screens and retrieve their properties
;
; retval: n - number of screens
; out: x_monitor_n.l - number of screens
; x_monitor_primary.l - number of primary display
; x_monitor_sameformat.l - whaddayah think?
; x_desktop_width.l - desktop width
; x_desktop_height.l - desktop height
; x_desktop_x.l - top left corner of most top left screen
; x_desktop_y.l - top left corner of most top left screen
; x_monitor.x_monitorinfo() - linked list starting at 0 containing monitor info
;
; note:
;
; - forget nt3 nt4 w95... all pretty much hopeless when it comes to multimonitor support
; - set x_multimonitorsupport = #false to disable multimonitor support
; - looks like fred is adding natural support for multi monitor configs in purebasic... oh well... at least i had the excercise
;
If OSVersion() = #PB_OS_Windows_95 Or OSVersion() = #PB_OS_Windows_NT3_51 Or OSVersion() = #PB_OS_Windows_NT_4
;
; just report to the system there is only one monitor...
;
x_monitor_n = 1
x_monitor_primary = 1
x_monitor_sameformat = #True
x_desktop_width = GetSystemMetrics_(#SM_CXSCREEN)
x_desktop_height = GetSystemMetrics_(#SM_CYSCREEN)
x_desktop_x = 0
x_desktop_y = 0
;
ClearList(x_monitor())
AddElement(x_monitor())
x_monitor()\n = x_monitor_n
x_monitor()\name = ""
x_monitor()\flags = 0
x_monitor()\f = 0
x_monitor()\d = 0
x_monitor()\w = x_desktop_width
x_monitor()\h = x_desktop_height
x_monitor()\x = x_desktop_x
x_monitor()\y = x_desktop_y
;
Else
;
;
; *** using 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_sameformat.l = GetSystemMetrics_(#SM_SAMEDISPLAYFORMAT)
;
x_desktop_x = GetSystemMetrics_(#SM_XVIRTUALSCREEN)
x_desktop_y = GetSystemMetrics_(#SM_YVIRTUALSCREEN)
x_desktop_width = GetSystemMetrics_(#SM_CXVIRTUALSCREEN)
x_desktop_height = GetSystemMetrics_(#SM_CYVIRTUALSCREEN)
;
; Debug "same display format on all screens (0 = no)"
; Debug x_monitor_sameformat
; Debug "counted using getsystemmetrics"
; Debug x_monitor_n
;
; *** using 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()
;
; the results were not always conclusive when using these functions, so i choose to use
; EnumDisplayDevices instead (see below)
;
; 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
;
; *** using 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 defined in purebasic itself
settings\dmDriverExtra = 0
;
ClearList(x_monitor())
;
n.l = 0
x_monitor_n = 0
x_desktop_x = 0
x_desktop_y = 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
x_monitor()\name = PeekS(@device\DeviceName,32) ; i want my fixed length strings!
x_monitor()\flags = device\StateFlags
;
If x_monitor()\flags & #DISPLAY_DEVICE_PRIMARY_DEVICE
x_monitor_primary = x_monitor_n
EndIf
;
; 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)
;
; x_desktop_x = x_min( x_desktop_x , x_monitor()\x )
; x_desktop_y = x_min( x_desktop_y , x_monitor()\y )
; x_desktop_width = x_max( x_monitor()\x + x_monitor()\w - x_desktop_x , x_desktop_width )
; x_desktop_height = x_max( x_monitor()\y + x_monitor()\h - x_desktop_height , x_desktop_height )
;
; still, the handle is missing, so find it one using a point that is somewhere on the monitor
; theoretically, overlapping devices would be possible and thus screw retrieving any handle...
; haven't seent that though... yet :-( note that enummonitorsettings allows a different way to
; find screen handles
;
; work around for calling the monitorfrompoint function, purebasic tries to get the address of
; the function at program start, thus it will error out on nt4, however by opening the dll
; by hand and looking for the function by name we can circumvent this
;
; x_monitor()\hnd = MonitorFromPoint_(x_monitor()\x,x_monitor()\y,#MONITOR_DEFAULTTONULL)
;
x = OpenLibrary(#PB_Any,"USER32.DLL")
x_monitor()\hnd = CallFunction(x,"MonitorFromPoint",x_monitor()\x,x_monitor()\y,#MONITOR_DEFAULTTONULL)
CloseLibrary(x)
;
x_monitor_n = x_monitor_n+1
EndIf
EndIf
Wend
;
; Debug "counted using enumdisplaydevices"
; Debug x_monitor_n
;
EndIf
;
x_retval = x_monitor_n
ProcedureReturn x_retval
EndProcedure