Page 1 of 1

Capturing windows (inactiv, too)

Posted: Mon Dec 24, 2007 6:45 am
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




Posted: Mon Dec 24, 2007 8:11 am
by electrochrisso
Could come in handy! Thanks. :)

Posted: Mon Dec 24, 2007 12:19 pm
by ABBKlaus
nice, but eats GDI-Objects :wink:

Posted: Mon Dec 24, 2007 12:46 pm
by gnozal
Shouldn't it be

Code: Select all

DeleteDC_(hdcMem) 
instead of

Code: Select all

DeleteObject_(hdcMem)
?

Posted: Mon Dec 24, 2007 2:28 pm
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.

Posted: Mon Dec 24, 2007 3:21 pm
by Hroudtwolf
Yes. Your'e right.

Best regards and merry christmas!

Wolf

Posted: Mon Dec 24, 2007 3:26 pm
by Dare
Thanks for the pointers, tricks and tips here. (Love the way things develop on these boards).

Great new year to all!

Posted: Wed Dec 26, 2007 3:53 am
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.

Posted: Wed Dec 26, 2007 3:58 am
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.

Posted: Wed Dec 26, 2007 10:02 pm
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

Posted: Wed Dec 26, 2007 10:09 pm
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.

Posted: Wed Dec 26, 2007 10:40 pm
by Psychophanta
:oops: Sorry, i didn't watch that section. :roll:

Posted: Wed Dec 26, 2007 11:56 pm
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.

Posted: Fri Dec 28, 2007 11:51 am
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

Posted: Sat Dec 29, 2007 4:39 am
by yrreti
Thank you ABBKlaus for the code.
Yours works on my system.