Как прокомментировал Remy Lebeau
, PrintWindow()
не выглядит надежным, поскольку он непосредственно захватывает клиентскую часть окна, даже если он не виден на экране (например, находится позади). другое окно). Одна вещь, которая, кажется, работает намного лучше, это сделать обычный скриншот и ограничить область клиентской областью целевого окна. Это имеет тот недостаток, что окно должно быть видимым, чтобы быть захваченным. Код для этого, например, следующее:
// Get the horizontal and vertical screen sizes in pixel
inline POINT get_window_resolution(const HWND window_handle)
{
RECT rectangle;
GetClientRect(window_handle, &rectangle);
const POINT coordinates{rectangle.right, rectangle.bottom};
return coordinates;
}
#include <iostream>
#include <ole2.h>
#include <olectl.h>
inline bool save_bitmap(const LPCSTR file_path,
const HBITMAP bitmap, const HPALETTE palette)
{
PICTDESC pict_description;
pict_description.cbSizeofstruct = sizeof(PICTDESC);
pict_description.picType = PICTYPE_BITMAP;
pict_description.bmp.hbitmap = bitmap;
pict_description.bmp.hpal = palette;
LPPICTURE picture;
auto initial_result = OleCreatePictureIndirect(&pict_description, IID_IPicture, false,
reinterpret_cast<void**>(&picture));
if (!SUCCEEDED(initial_result))
{
return false;
}
LPSTREAM stream;
initial_result = CreateStreamOnHGlobal(nullptr, true, &stream);
if (!SUCCEEDED(initial_result))
{
picture->Release();
return false;
}
LONG bytes_streamed;
initial_result = picture->SaveAsFile(stream, true, &bytes_streamed);
const auto file = CreateFile(file_path, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (!SUCCEEDED(initial_result) || !file)
{
stream->Release();
picture->Release();
return false;
}
HGLOBAL mem = nullptr;
GetHGlobalFromStream(stream, &mem);
const auto data = GlobalLock(mem);
DWORD bytes_written;
auto result = WriteFile(file, data, bytes_streamed, &bytes_written, nullptr);
result &= bytes_written == static_cast<DWORD>(bytes_streamed);
GlobalUnlock(mem);
CloseHandle(file);
stream->Release();
picture->Release();
return result;
}
inline POINT get_client_window_position(const HWND window_handle)
{
RECT rectangle;
GetClientRect(window_handle, static_cast<LPRECT>(&rectangle));
MapWindowPoints(window_handle, nullptr, reinterpret_cast<LPPOINT>(& rectangle), 2);
const POINT coordinates = {rectangle.left, rectangle.top};
return coordinates;
}
// https://stackoverflow.com/a/9525788/3764804
inline bool capture_screen_client_window(const HWND window_handle, const LPCSTR file_path)
{
SetActiveWindow(window_handle);
const auto hdc_source = GetDC(nullptr);
const auto hdc_memory = CreateCompatibleDC(hdc_source);
const auto window_resolution = get_window_resolution(window_handle);
const auto width = window_resolution.x;
const auto height = window_resolution.y;
const auto client_window_position = get_client_window_position(window_handle);
auto h_bitmap = CreateCompatibleBitmap(hdc_source, width, height);
const auto h_bitmap_old = static_cast<HBITMAP>(SelectObject(hdc_memory, h_bitmap));
BitBlt(hdc_memory, 0, 0, width, height, hdc_source, client_window_position.x, client_window_position.y, SRCCOPY);
h_bitmap = static_cast<HBITMAP>(SelectObject(hdc_memory, h_bitmap_old));
DeleteDC(hdc_source);
DeleteDC(hdc_memory);
const HPALETTE h_palette = nullptr;
if (save_bitmap(file_path, h_bitmap, h_palette))
{
return true;
}
return false;
}
Он основан на этом ответе.