Capturing windows (inactiv, too)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Capturing windows (inactiv, too)

Post by Hroudtwolf »

Hi,

This code demonstrates how to capture windows, and also inactive windows on windowsXP.

Best regards

Wolf

Code: Select all

; PureBasic-Lounge.de
; Author: Hroudtwolf
; Date: 04. November 2007
; OS: Windows
; Demo: No


Prototype.l            pPrintWindow(hWnd.l, hDc.l, lFlags.l)
Define   .l            hLib         = OpenLibrary(#PB_Any , "user32.dll")
Define   .pPrintWindow PrintWindow_ = GetFunction(hLib , "PrintWindow")


Procedure CreateWndSnapshot (hWnd.l)
   Protected hdc     .l     = GetWindowDC_(hWnd)
   Protected RC      .RECT
   Protected hBitmap .l
   Shared    PrintWindow_
   
   If Not hdc
      ProcedureReturn #Null
   EndIf
   hdcMem = CreateCompatibleDC_(hdc)
   If Not hdcMem
      ProcedureReturn #Null
   EndIf
   
   GetWindowRect_(hWnd, RC)
   hBitmap = CreateCompatibleBitmap_(hdc, RC\right , RC\bottom)
   If Not hBitmap
      ProcedureReturn #Null
   EndIf
   
   SelectObject_(hdcMem, hBitmap)
   PrintWindow_(hwnd, hdcMem, 0)
   DeleteObject_(hdcMem)

    ProcedureReturn hBitmap
EndProcedure

If OpenWindow(0, 0, 0, 1024 , 30, "Window in a box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))

   ImageGadget(0,  0, 0, 1024 , 30, CreateWndSnapshot (FindWindow_("Shell_TrayWnd", #Null)))


 Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf



User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Post by electrochrisso »

Could come in handy! Thanks. :)
PureBasic! Purely the best 8)
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

nice, but eats GDI-Objects :wink:
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Shouldn't it be

Code: Select all

DeleteDC_(hdcMem) 
instead of

Code: Select all

DeleteObject_(hdcMem)
?
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Yes, DeleteDC for hdcmem, and you miss:

Code: Select all

ReleaseDC_(hwnd, hdc)
which is the other leak. Also, when a programmer calls this procedure, he's got to remember to do a DeleteObject_() on every bitmap returned as soon as he's finished with it, or it's a huge leak.
BERESHEIT
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

Yes. Your'e right.

Best regards and merry christmas!

Wolf
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Thanks for the pointers, tricks and tips here. (Love the way things develop on these boards).

Great new year to all!
Dare2 cut down to size
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Post by yrreti »

I have a question:
I ran your code once and it 'worked ok'. Then I ran the same code later and it
always errors out on the

Code: Select all

PrintWindow_(hwnd, hdcMem, 0)
line. I tried repasting your code again and it still errors on that line.

The error is :
Line 33:PrintWindow_() is not a function, array, macro or linked list.

The fact that it ran ok the first time bugs me? Any ideas?
Thanks for your time.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

The PrintWindow api is not available directly in PureBasic, like so many other api commands are. You must call the function from the dll, e.g. using a prototype as htroudwolf has done, or CallFunction, etc. etc. Because unfortunately PrintWindow_() really isn't a function, array, macro or linked list.
BERESHEIT
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

netmaestro wrote:The PrintWindow api is not available directly in PureBasic, like so many other api commands are. You must call the function from the dll, e.g. using a prototype as htroudwolf has done, or CallFunction, etc. etc. Because unfortunately PrintWindow_() really isn't a function, array, macro or linked list.
Here it works without any problem :o
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Code: Select all

Prototype.l            pPrintWindow(hWnd.l, hDc.l, lFlags.l) 
Define   .l            hLib         = OpenLibrary(#PB_Any , "user32.dll") 
Define   .pPrintWindow PrintWindow_ = GetFunction(hLib , "PrintWindow") 
As long as this section is intact, it should work everywhere*. Without it, the command won't be recognized.

*Included in Windows XP and Windows Server 2003. Windows 95/98/Me: Unsupported.
BERESHEIT
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

:oops: Sorry, i didn't watch that section. :roll:
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Post by yrreti »

Thanks netmaestro for your reply and also the good explanation. The code you displayed is exactly what is
listed. The puzzling thing is that it worked the first time I ran it. I just can't understand why it doesn't work now.
I was beginning to suspect my user32.dll got messed up and so I looked into it and found the PrintWindow intact.
I even tried a different user32.dll and it still fails? I'm using XP Pro. Anyway thanks for your input.
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

here is my version : (without GDI-leaks)

Code: Select all

; PureBasic-Lounge.de 
; Author: Hroudtwolf 
; Date: 04. November 2007 
; OS: Windows 
; Demo: No 

Prototype.l pPrintWindow(hWnd.l, hDc.l, lFlags.l) 
Global hLib.l = OpenLibrary(#PB_Any , "user32.dll") 
Global PrintWindow_.pPrintWindow = GetFunction(hLib , "PrintWindow") 

Procedure CreateWndSnapshot (hWnd.l,Image.l=#PB_Any) 
   Protected hdc     .l     = GetWindowDC_(hWnd)
   Protected RC      .RECT
   Protected res     .l
   Protected Img     .l
   Protected DC      .l
   
   If Not hdc
     ProcedureReturn #Null
   EndIf
   
   If GetWindowRect_(hWnd, RC) 
     Res=CreateImage(Image,RC\right-RC\left,RC\bottom-RC\top,#PB_Image_DisplayFormat)
     If Image=#PB_Any
       Img=Res
     Else
       Img=Image
     EndIf
     If Res
       DC=StartDrawing(ImageOutput(Img))
       PrintWindow_(hwnd, DC, 0)
       StopDrawing()
     EndIf
   EndIf
   
   If hdc
     ReleaseDC_(hWnd,hdc)
   EndIf
   
   If Image=#PB_Any
     ProcedureReturn Img
   Else
     ProcedureReturn Res
   EndIf
EndProcedure 

If OpenWindow(0, 0, 0, 1024 , 30, "Window in a box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 

   ImageGadget(0,  0, 0, 1024 , 30, 0) 
   
   If CreateWndSnapshot(FindWindow_("Shell_TrayWnd", #Null),0)
     SetGadgetState(0,ImageID(0))
   EndIf
   
 Repeat
   Event=WaitWindowEvent(100)
   
   If Event=0
     If CreateWndSnapshot(FindWindow_("Shell_TrayWnd", #Null),0)
       SetGadgetState(0,ImageID(0))
     EndIf
   EndIf
   
 Until Event = #PB_Event_CloseWindow 
EndIf
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Post by yrreti »

Thank you ABBKlaus for the code.
Yours works on my system.
Post Reply