Sign in to follow this  
Followers 0
SkinnyWhiteGuy

Multiple Monitor Screenshot

4 posts in this topic

I was in need of this the other day, and researched out how to detect all displays. This should work with any number of monitors, and only generate one picture with all displays in it. It should also try to avoid taking screen shots from virtual displays used by some remote tools.

#NoTrayIcon
#include <ScreenCapture.au3>

Global $tag_DISPLAY_DEVICE = "dword cb;char DeviceName[32];char DeviceString[128];dword StateFlags;char DeviceID[128];char DeviceKey[128]"
Global Const $DISPLAY_DEVICE_MIRRORING_DRIVER = 0x00000008
Global Const $DISPLAY_DEVICE_PRIMARY_DEVICE = 0x00000004

Global $tag_POINTL = "long x;long y"
Global $tag_DEVMOD = "char dmDeviceName[32];ushort dmSpecVersion;ushort dmDriverVersion;short dmSize;" & _
        "ushort dmDriverExtra;dword dmFields;" & $tag_POINTL & ";dword dmDisplayOrientation;dword dmDisplayFixedOutput;" & _
        "short dmColor;short dmDuplex;short dmYResolution;short dmTTOption;short dmCollate;" & _
        "byte dmFormName[32];ushort LogPixels;dword dmBitsPerPel;int dmPelsWidth;dword dmPelsHeight;" & _
        "dword dmDisplayFlags;dword dmDisplayFrequency"
Global Const $ENUM_CURRENT_SETTINGS = -1

Global $Left, $Top, $Right, $Bottom
Global $i = 0

While 1
    $struct = DllStructCreate($tag_DISPLAY_DEVICE)
    DllStructSetData($struct, "cb", DllStructGetSize($struct))

    $aRetrun = DllCall("user32.dll", "int", "EnumDisplayDevices", "ptr", 0, "dword", $i, "ptr", DllStructGetPtr($struct), "dword", 0)
    If Not $aRetrun[0] Then ExitLoop

    If Not BitAND(DllStructGetData($struct, "StateFlags"), $DISPLAY_DEVICE_MIRRORING_DRIVER) Then ; Avoid Virtual Displays
;~      ConsoleWrite(DllStructGetData($struct, "DeviceName") & @TAB & "Primary: " & (BitAND(DllStructGetData($struct, "StateFlags"), $DISPLAY_DEVICE_PRIMARY_DEVICE) > 0) & @CRLF)

        $dev = DllStructCreate($tag_DEVMOD)
        DllStructSetData($dev, "dmSize", DllStructGetSize($dev))
        $aRetrun = DllCall("user32.dll", "int", "EnumDisplaySettings", "str", DllStructGetData($struct, "DeviceName"), "dword", $ENUM_CURRENT_SETTINGS, "ptr", DllStructGetPtr($dev))

        If Not IsNumber($Left) Or $Left > DllStructGetData($dev, "x") Then $Left = DllStructGetData($dev, "x")
        If Not IsNumber($Top) Or $Top > DllStructGetData($dev, "y") Then $Top = DllStructGetData($dev, "y")
        If Not IsNumber($Right) Or $Right < DllStructGetData($dev, "x") + DllStructGetData($dev, "dmPelsWidth") Then $Right = DllStructGetData($dev, "x") + DllStructGetData($dev, "dmPelsWidth")
        If Not IsNumber($Bottom) Or $Bottom < DllStructGetData($dev, "y") + DllStructGetData($dev, "dmPelsHeight") Then $Bottom = DllStructGetData($dev, "y") + DllStructGetData($dev, "dmPelsHeight")
    EndIf
    $i += 1
WEnd

If $CmdLine[0] = 1 Then
    _ScreenCapture_Capture($CmdLine[1], $Left, $Top, $Right, $Bottom)
Else
    _ScreenCapture_Capture(@ScriptDir & "\screenshot.jpg", $Left, $Top, $Right, $Bottom)
EndIf

Tested on Windows 7 (64-bit) & XP (32-bit). The commented line shows how to detect which of the displays is the Primary display.

Share this post


Link to post
Share on other sites



Great script!

Tested on Windows XP SP 3 with 2 monitors.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

wouldn't

#NoTrayIcon
#include <ScreenCapture.au3>

$Pos = WinGetPos("Program Manager")

If $CmdLine[0] = 1 Then
    _ScreenCapture_Capture($CmdLine[1], $Pos[0], $Pos[1], $Pos[0] + $Pos[2], $Pos[1] + $Pos[3])
Else
    _ScreenCapture_Capture(@ScriptDir & "\screenshot.jpg", $Pos[0], $Pos[1], $Pos[0] + $Pos[2], $Pos[1] + $Pos[3])
EndIf

work just as well?


[font="Impact"]Never fear, I is here.[/font]

Share this post


Link to post
Share on other sites

SkinnyWhiteGuy, thanks a lot for your code ;) . It made creating the following UDF, which can be used to retrieve all current, non-virtual displays' positions, a doddle:

#cs
    author: "SkinnyWhiteGuy" on http://www.autoitscript.com/forum/index.php?showtopic=105921
#ce

#include-once

;out: [n][0:x 1:y 2:width 3:height 4:is primary]
Func _displayGetPos()
    
    Local $returnArray[1][5]
    
    Local $tag_DISPLAY_DEVICE = "dword cb;char DeviceName[32];char DeviceString[128];dword StateFlags;char DeviceID[128];char DeviceKey[128]"
    Local $DISPLAY_DEVICE_MIRRORING_DRIVER = 0x00000008
    Local $DISPLAY_DEVICE_PRIMARY_DEVICE = 0x00000004

    Local $tag_POINTL = "long x;long y"
    Local $tag_DEVMOD = "char dmDeviceName[32];ushort dmSpecVersion;ushort dmDriverVersion;short dmSize;" & _
            "ushort dmDriverExtra;dword dmFields;" & $tag_POINTL & ";dword dmDisplayOrientation;dword dmDisplayFixedOutput;" & _
            "short dmColor;short dmDuplex;short dmYResolution;short dmTTOption;short dmCollate;" & _
            "byte dmFormName[32];ushort LogPixels;dword dmBitsPerPel;int dmPelsWidth;dword dmPelsHeight;" & _
            "dword dmDisplayFlags;dword dmDisplayFrequency"
    Local Const $ENUM_CURRENT_SETTINGS = -1

    Local $i = 0
    
    While 1
        
        $struct = DllStructCreate($tag_DISPLAY_DEVICE)
        DllStructSetData($struct, "cb", DllStructGetSize($struct))

        Local $aRetrun = DllCall("user32.dll", "int", "EnumDisplayDevices", "ptr", 0, "dword", $i, "ptr", DllStructGetPtr($struct), "dword", 0)
        If Not $aRetrun[0] Then ExitLoop

        If Not BitAND(DllStructGetData($struct, "StateFlags"), $DISPLAY_DEVICE_MIRRORING_DRIVER) Then ; Avoid Virtual Displays
         ConsoleWrite(DllStructGetData($struct, "DeviceName") & @TAB & "Primary: " & (BitAND(DllStructGetData($struct, "StateFlags"), $DISPLAY_DEVICE_PRIMARY_DEVICE) > 0) & @CRLF)

            $dev = DllStructCreate($tag_DEVMOD)
            DllStructSetData($dev, "dmSize", DllStructGetSize($dev))
            $aRetrun = DllCall("user32.dll", "int", "EnumDisplaySettings", "str", DllStructGetData($struct, "DeviceName"), "dword", $ENUM_CURRENT_SETTINGS, "ptr", DllStructGetPtr($dev))
            
            If IsNumber($returnArray[0][0]) Then ReDim $returnArray[UBound($returnArray)+1][5] ;if not first fill in, upsize

            $returnArray[UBound($returnArray)-1][0]=DllStructGetData($dev,"x")
            $returnArray[UBound($returnArray)-1][1]=DllStructGetData($dev,"y")
            $returnArray[UBound($returnArray)-1][2]=DllStructGetData($dev,"dmPelsWidth")
            $returnArray[UBound($returnArray)-1][3]=DllStructGetData($dev,"dmPelsHeight")
            
            $returnArray[UBound($returnArray)-1][4]=(BitAND(DllStructGetData($struct, "StateFlags"), $DISPLAY_DEVICE_PRIMARY_DEVICE) > 0) ;is primary?

        EndIf
        
        $i += 1
        
    WEnd    
    
    Return $returnArray
    
EndFunc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0