【发布时间】:2012-02-19 15:16:37
【问题描述】:
我正在使用 MFC 的 doc/view 架构来实现打印。我使用双缓冲,我将所有内容都绘制到我的后备缓冲区上,即 DIB 位图。比我使用 StretchBlt 将该 DIB 复制到打印机 DC 上。
奇怪的是 - 打印预览运行良好!当我在虚拟 PDF 打印机上打印时,它运行良好!但是当我在实际打印机上打印时(我在两台不同的打印机上进行测试——结果相同)——它只会打印“垃圾”。 “垃圾”意味着有时它打印完全黑页,有时它重复打印前几页,即它打印错误的DIB部分,就像我把坐标弄乱了StretchBlt一样,但我没有弄乱任何东西,我检查了多次,再加上为什么打印预览工作完美呢?
我尝试了很多变化:
- 打印时使用与屏幕 DC 兼容的内存 DC。
- 使用与打印机 DC 兼容的内存 DC,并在其中选择我的 DIB。
- 使用与打印机 DC 兼容的内存 DC,并使用专用的 DIB,我将原始后缓冲 DIB 复制到该 DIB 上。 等
但是结果是一样的。下面是我创建 DIB 的代码。我认为DIB格式可能是问题,所以如果它有问题,请提出建议。我尝试了 24 位和 32 位作为 bmiHeader.biBitCount 的值。
// Setup proper backbuffer:
_CleanupBackBufferStuff();
_pMemDc = new CDC;
_pMemDc->CreateCompatibleDC(&aDC);
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = _sizeBackBuffer.cx;
bmi.bmiHeader.biHeight = -_sizeBackBuffer.cy; // top-down
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24; // Tried 32 as well
bmi.bmiHeader.biCompression = BI_RGB;
unsigned char *pBitmapRawBits = 0;
HANDLE hMemBitmap = CreateDIBSection(aDC.GetSafeHdc(), &bmi, DIB_RGB_COLORS, (void**)&pBitmapRawBits, 0, 0);
_hOldSelBitmap = (HBITMAP)_pMemDc->SelectObject(hMemBitmap);
这里还有 StretchBlt 的代码(这里没什么特别的):
pDC->SetStretchBltMode(HALFTONE);
SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0);
BOOL bSuccess = pDC->StretchBlt(rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(),
_pMemDc, rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), SRCCOPY);
StretchBlt 返回真,(pDC->GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT) 也是真。
更新:在 Adrian 发表评论后,我将代码更改为使用 StretchDIBits。问题还是一样!以下是我目前正在使用的代码:
// Copy back buffer to screen dc:
pDC->SetStretchBltMode(HALFTONE);
SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0);
HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap);
DWORD dwLines = StretchDIBits(pDC->GetSafeHdc(),
rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(),
rectClipBoxBackBuffer.left, _sizeBackBuffer.cy - rectClipBoxBackBuffer.top - rectClipBoxBackBuffer.Height(), rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(),
_pBitmapRawBits, &_bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
_pMemDc->SelectObject(hMemBitmap);
它仍然表现得像源坐标不正确。它要么打印前几页之一(无论我选择什么页面),要么打印几乎全黑的页面。打印预览运行良好,所以这让我认为我的坐标计算代码应该没有问题。它在预览中工作,它与虚拟(pdf)打印机一起工作,在实际打印机上打印时失败。什么鬼?....
【问题讨论】:
-
你需要使用设备兼容的位图而不是我猜的 DIB。
-
我无法使用 CreateCompatibleBitmap,因为它无法用于大型位图。
标签: visual-c++ mfc gdi