Reputation: 91
I'm slowly making progress in my c++ application. I would like to 'automate' the repetitive manual screen capture I go through every time in support of my debugging process. I'm relatively new to c++ so I found this snippet that seems to work fine for me, except it's not quite capturing my application area :
RECT rectWindow;
GetWindowRect(hWnd, &rectWindow); // hWnd defined in global scope
int x1, y1, x2, y2, w, h;
x1 = rectWindow.left; // x1 = 780
y1 = rectWindow.top; // y1 = 385
x2 = rectWindow.right; // x2 = 1780
y2 = rectWindow.bottom; // y2 = 1055
// width and height
w = x2 - x1; // w = 1000
h = y2 - y1; // h = 670
// copy window to bitmap
HDC hWindow = GetDC(hWnd);
HDC hDC = CreateCompatibleDC(hWindow);
HBITMAP hBitmap = CreateCompatibleBitmap(hWindow, w, h);
HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
BOOL bRet = BitBlt(hDC, 0, 0, w, h, hWindow, x1, y1, SRCCOPY);
CImage image;
image.Attach(hBitmap);
image.Save(L"C:\\TEMP\\window.bmp", Gdiplus::ImageFormatBMP);
// clean-up
SelectObject(hDC, old_obj);
DeleteDC(hDC);
::ReleaseDC(NULL, hWindow);
DeleteObject(hBitmap);
Below is a manual screen capture of my application window :
Now, this (saved in JPEG to meet SO min size requirements) is what I'm getting :
Not quite what I expect. So I edited the Bit Block call this way :
BOOL bRet = BitBlt(hDC, 0, 0, w, h, hWindow, 0, 0, SRCCOPY);
And this gives me "almost" the correct capture :
What am doing wrong?
Upvotes: 0
Views: 146
Reputation: 595319
GetWindowRect()
returns screen coordinates, which you are then passing as-is to BitBlt()
, but it is expecting coordinates relative to the window instead since you are capturing from a window DC and not a screen DC. That is why the top-left corner of your capture is so far into the window.
Change this:
BitBlt(..., hWindow, x1, y1, ...)
To this instead:
BitBlt(..., hWindow, 0, 0, ...)
Also, GetDC()
retrieves an HDC
for just the client area of the window:
The GetDC function retrieves a handle to a device context (DC) for the client area of a specified window or for the entire screen.
Your window's title bar and menu do not appear in your capture because they are outside of the client area. Since you want a capture of the entire window, use GetWindowDC()
instead:
The GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. A window device context permits painting anywhere in a window, because the origin of the device context is the upper-left corner of the window instead of the client area.
Upvotes: 1
Reputation: 91
Found some code that worked flawlessly. It's using a lot of the same code?
RECT rcSrc;
HWND hSrcWnd;
HDC hDC2, hSrcDC;
HBITMAP hBmp;
//hSrcWnd = FindWindow(NULL, szWindowClass);
GetWindowRect(hWnd, &rcSrc);
hDC2 = GetDC(hWnd);
hSrcDC = CreateCompatibleDC(NULL);
hBmp = CreateCompatibleBitmap(hDC2, rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top);
SelectObject(hSrcDC, hBmp);
PrintWindow(hWnd, hSrcDC, 0);
BitBlt(hDC2, 0, 0, rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top, hSrcDC, 0, 0, SRCCOPY);
CImage image2;
image2.Attach(hBmp);
image2.Save(L"C:\\TMP\\Test.jpg", Gdiplus::ImageFormatJPEG);
DeleteObject(hBmp);
DeleteDC(hSrcDC);
ReleaseDC(hWnd, hDC2);
Upvotes: 0