[bb] Capture Screen functions by markcw [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:43

Previous topic - Next topic

BlitzBot

Title : Capture Screen functions
Author : markcw
Posted : 1+ years ago

Description : I was looking at how to use the clipboard in blitz3d (using the win32 api) and found some PB code to capture the screen and send it to the clipboard.

edit: found some more code on the PB forum that extended this function, it used GetSystemMetrics (for the desktop size) which was better than GetDeviceCaps.

You need to have a file named "User32.decls" in your "userlibs" folder with these declared.
.lib "User32.dll"

; Window Functions
Api_GetClientRect%(hWnd,lpRect*):"GetClientRect"
Api_GetDesktopWindow%():"GetDesktopWindow"
Api_GetForegroundWindow%():"GetForegroundWindow"
Api_GetWindowRect%(hWnd,lpRect*):"GetWindowRect"
; Clipboard Functions
Api_CloseClipboard%():"CloseClipboard"
Api_EmptyClipboard%():"EmptyClipboard"
Api_GetClipboardData%(uFormat):"GetClipboardData"
Api_IsClipboardFormatAvailable%(format):"IsClipboardFormatAvailable"
Api_OpenClipboard%(hwnd):"OpenClipboard"
Api_SetClipboardData%(uFormat,hData):"SetClipboardData"
; Coordinate Space and Transformation Functions
Api_ClientToScreen%(hWnd,lpPoint*):"ClientToScreen"
; Device Context Functions
Api_GetDC%(hWnd):"GetDC"
Api_ReleaseDC%(hwnd,hdc):"ReleaseDC"
; Accessibility Functions
Api_GetSystemMetrics%(nIndex):"GetSystemMetrics"

And a file named "Gdi32.decls" in the "userlibs" folder with these declared.
.lib "Gdi32.dll"

; Bitmap Functions
Api_BitBlt%(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop):"BitBlt"
Api_CreateCompatibleBitmap%(hdc,nWidth,nHeight):"CreateCompatibleBitmap"
Api_GetPixel%(hdc,nXPos,nYPos):"GetPixel"
Api_SetPixel%(hdc,X,Y,crColor):"SetPixel"
; Device Context Functions
Api_CreateCompatibleDC%(hdc):"CreateCompatibleDC"
Api_CreateDC%(lpszDriver$,lpszDevice$,lpszOutput$,lpInitData*):"CreateDCA"
Api_DeleteDC%(hdc):"DeleteDC"
Api_DeleteObject%(hObject):"DeleteObject"
Api_GetDeviceCaps%(hdc,nIndex):"GetDeviceCaps"
Api_GetObject%(hgdiobj,cbBuffer,lpvObject*):"GetObjectA"
Api_SelectObject%(hdc,hgdiobj):"SelectObject"

Or you can use the <a href="codearcsbcfe.html?code=1179" target="_blank">user32.dll decls</a> and <a href="codearcs3907-2.html?code=1181" target="_blank">gdi32.dll decls</a>.

The CaptureScreenArea function. [/i]

Code :
Code (blitzbasic) Select
;Capture Screen Area function, by markcw on 14 Jul 06

Graphics3D 320,240,0,2
SetBuffer BackBuffer()

initime=MilliSecs()

While Not KeyHit(1)

 If done=0 And MilliSecs()>initime+50 ;wait for text info
  done=1 : CaptureScreenArea(0,0,320,240) ;x,y,width,height
 EndIf

 Cls
 Text 0,0,"OK, paste the current clipboard data"
 Text 0,12,"to whatever program you use to see"
 Text 0,24,"the results of the screen capture."
 Text 0,36,"done="+done+" initime="+initime

Flip
Wend

Function CaptureScreenArea(sx,sy,swidth,sheight)
 ;Capture a given screen area to the clipboard
 ;From PureBasic CodeArchiv source, by wayne1 on 30/1/2002

 Local hdcSrc,hdcDst,hbmp,hold

 hdcSrc=Api_GetDC(0) ;hwnd
 hdcDst=Api_CreateCompatibleDC(hdcSrc) ;hdc
 hbmp=Api_CreateCompatibleBitmap(hdcSrc,swidth,sheight) ;hdc,width,height
 hold=Api_SelectObject(hdcDst,hbmp) ;hdc,hobject[bitmap]
 Api_BitBlt(hdcDst,0,0,swidth,sheight,hdcSrc,sx,sy,$00CC0020) ;SrcCopy
 Api_SelectObject(hdcDst,hold) ;restore old to dc
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(2,hbmp) ;CF_Bitmap,hdata[bitmap]
  Api_CloseClipboard()
 EndIf
 Api_ReleaseDC(0,hdcSrc) ;hwnd,hdc
 Api_DeleteDC(hdcDst) ;hdc

End Function


Comments :


markcw(Posted 1+ years ago)

 A CaptureDesktop function, which uses the CaptureScreenArea function.
;Capture Desktop function, by markcw on 16 Jul 06

Graphics3D 320,240,0,2
SetBuffer BackBuffer()

initime=MilliSecs()

While Not KeyHit(1)

 If done=0 And MilliSecs()>initime+50 ;wait for text info
  done=1 : CaptureDesktop()
 EndIf

 Cls
 Text 0,0,"OK, paste the current clipboard data"
 Text 0,12,"to whatever program you use to see"
 Text 0,24,"the results of the screen capture."
 Text 0,36,"done="+done+" initime="+initime

Flip
Wend

Function CaptureDesktop()
 ;Capture the entire desktop area to the clipboard
 ;From PureBasic Forum source, by Droopy on 18/10/2005

 Local dwidth,dheight

 dwidth=Api_GetSystemMetrics(0) ;SM_CXScreen
 dheight=Api_GetSystemMetrics(1) ;SM_CYScreen
 CaptureScreenArea(0,0,dwidth,dheight) ;x,y,width,height

End Function

Function CaptureScreenArea(sx,sy,swidth,sheight)
 ;Capture a given screen area to the clipboard
 ;From PureBasic CodeArchiv source, by wayne1 on 30/1/2002

 Local hdcSrc,hdcDst,hbmp,hold

 hdcSrc=Api_GetDC(0) ;hwnd
 hdcDst=Api_CreateCompatibleDC(hdcSrc) ;hdc
 hbmp=Api_CreateCompatibleBitmap(hdcSrc,swidth,sheight) ;hdc,width,height
 hold=Api_SelectObject(hdcDst,hbmp) ;hdc,hobject[bitmap]
 Api_BitBlt(hdcDst,0,0,swidth,sheight,hdcSrc,sx,sy,$00CC0020) ;SrcCopy
 Api_SelectObject(hdcDst,hold) ;restore old to dc
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(2,hbmp) ;CF_Bitmap,hdata[bitmap]
  Api_CloseClipboard()
 EndIf
 Api_ReleaseDC(0,hdcSrc) ;hwnd,hdc
 Api_DeleteDC(hdcDst) ;hdc

End Function



markcw(Posted 1+ years ago)

 A CaptureWindow function, which also uses the CaptureScreenArea function.;Capture Window function, by markcw on 15 Jul 06

Graphics3D 320,240,0,2
SetBuffer BackBuffer()

initime=MilliSecs()

While Not KeyHit(1)

 If done=0 And MilliSecs()>initime+50 ;wait for text info
  done=1 : CaptureWindow()
 EndIf

 Cls
 Text 0,0,"OK, paste the current clipboard data"
 Text 0,12,"to whatever program you use to see"
 Text 0,24,"the results of the screen capture."
 Text 0,36,"done="+done+" initime="+initime

Flip
Wend

Function CaptureWindow()
 ;Capture the entire window area to the clipboard
 ;From PureBasic Forum source, by Droopy on 18/10/2005

 Local hwnd,prect,rx,ry,rwidth,rheight

 hwnd=Api_GetForegroundWindow()
 If hwnd ;window valid
  prect=CreateBank(16) ;bank structure
  Api_GetWindowRect(hwnd,prect) ;hwnd,rect[left,top,right,bottom]
  rx=PeekInt(prect,0) ;rect left
  ry=PeekInt(prect,4) ;rect top
  rwidth=PeekInt(prect,8)-PeekInt(prect,0) ;rect right-left
  rheight=PeekInt(prect,12)-PeekInt(prect,4) ;rect bottom-top
  CaptureScreenArea(rx,ry,rwidth,rheight) ;x,y,width,height
  FreeBank prect ;free from memory
 EndIf

End Function

Function CaptureScreenArea(sx,sy,swidth,sheight)
 ;Capture a given screen area to the clipboard
 ;From PureBasic CodeArchiv source, by wayne1 on 30/1/2002

 Local hdcSrc,hdcDst,hbmp,hold

 hdcSrc=Api_GetDC(0) ;hwnd
 hdcDst=Api_CreateCompatibleDC(hdcSrc) ;hdc
 hbmp=Api_CreateCompatibleBitmap(hdcSrc,swidth,sheight) ;hdc,width,height
 hold=Api_SelectObject(hdcDst,hbmp) ;hdc,hobject[bitmap]
 Api_BitBlt(hdcDst,0,0,swidth,sheight,hdcSrc,sx,sy,$00CC0020) ;SrcCopy
 Api_SelectObject(hdcDst,hold) ;restore old to dc
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(2,hbmp) ;CF_Bitmap,hdata[bitmap]
  Api_CloseClipboard()
 EndIf
 Api_ReleaseDC(0,hdcSrc) ;hwnd,hdc
 Api_DeleteDC(hdcDst) ;hdc

End Function



markcw(Posted 1+ years ago)

 A CaptureClient function, again using the CaptureScreenArea function.;Capture Client function, by markcw on 16 Jul 06

Graphics3D 320,240,0,2
SetBuffer BackBuffer()

initime=MilliSecs()

While Not KeyHit(1)

 If done=0 And MilliSecs()>initime+50 ;wait for text info
  done=1 : CaptureClient()
 EndIf

 Cls
 Text 0,0,"OK, paste the current clipboard data"
 Text 0,12,"to whatever program you use to see"
 Text 0,24,"the results of the screen capture."
 Text 0,36,"done="+done+" initime="+initime

Flip
Wend

Function CaptureClient()
 ;Capture the entire client area to the clipboard
 ;From PureBasic CodeArchiv source, by Edwin Knoppert on 24/11/2003

 Local hwnd,prect,rx,ry,rwidth,rheight

 hwnd=Api_GetForegroundWindow()
 If hwnd ;window valid
  prect=CreateBank(16) ;bank structure
  Api_GetClientRect(hwnd,prect) ;hwnd,rect[left,top,right,bottom]
  Api_ClientToScreen(hwnd,prect) ;hwnd,point[x,y]
  rx=PeekInt(prect,0) ;point x
  ry=PeekInt(prect,4) ;point y
  rwidth=PeekInt(prect,8) ;rect right
  rheight=PeekInt(prect,12) ;rect bottom
  CaptureScreenArea(rx,ry,rwidth,rheight) ;x,y,width,height
  FreeBank prect ;free from memory
 EndIf

End Function

Function CaptureScreenArea(sx,sy,swidth,sheight)
 ;Capture a given screen area to the clipboard
 ;From PureBasic CodeArchiv source, by wayne1 on 30/1/2002

 Local hdcSrc,hdcDst,hbmp,hold

 hdcSrc=Api_GetDC(0) ;hwnd
 hdcDst=Api_CreateCompatibleDC(hdcSrc) ;hdc
 hbmp=Api_CreateCompatibleBitmap(hdcSrc,swidth,sheight) ;hdc,width,height
 hold=Api_SelectObject(hdcDst,hbmp) ;hdc,hobject[bitmap]
 Api_BitBlt(hdcDst,0,0,swidth,sheight,hdcSrc,sx,sy,$00CC0020) ;SrcCopy
 Api_SelectObject(hdcDst,hold) ;restore old to dc
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(2,hbmp) ;CF_Bitmap,hdata[bitmap]
  Api_CloseClipboard()
 EndIf
 Api_ReleaseDC(0,hdcSrc) ;hwnd,hdc
 Api_DeleteDC(hdcDst) ;hdc

End Function



markcw(Posted 1+ years ago)

 A CaptureClientArea function, like the CaptureClient function except lets you capture a given area, ie. an image.;Capture Client Area function, by markcw on 16 Jul 06

Graphics3D 320,240,0,2
SetBuffer BackBuffer()

image=CreateImage(128,128) ;new image
For y=0 To ImageHeight(image)-1
 For x=0 To ImageWidth(image)-1
  rgba=y+(y*256)+(x*256^2) ;gradient color
  WritePixel x,y,rgba,ImageBuffer(image)
 Next
Next

initime=MilliSecs()

While Not KeyHit(1)

 If done=0 And MilliSecs()>initime+50 ;wait for text info
  done=1 : CaptureClientArea(64,64,ImageWidth(image),ImageHeight(image))
 EndIf

 Cls
 DrawImage image,64,64 ;draw the image

 Text 0,0,"OK, paste the current clipboard data"
 Text 0,12,"to whatever program you use to see"
 Text 0,24,"the results of the screen capture."
 Text 0,36,"done="+done+" initime="+initime

Flip
Wend

Function CaptureClientArea(cx,cy,cwidth,cheight)
 ;Capture a given client area to the clipboard
 ;From PureBasic CodeArchiv source, by Edwin Knoppert on 24/11/2003

 Local hwnd,ppoint,px,py

 hwnd=Api_GetForegroundWindow()
 If hwnd ;window valid
  ppoint=CreateBank(8) ;bank structure
  Api_ClientToScreen(hwnd,ppoint) ;hwnd,point[x,y]
  px=PeekInt(ppoint,0) ;point x
  py=PeekInt(ppoint,4) ;point y
  CaptureScreenArea(px+cx,py+cy,cwidth,cheight) ;x,y,width,height
  FreeBank ppoint ;free from memory
 EndIf

End Function

Function CaptureScreenArea(sx,sy,swidth,sheight)
 ;Capture a given screen area to the clipboard
 ;From PureBasic CodeArchiv source, by wayne1 on 30/1/2002

 Local hdcSrc,hdcDst,hbmp,hold

 hdcSrc=Api_GetDC(0) ;hwnd
 hdcDst=Api_CreateCompatibleDC(hdcSrc) ;hdc
 hbmp=Api_CreateCompatibleBitmap(hdcSrc,swidth,sheight) ;hdc,width,height
 hold=Api_SelectObject(hdcDst,hbmp) ;hdc,hobject[bitmap]
 Api_BitBlt(hdcDst,0,0,swidth,sheight,hdcSrc,sx,sy,$00CC0020) ;SrcCopy
 Api_SelectObject(hdcDst,hold) ;restore old to dc
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(2,hbmp) ;CF_Bitmap,hdata[bitmap]
  Api_CloseClipboard()
 EndIf
 Api_ReleaseDC(0,hdcSrc) ;hwnd,hdc
 Api_DeleteDC(hdcDst) ;hdc

End Function



Wayne(Posted 1+ years ago)

 Right on Muk, good stuff !


markcw(Posted 1+ years ago)

 Thanks Wayne. I am going to see if i can copy a FreeImage bitmap directly now.


markcw(Posted 1+ years ago)

 just updated these examples to use the "Api_" prefix so there are no functions of the same name and so you can tell an api function straight away.Also, i changed to using Api_GetDC instead of Api_CreateDC because it does the same thing and is simpler to use.


Wayne(Posted 1+ years ago)

 I would of thought create would be functionaly differet from get. hmm


markcw(Posted 1+ years ago)

 well it's instead of creating a dc you just get an existing one, when you call getdc(0) it gets the display/desktop window, both can be used afaik.


markcw(Posted 1+ years ago)

 ok, i updated this code again. it doesn't really make much difference, but apparently you're supposed to put/reselect a dc's original dummy object back before deleting the dc.also, there was no need to delete the bitmap object as the clipboard uses it, i thought it made a copy but it just becomes the new owner.


schilcote(Posted 1+ years ago)

 Umm... CaptureDesktop doesn't work for me.


markcw(Posted 1+ years ago)

 It might be because the CaptureWindow/Client/ClientArea functions use Api_GetForegroundWindow to get the window handle which is not as reliable as using Api_FindWindow as there may be another foreground/active window. In order to use Api_FindWindow you need the define the Blitz app class (different in B+) and title, like so. Edit: SystemProperty("AppHWND") does the same thing as FindWindow..lib "User32.dll"
Api_FindWindow%(classname$, windowname$):"FindWindowA"
; Const class$="GX_WIN32_CLASS" ;BlitzPlus 1.11
; Const class$="BLITZMAX_WINDOW_CLASS" ;BlitzPlus 1.34
Const class$="Blitz Runtime Class" ;Blitz3D, app class
Const title$ = "My Blitz Window" ;app title

AppTitle title$
hwnd = Api_FindWindow(class$, title$)
As for CaptureDesktop not working I can only assume that Api_GetDC(0) isn't working for some reason. [/i]