3

I have created a second desktop using CreateDesktop and im not switching to it. Also i have created some processes in it like Explorer.exe and Winrar.exe. Next i have a code which takes Screenshot of current desktop to clipboard. Both CreateDesktop and Screenshot works, But Screenshot of that new desktop or window returns a black bitmap:

This is the screenshot for a window in a desktop which returns current desktop:

// hwnd is handle to winrar or ... created in a new desktop retrieved by EnumDesktopWindow
RECT rc;
GetClientRect(hwnd, &rc);
const HDC hScreenDC = GetDC(nullptr);
const HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
const int width = GetDeviceCaps(hScreenDC, HORZRES);
const int height = GetDeviceCaps(hScreenDC, VERTRES);
const HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
HBITMAP(SelectObject(hMemoryDC, hBitmap));
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);

OpenClipboard(nullptr);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();

DeleteDC(hMemoryDC);
DeleteDC(hScreenDC);

I have implemented both this methods in c# but same thing happens there.

There are great resources like:

Capture screenshot of hidden desktop

take a screenshot of a desktop created using createdesktop api

C# – SCREEN CAPTURE WITH VISTA DWM (SHARED DIRECT3D SURFACE)

Window Contents Capturing using WM_PRINT Message

how to capture screen from another desktop?(CreateDesktop)

Also this is like a dead topic, No new article, Explanation or solution to it.

I have read most of them but no luck, This was my closest try i think. Also language doesnt matter for me: C#, C++, Python or ... .

0_o
  • 570
  • 6
  • 18

1 Answers1

3

I found the solution, It is interesting but no perfect, Just resolves my needs.

After CreateDesktop by calling OpenDesktop then SetThreadDesktop then using the screenshot code you get the screenshot of the window which is created inside CreateDesktop, Also no need for Creating Explorer.exe inside it if you just want the window:

CreateDesktopW(L"NewDesktop"); // CreateDesktop code here. This is my function
const HDESK Handle = OpenDesktopW(L"NewDesktop", 0, 0, GENERIC_ALL);
SetThreadDesktop(Handle);

// Above ScreenShot code here ...

The screenshot code needs a PrintWindow:

RECT rc;
GetClientRect(hwnd, &rc);
const HDC hScreenDC = GetDC(nullptr);
const HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
const int width = GetDeviceCaps(hScreenDC, HORZRES);
const int height = GetDeviceCaps(hScreenDC, VERTRES);
const HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
HBITMAP(SelectObject(hMemoryDC, hBitmap));
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);

/// ADDED CODE
PrintWindow(hWnd, hMemoryDC, PW_CLIENTONLY);
///

OpenClipboard(nullptr);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();

DeleteDC(hMemoryDC);
DeleteDC(hScreenDC);

Mine worked with a winrar.exe window inside a inactive desktop. You can try this then paste it to paint to see the result.

There is just one thing, The whole area of the screenshot bitmap is black except the window handle that i want which is fine by me. I think i should get handle of every window from bottom to top in order then mix them up.

All additions to this are appreciated.

0_o
  • 570
  • 6
  • 18