0

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). enter image description here

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);
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
Gogogo
  • 167
  • 1
  • 8
  • What is the content of `rcClient`? – user7860670 Nov 12 '19 at 18:58
  • 1
    Try `GetWindowRect()` instead of `GetClientRect()`. A window's client area rectangle is usually smaller than its overall window rectangle. – Remy Lebeau Nov 12 '19 at 19:15
  • 2
    `GetWindowRect()` doesn't give you the right size either, because it includes the shadow area. Use `DwmGetWindowAttribute()` with `DWMWA_EXTENDED_FRAME_BOUNDS` to get the "real" window size. – zett42 Nov 12 '19 at 21:03

1 Answers1

1

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.

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • @Gogogo Hi,is the answer useful for you? If it helps you, please mark it, which is good for other members of the community to read this thread:) If you don't know how to mark, please refer to [this](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – Strive Sun Nov 21 '19 at 02:34