使用增强型元文件 DC 作为源 DC 时出现 BItBlt 问题

Posted

技术标签:

【中文标题】使用增强型元文件 DC 作为源 DC 时出现 BItBlt 问题【英文标题】:BItBlt issue when using enhanced meta file DC as source DC 【发布时间】:2016-11-29 15:20:37 【问题描述】:

我正在开发一个使用 emf 进行缓冲区绘制的应用程序。我正在尝试使用 BitBlt 将此 emf 保存到位图图像文件中。但是没有图纸被保存到位图中。我知道我可以使用 PlayEnhMetaFile() 但我必须为此使用 BitBlt 或 GDI/GDI+ 调用。因为在将其保存到位图后,还会有其他一些对 emf 的绘图调用。 示例代码。

void CTestGUIApplicationView::OnDraw(CDC* pDC)

CRect oRect(0, 0, 640, 434);
HDC hdc = pDC->GetSafeHdc();
//Meta file creation
int iWidthMM = GetDeviceCaps(hdc, HORZSIZE);
int iHeightMM = GetDeviceCaps(hdc, VERTSIZE);
int iWidthPels = GetDeviceCaps(hdc, HORZRES);
int iHeightPels = GetDeviceCaps(hdc, VERTRES);
CRect rect;
rect.left = (oRect.left * iWidthMM * 100) / iWidthPels;
rect.top = (oRect.top * iHeightMM * 100) / iHeightPels;
rect.right = (oRect.right * iWidthMM * 100) / iWidthPels;
rect.bottom = (oRect.bottom * iHeightMM * 100) / iHeightPels;

HDC hMetaDC = CreateEnhMetaFile(hdc, NULL, &rect, NULL);
CDC *pMetaDC = CDC::FromHandle(hMetaDC);

//Drawing on meta file DC.
RECT drawingRect;
CPen penBlue, pen2, pen3, pen4;
penBlue.CreatePen(PS_SOLID | PS_COSMETIC, 1, RGB(0, 0, 255));
pen2.CreatePen(PS_SOLID | PS_COSMETIC, 1, RGB(0, 255, 255));
pen3.CreatePen(PS_SOLID | PS_COSMETIC, 1, RGB(255, 0, 255));
pen4.CreatePen(PS_SOLID | PS_COSMETIC, 1, RGB(128, 0, 56));
auto pOldPen = pMetaDC->SelectObject(&penBlue);

pMetaDC->Arc(oRect,
    CPoint(oRect.right, oRect.CenterPoint().y),
    CPoint(oRect.CenterPoint().x, oRect.right));
pMetaDC->SelectObject(&pen2);
pMetaDC->Ellipse(oRect.left + 50, oRect.top + 25, oRect.Width(), oRect.Height());

//copy meta file to DC.
CopyToBitMap(_T("StateImage_EMFDC.bmp"), pMetaDC, oRect);

//some other drawing calls on meta file DC.
pMetaDC->SelectObject(&pen3);
pMetaDC->Ellipse(oRect.left + oRect.Width() / 2, oRect.top + oRect.Height() / 2, oRect.Width(), oRect.Height());
pMetaDC->SelectObject(pOldPen); pOldPen = NULL;

//Copy meta file to window DC.
HENHMETAFILE hMeta = CloseEnhMetaFile(pMetaDC->GetSafeHdc());
if (hMeta != NULL)

    //save meta file to disk to view its contents.
    HENHMETAFILE hMeta2 = CopyEnhMetaFile(hMeta, _T("test.emf"));
    DeleteEnhMetaFile(hMeta2);
    PlayEnhMetaFile(hdc, hMeta, oRect);
    DeleteEnhMetaFile(hMeta);

//some other drawing on Window DC.
pOldPen = pDC->SelectObject(&pen4);
pDC->Ellipse(oRect.left + 25, oRect.top + 50, oRect.Width() - 30, oRect.Height() - 60);
pDC->SelectObject(pOldPen);
CopyToBitMap(_T("StateImage_WindowDC.bmp"), pDC, oRect);

//Routine to copy data from DC to bitmap.
void CTestGUIApplicationView::CopyToBitMap(CString filePath, CDC* pDC, CRect & windRect)

//creating bitmap 
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(pDC, windRect.Width(), windRect.Height());
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap *oldBMP = memDC.SelectObject(&bitmap);
memDC.FillSolidRect(windRect, RGB(0, 255, 0));
BOOL result = BitBlt(memDC.GetSafeHdc(), 0, 0, windRect.Width() , windRect.Height(), pDC->GetSafeHdc(), 0, 0, SRCCOPY);
memDC.SelectObject(oldBMP);
//Saving bitmap to disk.
CImage image;
image.Attach(bitmap);
image.Save(filePath, Gdiplus::ImageFormatBMP);
image.Detach();
image.Destroy();
bitmap.DeleteObject();

“StateImage_WindowDC.bmp”有完整的绘图。而“StateImage_EMFDC.bmp”是完整的绿色图像,应该有绘图。

【问题讨论】:

将元文件播放到已选择位图的 HDC 有什么问题?从那里,您可以从这个位图 BitBlt 到第二个目标。 【参考方案1】:

元文件 DC 与常规 DC 不同,它不会在位图上绘制;它仅用于记录绘图指令。来自Microsoft's "Enhanced Metafile Creation" page:

当 CreateEnhMetaFile 成功时,它会返回一个句柄来标识一个特殊的元文件设备上下文。元文件设备上下文是唯一的,因为它与文件相关联,而不是与输出设备相关联。当系统处理接收到元文件设备上下文句柄的 GDI 函数时,它会将 GDI 函数转换为增强元文件记录,并将记录附加到增强元文件的末尾。

您说您不能调用PlayEnhMetaFile,因为您有其他绘图命令要在捕获后附加到元文件。在这种情况下,我可以看到两个选项:

    与元文件 DC 并行绘制到常规 DC。 使用GetEnhMetaFileBitsSetEnhMetaFileBits 制作可与PlayEnhMetaFile 一起使用的元文件副本

【讨论】:

以上是关于使用增强型元文件 DC 作为源 DC 时出现 BItBlt 问题的主要内容,如果未能解决你的问题,请参考以下文章

使用自己的 ldif 文件时出现 LDAP 异常

元宇宙经济学实现DC/EP在元宇宙经济中的法币地位

元宇宙经济学实现DC/EP在元宇宙经济中的法币地位

使用ARM模板在Azure中国大规模部署DC/OS集群

如何将 MFC DC 与 QPrinter 关联?

wireshark常用包过滤规则