Direct2D:在位图中捕获对话框背景 [英] Direct2D: Capturing a dialog background in a bitmap
问题描述
我将自定义MFC控件从GDI +转换为Direct2D.该控件位于具有位图背景的对话框中.我需要捕获对话框背景位于控件下的部分,以便可以在控件的OnPaint()函数中呈现背景.有没有一种方法可以将对话框背景捕获到Direct2D中的位图?
在GDI +中,这很简单.您只需创建一个与对话框dc兼容的dc.创建一个兼容的位图,将其加载到DC中,然后将对话框DC的BitBlt加载到兼容的DC中.然后可以使用GDI +绘制位图.
我曾尝试在Direct2D中执行类似的操作,但无法正常工作.我创建了一个ID2D1DCRenderTarget对象,然后将该对象绑定到对话框dc.然后,我调用ID2D1DCRenderTarget :: CreateCompatibleRenderTarget()来创建一个ID2D1BitmapRenderTarget对象.然后,我可以在对象上调用GetBitmap(),但它似乎没有返回可渲染到自定义控件上的有效位图?
I''m converting a custom MFC control from GDI+ to Direct2D. The control sits on a dialog which has a bitmap background. I need to capture the portion of the dialog background which sits under the control so that I can render the background in the control''s OnPaint() function. Is there a way to capture the dialog background to a bitmap in Direct2D?
In GDI+ this is pretty straight forward. You just create a dc compatible with the dialog dc. Create a compatible bitmap, load it into the dc and then BitBlt the dialog dc into the compatible dc. The bitmap can then be drawn using GDI+.
I''ve tried doing something similar in Direct2D but it''s not working. I created a ID2D1DCRenderTarget object and then bound the object to the dialog dc. I then called ID2D1DCRenderTarget::CreateCompatibleRenderTarget() which creates a ID2D1BitmapRenderTarget object. I can then call GetBitmap() on the object but it doesn''t seem to return a valid bitmap that I can render onto the custom control?
推荐答案
好吧,终于成功了.对于其他感兴趣的人,这里是从设备上下文捕获图像并将其渲染到Direct2D渲染目标中所需的步骤.就我而言,我想从具有位图背景的MFC CDialogEx对话框窗口中捕获图像.
第一步需要使用GDI将位图从对话框设备上下文复制到存储设备上下文.这可以使用CreateCompatibleDC(),CreateCompatibleBitmap()和BitBlt()完成.我将结果位图存储在MFC CBitmap对象中.
现在的技巧是将位图放入ID2D1Bitmap对象中,以便我们可以将其渲染到渲染目标.这是使用Windows Imaging Component(WIC)实现的.
首先,调用IWICImagingFactory :: CreateBitmapFromHBITMAP(),传入我们之前创建的CBitmap.这将创建一个IWICBitmap对象.现在需要将IWICBitmap对象转换为32bppPBGRA像素格式.这是使用IWICFormatConverter对象完成的.调用IWICFormatConverter :: Initialize(),以指定先前创建的IWICBitmap对象.
最后,调用ID2D1RenderTarget :: CreateBitmapFromWicBitmap(),传入上面创建的IWICFormatConverter对象.这将创建一个ID2D1Bitmap对象,现在可以在渲染目标中对其进行绘制.
代码片段如下所示:
Ok, finally got this working. For anyone else who is interested, here are the steps required to capture the image from a device context and render it into a Direct2D render target. In my case I wanted to capture the image from an MFC CDialogEx dialog window that had a bitmap background.
The first steps require the use of GDI to copy a bitmap from the dialog device context to a memory device context. This can be done using CreateCompatibleDC(), CreateCompatibleBitmap() and BitBlt(). I stored the resulting bitmap in an MFC CBitmap object.
The trick now is to get the bitmap into a ID2D1Bitmap object so that we can render it to the render target. This is achieved using the Windows Imaging Component (WIC).
First, call IWICImagingFactory::CreateBitmapFromHBITMAP(), passing in the CBitmap we created earlier. This will create an IWICBitmap object. The IWICBitmap object now needs to be converted to a 32bppPBGRA pixel format. This is done using a IWICFormatConverter object. Call IWICFormatConverter::Initialize() specifying the IWICBitmap object created previously.
Finally, call ID2D1RenderTarget::CreateBitmapFromWicBitmap(), passing in the IWICFormatConverter object created above. This will create an ID2D1Bitmap object that can now be drawn in the render target.
A snippet of code is shown below:
CClientDC dcParent(GetParent());
CRect rectClient;
CRect rectWindow;
CDC dcBackground;
CBitmap *pOldBitmap = NULL;
CBitmap DialogBitmap;
HRESULT hr = E_FAIL;
CComPtr<IWICBitmap> pDialogBitmap = NULL;
m_pParentBitmap.Release();
GetWindowRect(rectWindow);
GetParent()->ScreenToClient(rectWindow);
GetClientRect(rectClient);
dcBackground.CreateCompatibleDC(&dcParent);
DialogBitmap.CreateCompatibleBitmap(&dcParent, rectClient.Width(), rectClient.Height());
pOldBitmap = dcBackground.SelectObject(&DialogBitmap);
dcBackground.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &dcParent, rectWindow.left, rectWindow.top, SRCCOPY);
dcBackground.SelectObject(pOldBitmap);
// Note that the WICBitmapAlphaChannelOption is very important. If we don''t set it to a value that is compatible
// with the render target where we intend to draw the bitmap then a black bitmap will be drawn.
hr = theApp.g_pWICFactory->CreateBitmapFromHBITMAP(DialogBitmap, NULL, WICBitmapIgnoreAlpha/*WICBitmapUsePremultipliedAlpha*/, &pDialogBitmap);
if (SUCCEEDED(hr))
{
// Convert the dialog bitmap to a 32bppPBGRA pixel format. Before Direct2D can use an image, it must be converted
// to the 32bppPBGRA pixel format. To convert the image format, use the CreateFormatConverter method to create
// an IWICFormatConverter object. Once created, use the Initialize method to perform the conversion.
CComPtr<IWICFormatConverter> pFormatConverter = NULL;
hr = pWICFactory->CreateFormatConverter(&pFormatConverter);
if (SUCCEEDED(hr))
{
// dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when converting
// to a reduced bit-depth format. We do not need to do this so we use the following parameters:
// dither set to WICBitmapDitherTypeNone,
// pIPalette set to NULL,
// alphaThresholdPercent set to 0.0f,
// and paletteTranslate set to WICBitmapPaletteTypeCustom
hr = pFormatConverter->Initialize(pDialogBitmap, // Input bitmap to convert
GUID_WICPixelFormat32bppPBGRA, // Destination pixel format
WICBitmapDitherTypeNone, // Specified dither pattern
NULL, // Specify a particular palette
0.0f, // Alpha threshold
WICBitmapPaletteTypeCustom); // Palette translation type.
if (SUCCEEDED(hr))
{
hr = pRenderTarget->CreateBitmapFromWicBitmap(pFormatConverter, NULL, &m_pParentBitmap);
m_bParentBackgroundCaptured = true;
}
}
}
这篇关于Direct2D:在位图中捕获对话框背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!