Page 2 of 3

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 7:24 pm
by idle
Just enumerate the windows and use printwindow
if you can get the zorder you could composite them back into an image
or just grab the window your interested in

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 10:38 pm
by electrochrisso
Another way might be to make the calculator window fully transparent for the screenshot, someone with good API knowledge may be able to help on this one.

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 12:33 am
by electrochrisso
Here is another idea, move the calculator just out of view of the desktop, take the screenshot, then move it back to its original position, there are so many ways to approach things in programming. :)

Code: Select all

UsePNGImageEncoder()

Procedure GetDesktopWindows()
  h = GetWindow_(GetDesktopWindow_(), #GW_CHILD)
  Repeat
    If IsWindowVisible_(h) = #True
      c$ = Space(999) : GetWindowText_(h, c$, 999)
      If c$ <> ""
        If c$ = "Calculator"
          ExamineDesktops()
          Protected WR.RECT
          GetWindowRect_(h, WR)
          sx = WR\Left
          wd = WR\Right - WR\Left
          ht = WR\Bottom - WR\Top
          MoveWindow_(h,DesktopWidth(0),WR\Top,wd,ht,#True)
          Delay (500)
          img = CreateImage(#PB_Any, DesktopWidth(0), DesktopHeight(0))
          dc = GetDC_(0)
          t = StartDrawing(ImageOutput(img))
          BitBlt_(t, 0, 0, DesktopWidth(0), DesktopHeight(0), dc, 0, 0, #SRCCOPY)
          StopDrawing()
          ReleaseDC_(0, dc)
          SaveImage(img, "C:\temp\test.png", #PB_ImagePlugin_PNG)
          Delay (500)
          MoveWindow_(h,sx,WR\Top,wd,ht,#True)
       EndIf
      EndIf
    EndIf
    h = GetWindow_(h, #GW_HWNDNEXT)
  Until h = 0
EndProcedure

GetDesktopWindows()

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 3:57 am
by American Ninja
Moving or changing the appearance of Calculator is *not* the answer, as it causes a visible change, and interrupts the user if he's working on it. A window can't just move when being clicked or typed on, so that's not the answer. Also, you can't move a maximized window, so that's not the answer. Recall that the foreground window may be maximized, and yet I still want to screenshot everything underneath it. Calculator was just an example, but in my first post I said the *foreground* window, whatever size or state that may be at the time.

I think idle's tip may be the answer, because PrintWindow can grab a window's image silently and without interruption. I'll look further into that avenue.

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 6:08 am
by netmaestro
You can use the PrintWindow api to have a window print its contents to a device context. Here I show you how to get the main background windows of your desktop drawn to an image, giving you the basic background. Simply do an EnumWindows to find the visible ones, have them add themselves to the image and ignore the window you don't want in the image. No hiding or flickering needed.

Code: Select all

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

Procedure enummer(hwnd, lparam)
  cn$ = Space(255)
  wn$ = Space(255)
  GetClassName_(hwnd, @cn$, 255)
  GetWindowText_(hwnd, @wn$, 255)
  If wn$ = "FolderView" And cn$ = "SysListView32"
    PokeI(lparam, hwnd)
    ProcedureReturn 0
  Else
    ProcedureReturn 1
  EndIf
EndProcedure

win.i = 0
EnumChildWindows_(GetDesktopWindow_(), @enummer(), @win)

If win
  ExamineDesktops()
  CreateImage(0, DesktopWidth(0), DesktopHeight(0), 24)
  hdc = StartDrawing(ImageOutput(0))
    PrintWindow_(win, hdc, 0)
  StopDrawing()
  w = ImageWidth(0)/2
  h = ImageHeight(0)/2
  ResizeImage(0, w,h)
  CreateImage(1, DesktopWidth(0), 30, 32|#PB_Image_Transparent)
  hdc = StartDrawing(ImageOutput(1))
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    PrintWindow_(FindWindow_("Shell_TrayWnd", #Null), hdc, 0)
  StopDrawing()
  ResizeImage(1, ImageWidth(1)/2, ImageHeight(1)/2)
  StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    DrawImage(ImageID(1),0,ImageHeight(0)-16)
  StopDrawing()
  OpenWindow(0,0,0,w,h,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ImageGadget(0,0,0,0,0,ImageID(0))
  Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
CloseLibrary(hLib)

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 8:22 am
by RASHAD
Hi

Code: Select all


ExamineDesktops()

Prototype.i ptPrintWindow(hWnd, hdc, flags)

OpenLibrary(1, "User32.dll")
PrintWindow.ptPrintWindow = GetFunction(1, "PrintWindow")

CreateImage(0, DesktopWidth(0), DesktopHeight(0), 32)
hWnd = FindWindow_("ProgMan", 0)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hdc = StartDrawing(ImageOutput(0))
  PrintWindow(hWnd, hdc, 0)
StopDrawing()
CreateImage(1, DesktopWidth(0), 30,32)
hdc = StartDrawing(ImageOutput(1))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  PrintWindow(FindWindow_("Shell_TrayWnd", #Null), hdc, 0)
StopDrawing()
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip )
  DrawImage(ImageID(1),0,DesktopHeight(0)-30)
StopDrawing()
FreeImage(1)

hWnd = GetTopWindow_(GetDesktopWindow_())

While hWnd
  hWnd = GetWindow_(hWnd,#GW_HWNDNEXT)
  If  IsWindowVisible_(hWnd)        
    WTitle$ = Space(128)
      GetWindowText_(hWnd,@WTitle$,128)
      If WTitle$ <> "Calculator"
         GetWindowRect_(hWnd,r.RECT)
           If r\left > 0 And r\right > 0
               CreateImage(1,r\right - r\left,r\bottom-r\top)
               hdc = StartDrawing(ImageOutput(1))
                PrintWindow(hWnd, hdc, 0)
               StopDrawing()
               Delay(50)
               StartDrawing(ImageOutput(0))
                DrawImage(ImageID(1),r\left,r\top)
               StopDrawing()
           EndIf
      EndIf 
   EndIf
 Wend
 

SaveImage(0,"e:\test2.bmp") 
CloseLibrary(1)


Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 10:16 am
by davido
Thanks NetMaestro and RASHAD.

Nice work.

Guess I'll learn a lot trying to figure how the magic works! :D

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 10:38 am
by American Ninja
Rashad, that's close, but two problems... the first is that my desktop has a gray background but it's black in the BMP screenshot, and second is if I replace "Calculator" with "Untitled - Notepad" and put a maximized Notepad window at the foreground, then this line crashes:

Code: Select all

CreateImage(1,r\right - r\left,r\bottom-r\top)
The error is that the image width must be >0. Remember, Calculator was just an example... the code must work with any size foreground window, such as when maximized. Thanks for getting me this far, though!!!

Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 3:23 pm
by RASHAD
- Fixed Z-Order of the captured windows
- No more dimensions restrictions
- Speed enhanced

Code: Select all

ExamineDesktops()
Dim hnd(0)

Prototype.i ptPrintWindow(hWnd, hdc, flags)
OpenLibrary(1, "User32.dll")
PrintWindow.ptPrintWindow = GetFunction(1, "PrintWindow")

CreateImage(0, DesktopWidth(0), DesktopHeight(0), 32)
hWnd = FindWindow_("ProgMan", 0)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hdc = StartDrawing(ImageOutput(0))
  PrintWindow(hWnd, hdc, 0)
StopDrawing()

hWnd = GetTopWindow_(GetDesktopWindow_())

While hWnd
  hWnd = GetWindow_(hWnd,#GW_HWNDNEXT)
  If  IsWindowVisible_(hWnd)
      x + 1
      ReDim hnd(x)
      hnd(x) = hWnd
   EndIf
 Wend
 
 For i = x  To 1 Step -1
      WTitle$ = Space(128)
      GetWindowText_(hnd(i),@WTitle$,128)
      If WTitle$ <> "Calculator" And hnd(i) <> FindWindow_("Shell_TrayWnd", #Null)
         GetWindowRect_(hnd(i),r.RECT)
         CreateImage(1,r\right - r\left,r\bottom-r\top,32)
         hdc = StartDrawing(ImageOutput(1))
          PrintWindow(hnd(i), hdc, 0)
         StopDrawing()
         StartDrawing(ImageOutput(0))
          DrawImage(ImageID(1),r\left,r\top)
         StopDrawing()
      EndIf
 Next
 
CreateImage(1, DesktopWidth(0), 30,32)
hdc = StartDrawing(ImageOutput(1))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  PrintWindow(FindWindow_("Shell_TrayWnd", #Null), hdc, 0)
StopDrawing()
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip )
  DrawImage(ImageID(1),0,DesktopHeight(0)-30)
StopDrawing()
FreeImage(1)

SaveImage(0,"e:\test2.bmp") 
CloseLibrary(1)


Re: Screenshot of desktop but not current window

Posted: Tue Jan 15, 2013 5:06 pm
by RASHAD
- Better logic
- Much faster

# 1 :

Code: Select all

ExamineDesktops()

Prototype.i ptPrintWindow(hWnd, hdc, flags)
OpenLibrary(1, "User32.dll")
PrintWindow.ptPrintWindow = GetFunction(1, "PrintWindow")

CreateImage(0, DesktopWidth(0), DesktopHeight(0), 32)
hWnd = FindWindow_("ProgMan", 0)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hdc = StartDrawing(ImageOutput(0))
  PrintWindow(hWnd, hdc, 0)
StopDrawing()

hWnd = GetTopWindow_(GetDesktopWindow_())
hWnd = GetWindow_(hWnd,#GW_HWNDLAST)

While hWnd
  hWnd = GetWindow_(hWnd,#GW_HWNDPREV)
  If  IsWindowVisible_(hWnd)        
    WTitle$ = Space(128)
      GetWindowText_(hWnd,@WTitle$,128)
      If WTitle$ <> "Calculator" And hWnd <> FindWindow_("Shell_TrayWnd", #Null)
         GetWindowRect_(hWnd,r.RECT)
               CreateImage(1,r\right - r\left,r\bottom-r\top)
               hdc = StartDrawing(ImageOutput(1))
                PrintWindow(hWnd, hdc, 0)
               StopDrawing()
               Delay(50)
               StartDrawing(ImageOutput(0))
                DrawImage(ImageID(1),r\left,r\top)
               StopDrawing()
      EndIf 
   EndIf
 Wend

CreateImage(1, DesktopWidth(0), 30,32)
hdc = StartDrawing(ImageOutput(1))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  PrintWindow(FindWindow_("Shell_TrayWnd", #Null), hdc, 0)
StopDrawing()
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip )
  DrawImage(ImageID(1),0,DesktopHeight(0)-30)
StopDrawing()
FreeImage(1)
 

SaveImage(0,"e:\test2.bmp") 
CloseLibrary(1)

# 2 :

Code: Select all

#CAPTUREBLT  = $40000000

ExamineDesktops()

hWnd = FindWindow_("ProgMan", 0)
hWnd = GetWindow_(hWnd, #GW_CHILD)
hWnd = GetWindow_(hWnd, #GW_CHILD)

hBitmap = CreateImage(0, DesktopWidth(0), DesktopHeight(0),32)
hdc = StartDrawing(ImageOutput(0))
     SelectObject_(hdc, hBitmap)
     BitBlt_(hdc, 0, 0,DesktopWidth(0), DesktopHeight(0), GetWindowDC_(hWnd), 0, 0, #SRCCOPY | #CAPTUREBLT)
StopDrawing()

hWnd = GetTopWindow_(GetDesktopWindow_())
hWnd = GetWindow_(hWnd,#GW_HWNDLAST)

While hWnd
  hWnd = GetWindow_(hWnd,#GW_HWNDPREV)
  If  IsWindowVisible_(hWnd)        
    WTitle$ = Space(128)
      GetWindowText_(hWnd,@WTitle$,128)
      If WTitle$ <> "Calculator" And hWnd <> FindWindow_("Shell_TrayWnd", #Null)
           GetWindowRect_(hWnd,r.RECT)
               hBitmap = CreateImage(1,r\right-r\left,r\bottom-r\top ,32)
               hdc = StartDrawing(ImageOutput(1))
                     SelectObject_(hdc, hBitmap)
                     BitBlt_(hdc, 0, 0,r\right-r\left,r\bottom-r\top , GetWindowDC_(hWnd), 0,0, #SRCCOPY | #CAPTUREBLT)
               StopDrawing()
               StartDrawing(ImageOutput(0))
                DrawImage(ImageID(1),r\left,r\top)
               StopDrawing()
      EndIf 
   EndIf
 Wend
 
 hWnd = FindWindow_("Shell_TrayWnd", #Null)

hBitmap = CreateImage(1, DesktopWidth(0), 30,32)
hdc = StartDrawing(ImageOutput(1))
   SelectObject_(hdc, hBitmap)
   BitBlt_(hdc, 0, 0,DesktopWidth(0), 30, GetWindowDC_(hWnd), 0, 0, #SRCCOPY| #CAPTUREBLT)
StopDrawing()

StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip )
  DrawImage(ImageID(1),0,DesktopHeight(0)-30)
StopDrawing()
FreeImage(1)
 

SaveImage(0,"e:\test2.bmp") 


Re: Screenshot of desktop but not current window

Posted: Wed Jan 16, 2013 1:20 am
by American Ninja
RASHAD wrote:- Better logic
- Much faster

# 1 :
Your #1 code seems okay but still shows my desktop as being black instead of gray. Looks like some sort of alpha issue, or bitdepth issue??? Thanks for persevering for me!!! :mrgreen:

Re: Screenshot of desktop but not current window

Posted: Wed Jan 16, 2013 1:56 am
by IdeasVacuum
Your #1 code seems okay but still shows my desktop as being black instead of gray. Looks like some sort of alpha issue, or bitdepth issue??? Thanks for persevering for me!!!
If the app is only on your desktop and your desktop always has a grey wallpaper, then use the Box() command to paint the image grey before the window images are added to it. Otherwise, you will need to find the active wallpaper and draw that on your image first.

Re: Screenshot of desktop but not current window

Posted: Wed Jan 16, 2013 6:17 am
by RASHAD
The problem is with DrawImage() which is used for merging several images

Tested with PB 5.0 x86 - Win 7 x64
- No problem with FireFox maximized

Code: Select all

#CAPTUREBLT  = $40000000

ExamineDesktops()

hWnd = FindWindow_("ProgMan", 0)

hBitmap = CreateImage(0, DesktopWidth(0), DesktopHeight(0),32)
hdc = StartDrawing(ImageOutput(0))
     SelectObject_(hdc, hBitmap)
     BitBlt_(hdc, 0, 0,DesktopWidth(0), DesktopHeight(0), GetWindowDC_(hWnd), 0, 0, #SRCCOPY | #CAPTUREBLT)
StopDrawing()

hWnd = GetTopWindow_(GetDesktopWindow_())
hWnd = GetWindow_(hWnd,#GW_HWNDLAST)

While hWnd
  hWnd = GetWindow_(hWnd,#GW_HWNDPREV)
  If  IsWindowVisible_(hWnd)       
    WTitle$ = Space(128)
      GetWindowText_(hWnd,@WTitle$,128)
      If WTitle$ <> "Calculator"And WTitle$ <> "Start" And hWnd <> FindWindow_("Shell_TrayWnd", #Null)
           GetWindowRect_(hWnd,r.RECT)
               hBitmap = CreateImage(1,r\right-r\left,r\bottom-r\top ,32)
               hdc = StartDrawing(ImageOutput(1))
                     SelectObject_(hdc, hBitmap)
                     BitBlt_(hdc, 0, 0,r\right-r\left,r\bottom-r\top , GetWindowDC_(hWnd), 0,0, #SRCCOPY | #CAPTUREBLT)
               StopDrawing()
               StartDrawing(ImageOutput(0))
                ;DrawingMode(#PB_2DDrawing_AlphaClip  )
                DrawImage(ImageID(1),r\left,r\top)
               StopDrawing()
      EndIf
   EndIf
 Wend
;  
hWnd = FindWindow_("Shell_TrayWnd", #Null)

hBitmap = CreateImage(1, DesktopWidth(0), 30,32)
hdc = StartDrawing(ImageOutput(1))
   SelectObject_(hdc, hBitmap)
   BitBlt_(hdc, 0, 0,DesktopWidth(0), 30, GetWindowDC_(hWnd), 0, 0, #SRCCOPY| #CAPTUREBLT)
StopDrawing()

StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_AlphaClip  )
  DrawAlphaImage(ImageID(1),0,DesktopHeight(0)-30,255)
StopDrawing() 

SaveImage(0,"e:\test2.bmp") 

Edit :Updated

Re: Screenshot of desktop but not current window

Posted: Wed Jan 16, 2013 6:41 am
by American Ninja
Still not quite right... I now get an error of "Line: 22 - Image 'Width' is too small, should be > 0" for this line:

Code: Select all

hBitmap = CreateImage(1,r\right-r\left,r\bottom-r\top ,32)
It returns 0 for both width and height of a window that isn't seen, so it seems to be picking up invisible windows. I tried to use "IsWindowVisible_(hwnd)" to trap it, but it still fails. Looking into it.....

And no, it doesn't show all windows here anyway. Just the foreground one, which is the opposite of the goal. The code you had above was better, because it worked except for the desktop color.

Re: Screenshot of desktop but not current window

Posted: Wed Jan 16, 2013 8:38 am
by RASHAD
Previous post updated