Search code examples
winapiscreenshot

How to screenshot a Zoom window?


I have a requirement in my app to programmatically screenshot a Zoom window. I implemented this using standard Windows API calls:

Hdc hdcWindow = GetWindowDC(hwnd);
Hdc hdcMemDC = CreateCompatibleDC(hdcWindow);

var windowRect = new Rect();
GetWindowRect(hwnd, ref windowRect);
int width = windowRect.Right - windowRect.Left;
int height = windowRect.Bottom - windowRect.Top;

var hbmScreen = CreateCompatibleBitmap(hdcWindow, width, height);
var hOld = SelectObject(hdcMemDC, hbmScreen);

//tried this
BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY);
//also tried this
PrintWindow(hwnd, hdcMemDC, 0);
//and this
// Send WM_PRINT message to the window to have it print to the memory dc
SendMessage(hwnd, WM_PRINT, hdcMemDC, (IntPtr)(PRF_CHILDREN | PRF_CLIENT | PRF_NONCLIENT));

//get the bitmap
var bmp = System.Drawing.Bitmap.FromHbitmap(hbmScreen);
                
//clean up
SelectObject(hdcMemDC, hOld);
DeleteObject(hbmScreen);
DeleteDC(hdcMemDC);
ReleaseDC(hwnd, hdcWindow);

return bmp;

What happens is that I do get a screenshot of the Zoom window, but instead of getting the video, I get the window frame, but the window client area is whatever was behind it at the time:

enter image description here

In this case, I happened to have Visual Studio running behind the Zoom window, and so you can see the title bar and the Zoom controls, but instead of the video, you see that VS window. And I get this image every time, until I restart a new Zoom session.

I think probably Zoom is doing something non-standard with its windowing, so how can I take a screenshot of it?


Solution

  • Instead of trying to capture the window itself, it worked to screenshot the entire desktop window and then crop it to the location and size of the zoom window, which can be obtained by ordinary methods. Doing this is good enough for my needs at this time.