我有一个生成图形图像的MFC桌面应用程序,我希望用户能够将其作为位图复制到剪贴板。我使用标准的剪贴板API例程,到目前为止它们一直很好用。但是,我现在已经激活了GDI Scaling(通过清单),以便程序可以在HiDPI显示器上运行(相当好),并且我发现放在剪贴板上的图像只是实际图像的左上象限。这可能是由于图像的内部缩放 - 显示器以200%运行。如何复制整个图像?
关键是在上一个问题的答案中给出的:Saving Bitmaps on Windows 10 with GDI scaling active,但我花了一些时间来调整我的特定问题的答案,所以我想我会分享,以防它对其他人有帮助。 (免责声明 - 我不是专家,所以可能有更好的方法......)
bool CopyRectToClipboard(CWnd *pW, CRect rctCopy)
{
if (!pW->OpenClipboard())
return false;
if (!EmptyClipboard())
return false;
CClientDC dc(pW);
CDC dcMem;
VERIFY(dcMem.CreateCompatibleDC(&dc));
CBitmap bmTrial; // need a trial bitmap to get GDI Scaled size
VERIFY(bmTrial.CreateCompatibleBitmap(&dc, rctCopy.Width(), rctCopy.Height()));
// see https://stackoverflow.com/questions/51169846/saving-bitmaps-on-windows-10-with-gdi-scaling-active
BITMAPINFO bi = {};
bi.bmiHeader.biSize = sizeof(bi);
int result = GetDIBits(dc.GetSafeHdc(), (HBITMAP)bmTrial.GetSafeHandle(), 0, 0, NULL, &bi, DIB_RGB_COLORS);
CBitmap bm;
VERIFY(bm.CreateCompatibleBitmap(&dc, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight));
ASSERT(bm.m_hObject != NULL);
CBitmap* pbmOld = dcMem.SelectObject(&bm);
//dcMem.PatBlt(0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, WHITENESS); // legacy
VERIFY(dcMem.BitBlt(0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight,
&dc, rctCopy.left - 1, rctCopy.top - 1, SRCCOPY));
HGDIOBJ hBM = bm.Detach();
VERIFY(::EmptyClipboard());
VERIFY(::SetClipboardData(CF_BITMAP, hBM));
VERIFY(::CloseClipboard());
dcMem.SelectObject(pbmOld);
dcMem.DeleteDC();
return true;
}