Dont use StartDrawing() to get the device context.
Its undefined behaviour and therefore bad practise.
If those system handles would be documented it would be another story.
I dont know why such helpful things arent...
Getting to all monitors is not so easy.
Here is my version:
Code: Select all
EnableExplicit
;Procedure - Screenshot()
;Author: Mijikai
Procedure.i Screenshot(MonitorNumber.i = -1,File.s = #Null$,Width.i = #Null,Height.i = #Null)
Protected device.DISPLAY_DEVICE
Protected mode.DEVMODE
Protected bounds.RECT
Protected hmonitor.i
Protected hdc.i
Protected hcopy.i
Protected hbm.i
Protected hrestore.i
Protected *bits
Protected image.i
Protected bminfo.BITMAPINFOHEADER
device\cb = SizeOf(DISPLAY_DEVICE)
If MonitorNumber < 0
ProcedureReturn GetSystemMetrics_(#SM_CMONITORS)
EndIf
If EnumDisplayDevices_(#Null,MonitorNumber,@device,#Null)
If device\StateFlags & (#DISPLAY_DEVICE_ATTACHED_TO_DESKTOP|#DISPLAY_DEVICE_MIRRORING_DRIVER) = #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
mode\dmSize = SizeOf(DEVMODE)
If EnumDisplaySettings_(@device\DeviceName[0],#ENUM_CURRENT_SETTINGS,@mode)
bounds\left = mode\Display\dmPosition\x
bounds\top = mode\Display\dmPosition\y
bounds\right = mode\dmPelsWidth + bounds\left
bounds\bottom = mode\dmPelsHeight + bounds\top
hmonitor = MonitorFromRect_(@bounds,#MONITOR_DEFAULTTONEAREST)
If hmonitor
If Width < 1
Width = mode\dmPelsWidth
EndIf
If Height < 1
Height = mode\dmPelsHeight
EndIf
hdc = GetDC_(#Null)
If hdc
hcopy = CreateCompatibleDC_(hdc)
If hcopy
bminfo\biSize = SizeOf(BITMAPINFOHEADER)
bminfo\biWidth = Width
bminfo\biHeight = Height
bminfo\biPlanes = 1
bminfo\biBitCount = 24
bminfo\biCompression = #BI_RGB
bminfo\biSizeImage = Height * (Width * 3)
hbm = CreateDIBSection_(hcopy,@bminfo,#DIB_RGB_COLORS,@*bits,#Null,#Null)
If hbm
SaveDC_(hcopy)
SelectObject_(hcopy,hbm)
SetStretchBltMode_(hcopy,#HALFTONE)
SetBrushOrgEx_(hcopy,#Null,#Null,#Null)
If StretchBlt_(hcopy,#Null,#Null,Width,Height,hdc,mode\Display\dmPosition\x,mode\Display\dmPosition\y,mode\dmPelsWidth,mode\dmPelsHeight,#SRCCOPY)
image = CreateImage(#PB_Any,Width,Height,24)
If image
If StartDrawing(ImageOutput(image))
CopyMemory(*bits,DrawingBuffer(),bminfo\biSizeImage)
StopDrawing()
RestoreDC_(hcopy,-1)
DeleteObject_(hbm)
DeleteDC_(hcopy)
ReleaseDC_(#Null,hdc)
CloseHandle_(hmonitor)
If File
*bits = SaveImage(image,File,#PB_ImagePlugin_BMP)
FreeImage(image)
ProcedureReturn *bits
Else
ProcedureReturn image
EndIf
EndIf
FreeImage(image)
EndIf
EndIf
RestoreDC_(hcopy,-1)
DeleteObject_(hbm)
EndIf
DeleteDC_(hcopy)
EndIf
ReleaseDC_(#Null,hdc)
EndIf
CloseHandle_(hmonitor)
EndIf
EndIf
EndIf
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i Main()
Protected count.i
Protected index.i
count = Screenshot();<- empty will return the monitor count
;width and height will clamp (resize) the screenshot if specified
;if no file is specified the function will return a image
For index = 0 To count - 1
Debug Screenshot(index,"screenshot_" + Str(index) + ".bmp")
Next
ProcedureReturn #Null
EndProcedure
Main()
End
To take a screenshot of the second monitor (first monitor is 0):
Code: Select all
Screenshot(1,"screenshot_test.bmp")