Page 1 of 3

Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 9:01 am
by American Ninja
Hi everyone, I have a question regarding a special type of screenshot. I know how to get a desktop screenshot, and a screenshot of just the active window; but I need to get a screenshot of the entire desktop *without* the current foreground window, as if it were invisible. All other windows should be present in the shot. Can't figure out a way to do it. Any ideas? I don't need code, I'm just after a conceptual approach that I could try. Hiding the window, or moving it, is no good as it causes a noticeable flicker. Thanks for any ideas. 8)

EDIT Here's what I'm trying to do... first image below shows several windows, and I want to take a screenshot of the entire desktop but *without* calculator included. The second image shows how I'd like my screenshot to look like.

Image Image

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 10:39 am
by Nituvious
Something like this?

Code: Select all

ExamineDesktops()
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)

UsePNGImageEncoder()
SaveImage(img, "D:\test.png", #PB_ImagePlugin_PNG)
[edit] sorry, just reread your post. I'm dumb :oops:

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 11:15 am
by electrochrisso
Nituvious wrote:Something like this?

Code: Select all

ExamineDesktops()
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)

UsePNGImageEncoder()
SaveImage(img, "D:\test.png", #PB_ImagePlugin_PNG)
[edit] sorry, just reread your post. I'm dumb :oops:
Not that dumb, why not use that code and use SetWindowState(#Window,#PB_Window_Minimize) before the capture, then SetWindowState(#Window,#PB_Window_Normal) after the capture.
Or it might be better to use HideWindow(#Window, #True/#False) instead.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 11:30 am
by American Ninja
I neglected to mention that my program has no window of its own, so there won't be a use for SetWindowState() or other window commands. The foreground window that I *don't* want to capture will be a third-party window.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 11:55 am
by electrochrisso
American Ninja wrote:I neglected to mention that my program has no window of its own, so there won't be a use for SetWindowState() or other window commands. The foreground window that I *don't* want to capture will be a third-party window.
I was wondering about that, if you are on windows, if you know the handle to the window through the API, then use the ShowWindow_(#hWnd,#SW_SHOWMINIMIZED) and ShowWindow_(hWnd,#SW_SHOWNORMAL) or if this is not possible another idea would be to use AutoIT, which can use the name of the window, there is some PB stuff that uses the AutoIT2 dll on the forum somewhere.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 12:11 pm
by American Ninja
ShowWindow is no good because it causes flicker and also re-arranges the taskbar buttons when the window hides. And the user will wonder where his window went that he was typing on.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 12:38 pm
by IdeasVacuum
It's unusual for HideWindow/ShowWindow to cause flicker in my experience, so that issue may be limited to you in some way, either code or hardware.

Sounds long-winded but the alternative is mostly simple and can be performed in milliseconds:
1) Get the ScreenSize
2) Get the Wallpaper Setting (image, image arrangement)
3) Create a blank image, ScreenSize, draw the wallpaper on it
4) Verify the location and size of the window that should not be captured
5) Capture the screen regions around the window. For example, if the window is center screen, your app will capture 4 regions - above the window, either side, below the window. Draw these 4 captures onto your image.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 1:01 pm
by American Ninja
Hiding a window (making it disappear) and then re-showing it, you're saying it's unnoticable? :shock:

Looking at your steps, it's similar to what I was planning, but how do I get the imagery UNDER where the window is? This imagery could be composed of lots of other windows from other apps (see first post where I put other windows under the foreground one that I *don't* want). I don't want just a blank space. You see, it's not so easy to accomplish.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 1:23 pm
by electrochrisso
American Ninja wrote:ShowWindow is no good because it causes flicker and also re-arranges the taskbar buttons when the window hides. And the user will wonder where his window went that he was typing on.
Here is an example, no flicker on my computer, using minimize and normal, so the takbar buttons should not be re-arranged.

Code: Select all

Procedure WindowCallback(Window, Message, wParam, lParam)
  Select Message
    Case #WM_CLOSE
      DestroyWindow_(Window)
    Case #WM_DESTROY
      PostQuitMessage_(0)
      Result  = 0
    Default
      Result  = DefWindowProc_(Window, Message, wParam, lParam)
  EndSelect
  ProcedureReturn Result
EndProcedure

#Style  = #WS_VISIBLE | #WS_CAPTION | #WS_SYSMENU
WindowClass.s  = "WindowClass_227B"
wc.WNDCLASSEX
wc\cbSize  = SizeOf(WNDCLASSEX)
wc\hbrBackground = CreateSolidBrush_(GetSysColor_(#COLOR_BTNFACE))
wc\hCursor = LoadCursor_(0, #IDC_ARROW)
wc\lpfnWndProc  = @WindowCallback()
wc\lpszClassName  = @WindowClass
RegisterClassEx_(@wc)

screenx = GetSystemMetrics_(#SM_CXSCREEN)/2-320/2
screeny = GetSystemMetrics_(#SM_CYSCREEN)/2-240/2

hWndMain  = CreateWindow_( WindowClass, "Test Window", #Style, screenx, screeny, 320, 240, 0, 0, 0, 0)

Delay (1000)
ShowWindow_(hWndMain,  #SW_MINIMIZE) 
Delay (1000)
ShowWindow_(hWndMain,  #SW_SHOWNORMAL) 
Delay (1000)
ShowWindow_(hWndMain,  #SW_MINIMIZE) 
Delay (1000)
ShowWindow_(hWndMain,  #SW_SHOWNORMAL) 
Delay (1000)
ShowWindow_(hWndMain,  #SW_MINIMIZE) 
Delay (1000)
ShowWindow_(hWndMain,  #SW_SHOWNORMAL) 

While GetMessage_(msg.MSG, #Null, 0, 0 )
  TranslateMessage_(msg)
  DispatchMessage_(msg)
Wend

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 1:28 pm
by American Ninja
electrochrisso, my program doesn't use a window... and besides, your window disappears from the screen, which is not the desire. I think you misunderstand my requirements. Look at the first post again, I've included images to show what I want to achieve. I think it's actually impossible now. :(

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 2:00 pm
by electrochrisso
American Ninja wrote:electrochrisso, my program doesn't use a window... and besides, your window disappears from the screen, which is not the desire. I think you misunderstand my requirements. Look at the first post again, I've included images to show what I want to achieve. I think it's actually impossible now. :(
Yes I know you are not using a window you created, you are using the calculator for your example, here is another example that uses the calculator, I thought you wanted the window(calculator) out of the way when you take the screen-shot, this is what happens then reappears when that is done, all you need to do is work out the timing, this is the best I can think of for now.

Code: Select all

Procedure GetDesktopWindows()
  h = GetWindow_(GetDesktopWindow_(), #GW_CHILD)
  Repeat
    If IsWindowVisible_(h) = #True
      c$ = Space(999) : GetWindowText_(h, c$, 999)
      If c$ <> ""
        If c$ = "Calculator"
          ShowWindow_(h,  #SW_MINIMIZE) 
          Delay (2000)
          ShowWindow_(h,  #SW_SHOWNORMAL) 
        EndIf
      EndIf
    EndIf
    h = GetWindow_(h, #GW_HWNDNEXT)
  Until h = 0
EndProcedure

GetDesktopWindows()

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 2:12 pm
by American Ninja
Thanks but hiding is not the answer. It flashes the window (especially on a maximized window), moves the taskbar position of it, and gives the focus to another arbitrary window when it shouldn't. See in my second image in the first post how none of the windows have the focus? That's because Calculator still does, but it's not included in the screenshot. That's the goal.

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 2:18 pm
by electrochrisso
I have added the code to take the screen shot with the calculator out of the way, then back again when done.

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"
          ShowWindow_(h,  #SW_SHOWMINNOACTIVE) 
          Delay (500)
          ExamineDesktops()
          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)
          ShowWindow_(h,  #SW_SHOWNORMAL) 
        EndIf
      EndIf
    EndIf
    h = GetWindow_(h, #GW_HWNDNEXT)
  Until h = 0
EndProcedure

GetDesktopWindows()

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 2:32 pm
by electrochrisso
American Ninja wrote:Thanks but hiding is not the answer. It flashes the window (especially on a maximized window), moves the taskbar position of it, and gives the focus to another arbitrary window when it shouldn't. See in my second image in the first post how none of the windows have the focus? That's because Calculator still does, but it's not included in the screenshot. That's the goal.
Not sure what is going on with your system but I get no flashing or taskbar shifting, as for the focus issue, you will have to do it IdeasVacuum way, it is possible with a little work, I might even have a go at it, but not tonight, it is late here and beddy-byes time for me. :)

Re: Screenshot of desktop but not current window

Posted: Mon Jan 14, 2013 2:55 pm
by electrochrisso
I have edited the last code and changed to ShowWindow_(h, #SW_SHOWMINNOACTIVE), this now makes sure the other windows on the desktop do not have focus before the screenshot, I am really off to bed now. :lol: