Screenshot of desktop but not current window

Just starting out? Need help? Post your questions and find answers here.
User avatar
idle
Always Here
Always Here
Posts: 6150
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Screenshot of desktop but not current window

Post 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
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Screenshot of desktop but not current window

Post 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.
PureBasic! Purely the best 8)
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Screenshot of desktop but not current window

Post 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()
PureBasic! Purely the best 8)
American Ninja
User
User
Posts: 24
Joined: Mon Jan 14, 2013 8:01 am

Re: Screenshot of desktop but not current window

Post 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.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Screenshot of desktop but not current window

Post 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)
BERESHEIT
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5022
Joined: Sun Apr 12, 2009 6:27 am

Re: Screenshot of desktop but not current window

Post 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)

Egypt my love
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Screenshot of desktop but not current window

Post by davido »

Thanks NetMaestro and RASHAD.

Nice work.

Guess I'll learn a lot trying to figure how the magic works! :D
DE AA EB
American Ninja
User
User
Posts: 24
Joined: Mon Jan 14, 2013 8:01 am

Re: Screenshot of desktop but not current window

Post 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!!!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5022
Joined: Sun Apr 12, 2009 6:27 am

Re: Screenshot of desktop but not current window

Post 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)

Egypt my love
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5022
Joined: Sun Apr 12, 2009 6:27 am

Re: Screenshot of desktop but not current window

Post 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") 

Egypt my love
American Ninja
User
User
Posts: 24
Joined: Mon Jan 14, 2013 8:01 am

Re: Screenshot of desktop but not current window

Post 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:
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Screenshot of desktop but not current window

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5022
Joined: Sun Apr 12, 2009 6:27 am

Re: Screenshot of desktop but not current window

Post 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
Last edited by RASHAD on Wed Jan 16, 2013 8:37 am, edited 1 time in total.
Egypt my love
American Ninja
User
User
Posts: 24
Joined: Mon Jan 14, 2013 8:01 am

Re: Screenshot of desktop but not current window

Post 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.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5022
Joined: Sun Apr 12, 2009 6:27 am

Re: Screenshot of desktop but not current window

Post by RASHAD »

Previous post updated
Egypt my love
Post Reply