Reputation: 257
The problem is that although the image is created, there is a small indent on the left side, a screenshot is attached (on top is the image that my program makes, just below the program itself).
HDC hdcWindow{ HdcWindowScreen }, hdcMemDC{ CreateCompatibleDC(hdcWindow) };
HBITMAP hbmScreen{};
BITMAP bmpScreen{};
RECT rcClient;
GetClientRect(WindowFromDC(hdcWindow), &rcClient);
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right + rcClient.left, rcClient.bottom + rcClient.top);
SelectObject(hdcMemDC, hbmScreen);
if (!(BitBlt(hdcMemDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcWindow, 0, 0, SRCCOPY))) {
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
ClearMemory();
}
GetObject(hdcWindow, sizeof(BITMAP), &bmpScreen);
BITMAPFILEHEADER bmfHeader{};
BITMAPINFOHEADER bi{};
bi.biSize = sizeof(BITMAPFILEHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfHeader.bfOffBits = static_cast<DWORD>(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
bmfHeader.bfSize = dwSizeofDIB;
bmfHeader.bfType = 0x4D42;
GdiplusStartupInput gdiplusStartupInput{};
ULONG_PTR gdiplusToken{};
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CLSID myClsId{};
Bitmap* image = new Bitmap(hbmScreen, nullptr);
image->Save(FileName, &myClsId, NULL);
Gdiplus::GdiplusShutdown(gdiplusToken);
Upvotes: 0
Views: 291
Reputation: 6299
GetClientRect() does not include the border and title bar. All it does is tell you the dimensions of the client area.
GetWindowRect retrieves the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
But Windows 10 has thin invisible borders on left, right, and bottom, it is used to grip the mouse for resizing. The borders might look like this: 7,0,7,7 (left, top, right, bottom)
So if we use GetWindowRect
- this gives a little large window rect as compared to what we see on screen.
Please refer: GetWindowRect returns a size including “invisible” borders
As @zett42 said that, use DwmGetWindowAttribute
with DWMWA_EXTENDED_FRAME_BOUNDS
to get the correct window size is a good way.
Like this:
Rect rect;
DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, (PVOID)&rect, sizeof(rect));
Note: If DPI changes, GetWindowRect
will not return the correct window size.
But DwmGetWindowAttribute
will still return a correct size.
Please refer: How to get rectangle bounds given hWnd?
Expand: If DPI changes, LogicalToPhysicalPointForPerMonitorDPI
can return correct coordinates (+invisible borders)
LogicalToPhysicalPointForPerMonitorDPI : Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller.
If you think it's better to have invisible borders, you can use this API.
Upvotes: 1