I have created a small demo app which window looks as below:
https://i.stack.imgur.com/iW05q.png[
^]
When I run this demo app, and press any key, I want to capture the part of the screen bitmap.
The part of the screen I am interested in, is the one my window occupies, namely the content of the top rectangle in my window that holds letters. The captured screen bitmap should look like below:
https://i.stack.imgur.com/9eSVH.png[
^]
The problem I face is that screen capturing code captures wrong part of the screen.
Below is the full code (bare in mind that I tried to keep things as minimal as possible):
#include <Windows.h>
void foo(HWND hWnd)
{
HDC hdcScreen;
HDC hdcWindow;
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
RECT rcClient;
GetClientRect(hWnd, &rcClient);
RECT rc1 = rcClient;
MapWindowPoints(hWnd, NULL, (LPPOINT)&rc1, 2);
if (!BitBlt(hdcWindow,
rcClient.left + 50, rcClient.top + 70, 75, 35, hdcScreen,
rc1.left + 50, rc1.top + 20, SRCCOPY))
{
OutputDebugString(L"StretchBlt has failed");
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow);
return;
}
RECT rcBottomRect; rcBottomRect.left = rcClient.left + 50; rcBottomRect.top = rcClient.top + 70; rcBottomRect.right = rcClient.left + 125; rcBottomRect.bottom = rcClient.top + 105;
HBRUSH br = (HBRUSH)GetStockObject(BLACK_BRUSH);
FrameRect(hdcWindow, &rcBottomRect, br);
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYUP: foo(hwnd); break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rcClient;
GetClientRect(hwnd, &rcClient);
RECT rcTopRect;
rcTopRect.left = rcClient.left + 50;
rcTopRect.top = rcClient.top + 20;
rcTopRect.right = rcTopRect.left + 75;
rcTopRect.bottom = rcTopRect.top + 35;
HBRUSH br = (HBRUSH)GetStockObject(BLACK_BRUSH);
TextOut(hdc, 20, 30, L"Asdf ghj kkl oioio 4545 676767", ARRAYSIZE(L"Asdf ghj kkl oioio 4545 676767"));
FrameRect(hdc, &rcTopRect, br);
RECT rcBottomRect;
rcBottomRect.left = rcClient.left + 50;
rcBottomRect.top = rcClient.top + 70;
rcBottomRect.right = rcClient.left + 125;
rcBottomRect.bottom = rcClient.top + 105;
FrameRect(hdc, &rcBottomRect, br);
EndPaint(hwnd, &ps);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"myWindowClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"myWindowClass",
L"MVCE",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 170,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
How to fix calculation "error" (maybe it is not an error, maybe I am misusing the API?) with
MapWindowPoints
?
UPDATE:
I have forgotten to mention that I have 2 monitors. After testing the app on second monitor everything worked fine.
After going through the settings for the first monitor, I have found out that it is set to scale text, apps and other items to 150%.
Reverting it to 100% made the code work, but now I need to find a solution for this case, as I may not force users to change their settings.
Any help would be appreciated.
What I have tried:
Commenting out MapWindowPoints didn't help, ClientToScreen didn't help either, nor have I found alternative API...