Screenshot of Windows?

BlitzMax Forums/BlitzMax Programming/Screenshot of Windows?

chaos.mod/desktopext.mod can do that, and more:

Public Domain by hamZta, Suco-X, d-bug

See below:

'-- HEADER  ----------------------------------------------------------------------------------------------------------------------

Rem
	bbdoc:    DesktopExt
	about:    DesktopExt dient der Komunikation zwischen BMax und dem Desktop,
                ohne dabei auf MaxGUI Funktionen zurück greifen zu müssen.
End Rem

Module chaos.desktopext
ModuleInfo "Version: 1.13"
ModuleInfo "Author: hamZta, Suco-X, d-bug"
ModuleInfo "License: Public Domain"
ModuleInfo "Contact: d-bug@..."
ModuleInfo "Homepage: www.chaos-interactive.de"

ModuleInfo "History: 1.13 DesktopRatio hinzu"
ModuleInfo "History: 1.12 Macos 'identifer screen not found' bug behoben"
ModuleInfo "History: 1.11 Win32 Unterstützung mehrerer Desktops überarbeitet (danke klepto2 und Suco-X)"
ModuleInfo "History: 1.10 Unterstützung mehrerer Monitore für Win32 implementiert"
ModuleInfo "History: 1.09 Pixmap wird wieder konvertiert"
ModuleInfo "History: 1.08 Optionaler Flip und Pixmapformatierung bei DesktopPixmap implementiert"
ModuleInfo "History: 1.07 Unterstützung mehrerer Monitore für MacOS implementiert"
ModuleInfo "History: 1.06 'TPixmap not found' repariert"
ModuleInfo "History: 1.05 DesktopMouseX() bzw DesktopMouseY() für Win32"
ModuleInfo "History: 1.04 DesktopPixmap() für Win32"
ModuleInfo "History: 1.03 Dokumentation ist ab jetzt in deutsch"
ModuleInfo "History: 1.02 Scope von dbug. nach chaos. geändert"
ModuleInfo "History: 1.01 ReleaseDC eingefügt"
ModuleInfo "History: 1.00 Erster Release (16.05.2006)"



SuperStrict

Import brl.standardio
Import brl.pixmap
Import brl.linkedlist


?Win32 

	Import pub.win32

	Private 

		Const SM_CXVIRTUALSCREEN:Int = 78
		Const SM_CYVIRTUALSCREEN:Int = 79
		Const SM_CMONITORS:Int = 80
		Const SM_SAMEDISPLAYFORMAT:Int = 81
	
		Type TDisplay
			Global List:TList = New TList
			Field id:Int
			Field handle:Int
			Field x:Int
			Field y:Int
			Field width:Int
			Field height:Int
		End Type

		Type TRect
		   Field rLeft:Int
		   Field rTop:Int
		   Field rRight:Int
		   Field rBottom:Int
		End Type
		
		Extern "Win32"
			Function GetSystemMetrics:Int (nIndex:Int)"Win32"
			Function EnumDisplayMonitors:Int (hdc:Int, lprcClip:Byte Ptr, lpfnEnum:Byte Ptr, dwData:Byte Ptr)"Win32"
			Function GetCursorPos(lpPoint:Byte Ptr)"Win32" = "GetCursorPos@4"
			Function GetDIBits(hdc:Int, bitmap:Int, Start:Int, Num:Int, bits:Byte Ptr, lpbi:Byte Ptr, usage:Int)"Win32"
			Function GetWindowDC(hwnd:Int)"Win32"
			Function ReleaseDC(hwnd:Int, hdc:Int)"Win32"
		End Extern
		
		Function MonitorEnumProc:Byte (hMonitor:Int,hdcMonitor:Int,lprcMonitor:Byte Ptr,dwData:Int)
			Local tempRect:TRect = New TRect
			MemCopy(tempRect, lprcMonitor, SizeOf(tempRect))
			Local display:TDisplay = New TDisplay
			TDisplay.List.AddLast(display)
			display.id = TDisplay.List.Count()
			display.handle = hMonitor
			display.x = tempRect.rLeft
			display.y = tempRect.rTop
			display.width = tempRect.rRight - display.x
			display.height = tempRect.rBottom - display.y
			Return True
		End Function
		EnumDisplayMonitors (Null , Null , MonitorEnumProc , Null)
	
	Public 
?MacOS
	Import "macscreen.c"
	Private
		Extern
			Function CGDisplayCurrentMode:Byte Ptr(displayID:Byte Ptr)"MacOS"
			Function CGGetActiveDisplayList:Byte Ptr(kMaxDisplays:Int, display:Byte Ptr, numDisplays:Int Var)"MacOS"
			Function MACOS_GetWidth:Int(mode:Byte Ptr)"C"
			Function MACOS_GetHeight:Int(mode:Byte Ptr)"C"
			Function MACOS_GetBPP:Int(mode:Byte Ptr)"C"
			Function MACOS_GetHertz:Int(mode:Byte Ptr)"C"
		End Extern 
	Public
?Linux
	Import brl.graphics
? 



Rem
	bbdoc:		Aspekt-Ratio des Desktops (Monitors) abfragen
	returns:	AspektRatio als String
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td></td><td></td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopRatio:String (screen:Int=0)

			Function DAR:Int (a:Int, b:Int)
				Local fudge:Int = 0
				Local Result:Int
				If b mod a <= fudge
					Result = a
				Else
					Result = DAR (b, a mod b)
				EndIf
				Return Result
			End Function

	Local X:Int = DesktopWidth(screen)
	Local Y:Int = DesktopHeight(screen)
	Local Div:Int = DAR(X,Y)
	Local Result:String = String (X/Div) + ":" + String(Y/Div)
	Select Result
		Case "8:5" ; 	Return "16:10"
		Default ; 		Return Result
	End Select

End Function


Rem
	bbdoc:		Anzahl der Desktops (Monitore) abfragen
	returns:	Anzahl als Integer
	about:		<table>
							<tr><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>X</td><td>X</td><td></td></tr>
						</table>
End Rem

Function DesktopCount:Int () 

	?Win32
		Return GetSystemMetrics (SM_CMONITORS)
	?MacOS
		Local display:Byte Ptr[] = New Byte Ptr[1]
		Local iMode:Byte Ptr = Null
		Local iCount:Int
		CGGetActiveDisplayList 1, display, iCount
		Return iCount
	?Linux
		Return 0
	?

End Function 


							

Rem
	bbdoc:		X-Koordinate des Desktops (Monitors) abfragen
	returns:	X-koordinate als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td></td><td></td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopX:Int (screen:Int = 0) 
	If screen < 0 Then screen = 0
	?Win32
			For Local display:TDisplay = EachIn TDisplay.List
				If display.id = screen+1
					Return display.X
				EndIf
			Next
			Return 0
	?MacOS
		Return 0
	?Linux
		Return 0
	?
End Function 

Rem
	bbdoc:		Y-Koordinate des Desktops (Monitors) abfragen
	returns:	Y-koordinate als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td></td><td></td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopY:Int (screen:Int = 0) 
	If screen < 0 Then screen = 0
	?Win32
			For Local display:TDisplay = EachIn TDisplay.List
				If display.id = screen+1
					Return display.Y
				EndIf
			Next
			Return 0
	?MacOS
		Return 0
	?Linux
		Return 0
	?
End Function 


Rem
	bbdoc:		Breite des Desktops (Monitors) abfragen
	returns:	Breite als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>-1</td><td>Gesammtbreite aller Desktops (Monitore)</td><td>X</td><td></td><td></td></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td>X</td><td>X</td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td>X</td><td>X</td><td></td></tr>
						</table>
End Rem
Function DesktopWidth:Int (screen:Int=0) 
	Local width:Int,height:Int,depth:Int,hertz:Int
	GetDesktopMode (width, height, depth, hertz, screen)
	Return width
End Function 


Rem
	bbdoc:		Höhe des Desktops (Monitors) abfragen
	returns:	Höhe als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>-1</td><td>Gesammthöhe aller Desktops (Monitore)</td><td>X</td><td></td><td></td></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td>X</td><td>X</td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td>X</td><td>X</td><td></td></tr>
						</table>
End Rem
Function DesktopHeight:Int (screen:Int=0) 
	Local width:Int,height:Int,depth:Int,hertz:Int
	GetDesktopMode (width, height, depth, hertz, screen)
	Return height
End Function 

Rem
	bbdoc:		Tiefe des Desktops (Monitors) abfragen
	returns:	Tiefe als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td>X</td><td>X</td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td></td><td>X</td><td></td></tr>
						</table>
End Rem
Function DesktopDepth:Int (screen:Int=0) 
	Local width:Int,height:Int,depth:Int,hertz:Int
	GetDesktopMode (width, height, depth, hertz, screen)
	Return depth
End Function 

Rem
	bbdoc:		Wiederholrate des Desktops (Monitors) abfragen
	returns:	Wiederholrate als Integer
	about:		<table>
							<tr><th>Parameter</th><th>Wert</th><th>Beschreibung</th><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>screen</td><td>0</td><td>Primärer Desktop (Monitor)</td><td>X</td><td>X</td><td>X</td></tr>
							<tr><td>screen</td><td>1 - x</td><td>Sekundäre Desktops (Monitore)</td><td></td><td>X</td><td></td></tr>
						</table>
End Rem
Function DesktopHertz:Int (screen:Int=0) 
	Local width:Int,height:Int,depth:Int,hertz:Int
	GetDesktopMode (width, height, depth, hertz, screen)
	Return hertz
End Function 


Rem
	bbdoc:		Breite, Höhe, Tiefe und Wiederholrate des Desktops (Monitors) abfragen
	about:		Kompatibilität siehe DesktopWidth(), DesktopHeight(), DesktopDepth() und DesktopHertz()
End Rem
Function GetDesktopMode:Int (width:Int Var, height:Int Var, depth:Int Var, hertz:Int Var, screen:Int=0) 
	?Win32
		Local hwnd:Int = GetDesktopWindow()
		Local hdc:Int = GetDC(hwnd)
		If hdc = Null Then Return -1
		depth  = GetDeviceCaps(hdc, BITSPIXEL)
		hertz  = GetDeviceCaps(hdc, VREFRESH)
		ReleaseDC(hwnd,hdc)
		If screen = -1
			width = GetSystemMetrics (SM_CXVIRTUALSCREEN)
			height = GetSystemMetrics (SM_CYVIRTUALSCREEN)
		Else
			Local valid:Byte = True
			For Local display:TDisplay = EachIn TDisplay.List
				If display.id = screen+1
					width = display.width
					height = display.height
					Exit
				EndIf
			Next
		EndIf	
	?MacOS
		Local display:Byte Ptr[] = New Byte Ptr[screen+1]
		Local iMode:Byte Ptr = Null
		Local iCount:Int
		CGGetActiveDisplayList screen+1, display, iCount
		If (screen < iCount)
			iMode  = CGDisplayCurrentMode(display[screen])
		Else
			Throw " [DesktopExt] Screen '"+screen+"' does not exist!"
		End If
		width  = MACOS_GetWidth(iMode)
		height = MACOS_GetHeight(iMode)
		depth  = MACOS_GetBPP(iMode)
		hertz  = MACOS_GetHertz(iMode)
	?Linux
		CountGraphicsModes()
		GetGraphicsMode (0,width,height,depth,hertz)
	?
End Function 



Rem
	bbdoc:		Screenshot des Desktops in einer Pixmap erstellen
	returns:	Screenshot als TPixmap
	about:		<table>
							<tr><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopPixmap:TPixmap (flag:Byte = True) 

	'Original Funktion von Suco-X

	?Linux
		Return Null
	?MacOS
		Return Null
	?Win32
		Local hwnd:Int = GetDesktopWindow()
		If Not hwnd Return Null
		Local hdc:Int = GetWindowDC(hwnd)
		If Not hdc Return Null
		Local hdcmem:Int = CreateCompatibleDC(hdc)
     	If Not hdcmem Return Null
		Local info:BITMAPINFOHEADER = New BITMAPINFOHEADER
		info.biSize = SizeOf(info)
		info.biPlanes = 1
		info.biCompression = 0
		Local hertz:Int,depth:Int
		GetDesktopMode:Int (info.biWidth,info.biHeight,depth,hertz,-1)
		info.biBitCount = depth
		Local bmpmem:Int  = CreateCompatibleBitmap(hdc, info.biWidth, info.biHeight)
 		If (Not bmpmem) Or (Not SelectObject(hdcmem, bmpmem)) Return Null
		If Not BitBlt(hdcmem,0,0,info.biWidth,info.biHeight,hdc,0,0,ROP_SRCCOPY) Return Null
		Local out:TPixmap = CreatePixmap(info.biWidth, info.biHeight, PF_BGRA8888)
		If Not GetDIBits(hdcmem, bmpmem, 0, info.biHeight, out.PixelPtr(0,0), info, 0) Return Null
	      DeleteDC(hdcmem)
	      DeleteObject(bmpmem)
		ReleaseDC(hwnd, hdc)
		out = out.Convert(PF_BGR888) 'dumm gelaufen, man kann nicht direkt in dem Format grabben
		If flag = True out = YFlipPixmap(out)
		Return out
	?
End Function 


Rem
	bbdoc:		Globale Maus X-Koordinate abfragen
	returns:	X-Koordinate als Integer
	about:		<table>
							<tr><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopMouseX:Int () 
	?Linux
		Return 0
	?MacOS
		Return 0
	?Win32
		Local Coord:Int[2]
		GetCursorPos(Coord)
		Return Coord[0]
	?
End Function 


Rem
	bbdoc:		Globale Maus Y-Koordinate abfragen
	returns:	Y-Koordinate als Integer
	about:		<table>
							<tr><th>Windows</th><th>MacOSX</th><th>Linux</th></tr>
							<tr><td>X</td><td></td><td></td></tr>
						</table>
End Rem
Function DesktopMouseY:Int () 
	?Linux
		Return 0
	?MacOS
		Return 0
	?Win32
		Local Coord:Int[2]
		GetCursorPos(Coord)
		Return Coord[1]
	?
End Function