BitBlt()
требует GDI HDC
для копирования, но TDirect2DCanvas
не имеет собственного HDC
, и он не может напрямую отображать за пределами экрана HDC
/ TCanvas
, например TBitmap.Canvas
, согласно документации :
TDirect2DCanvas будет работать только для контекстов экранного устройства . Вы не можете использовать TDirect2DCanvas для рисования в контексте устройства принтера, например.
И вы не можете связать пользовательский RenderTarget
(например, созданный с ID2D1Factory.CreateDCRenderTarget()
* 1023). * и ID2D1DCRenderTarget.BindDC()
), поскольку свойство TDirect2DCanvas.RenderTarget доступно только для чтения.
Таким образом, вам, вероятно, потребуется go длинный путь, чтобы получить то, что ты хочешь. Основываясь на коде, который я нашел в Direct2d Desktop для печати C ++ , который демонстрирует копирование произвольного ID2D1RenderTarget
в произвольное HDC
, вы можете попробовать следующее:
Создайте Direct2D ID2D1Bitmap
, привязанный к текущему RenderTarget
холста, используя один из методов CreateBitmap()
цели.
Скопируйте пиксели из холста в растровое изображение с использованием метода CopyFromRenderTarget()
.
Создайте IWICBitmap
(вы, вероятно, можете использовать VCL TWICImage
для этого) и визуализировать в него растровое изображение Direct2D, используя один из методов ID2D1Factory.CreateWicBitmapRenderTarget()
с одним из методов ID2D1RenderTarget.DrawBitmap()
.
Создайте растровое изображение GDI DIB
и визуализируйте в него IWICBitmap
, используя растровое изображение WI C CopyPixels()
.
Наконец, вы используете DIB
так, как вам нужно, например, выберите / скопируйте его в ваш окончательный HDC
, или вы можете просто поместить его содержимое прямо в буфер обмена, используя CF_DIB
формат.
Вот код (извините, это на C ++, я не собираюсь переводить его на Delphi):
void Direct2DRender::RenderToDC(HDC hDC, UINT uiWidth, UINT uiHeight)
{
HRESULT hr = S_OK;
IWICImagingFactory *pImageFactory = WICImagingFactory::GetInstance().GetFactory();
CComPtr<IWICBitmap> wicBitmap;
hr = pImageFactory->CreateBitmap( uiWidth, uiHeight, GUID_WICPixelFormat32bppBGR, WICBitmapCacheOnLoad, &wicBitmap);
D2D1_SIZE_U bitmapPixelSize = D2D1::SizeU( uiWidth, uiHeight);
float dpiX, dpiY;
m_pRenderTarget->GetDpi( &dpiX, &dpiY);
CComPtr<ID2D1Bitmap> d2dBitmap;
hr = m_pRenderTarget->CreateBitmap( bitmapPixelSize, D2D1::BitmapProperties(
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
dpiX, dpiY), &d2dBitmap );
D2D1_POINT_2U dest = D2D1::Point2U(0,0);
D2D1_RECT_U src = D2D1::RectU(0, 0, uiWidth, uiHeight);
hr = d2dBitmap->CopyFromRenderTarget(&dest, m_pRenderTarget, &src);
D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();
rtProps.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
rtProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
rtProps.usage = D2D1_RENDER_TARGET_USAGE_NONE;
CComPtr<ID2D1RenderTarget> wicRenderTarget;
hr = m_pDirect2dFactory->CreateWicBitmapRenderTarget( wicBitmap, rtProps, &wicRenderTarget);
wicRenderTarget->BeginDraw();
wicRenderTarget->DrawBitmap(d2dBitmap);
hr = wicRenderTarget->EndDraw();
// Render the image to a GDI device context
HBITMAP hDIBBitmap = NULL;
try
{
// Get a DC for the full screen
HDC hdcScreen = GetDC(NULL);
if (!hdcScreen)
throw 1;
BITMAPINFO bminfo;
ZeroMemory(&bminfo, sizeof(bminfo));
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo.bmiHeader.biWidth = uiWidth;
bminfo.bmiHeader.biHeight = -(LONG)uiHeight;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
void* pvImageBits = nullptr; // Freed with DeleteObject(hDIBBitmap)
hDIBBitmap = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
if (!hDIBBitmap)
throw 2;
ReleaseDC(NULL, hdcScreen);
// Calculate the number of bytes in 1 scanline
UINT nStride = DIB_WIDTHBYTES(uiWidth * 32);
// Calculate the total size of the image
UINT nImage = nStride * uiHeight;
// Copy the pixels to the DIB section
hr = wicBitmap->CopyPixels(nullptr, nStride, nImage, reinterpret_cast<BYTE*>(pvImageBits));
// Copy the bitmap to the target device context
::SetDIBitsToDevice(hDC, 0, 0, uiWidth, uiHeight, 0, 0, 0, uiHeight, pvImageBits, &bminfo, DIB_RGB_COLORS);
DeleteObject(hDIBBitmap);
}
catch (...)
{
if (hDIBBitmap)
DeleteObject(hDIBBitmap);
// Rethrow the exception, so the client code can handle it
throw;
}
}
В том же обсуждении описывается другая альтернатива:
Создайте раздел DIB и выберите его в D C
Создание цели рендеринга D C
Привязка цели рендеринга к D C, который соответствует секции DIB
Рисование с использованием Direct2D. После вызова EndDraw DIB содержит то, что было отрендерено.
Последний шаг - нарисовать метку там, где она вам нужна.
Итак, попробуйте переместить ваш код для рисования в его собственную функцию, которая принимает ID2D1RenderTarget
в качестве входных данных и dr aws в случае необходимости. Затем вы можете создать RenderTarget
на основе HDC
, когда хотите поместить растровое изображение в буфер обмена, и использовать TDirect2DCanvas.RenderTarget
, когда хотите нарисовать на D2DBox
.