如何在打印机上打印DIB后备缓冲区-GDI,MFC [英] How to print DIB backbuffer on printer - GDI, MFC

查看:151
本文介绍了如何在打印机上打印DIB后备缓冲区-GDI,MFC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MFC的doc/view体系结构来实现打印.我使用双缓冲,将所有内容绘制到我的后缓冲区即DIB位图上.比起我使用StretchBlt将该DIB复制到打印机DC上.

I'm using MFC's doc/view architecture to implement printing. I use double buffering, I draw everything onto my backbuffer which is DIB bitmap. Than I use StretchBlt to copy that DIB onto printer DC.

奇怪的是-打印预览效果很好!当我在虚拟PDF打印机上打印时,它运行良好!但是,当我在实际打印机上打印时(我正在两台不同的打印机上进行测试-结果相同)-它只会打印垃圾". 垃圾"表示有时会打印出全黑的页面,有时会重复打印出前几页,即,打印出DIB的错误部分,就像我将坐标弄乱了StretchBlt一样,但是我没有弄乱任何东西,所以我检查了一下多次,那么为什么打印预览可以正常工作?

The strange thing is - print preview is working well! When I print on virtual PDF printer, it is working well! But when I print on actual printer (I'm testing on two different printers - same results) - it just prints "garbage". The "garbage" means sometimes it prints totally black page, sometimes it prints the first few pages repeatedly, i.e. it prints wrong part of DIB, just like if I messed up coordinates to StretchBlt, but I didn't mess anything up, I checked multiple times, plus why is print preview is working flawlessly then?

我尝试了许多变体:

  1. 在打印时,使用与屏幕DC兼容的DC存储器.
  2. 使用与打印机DC兼容的内存DC,然后在其中选择我的DIB.
  3. 使用与打印机DC兼容的内存DC,并使用专用的DIB,将我的原始后备缓冲区DIB复制到该DC. 等
  1. Using memory DC compatible to screen DC, when printing.
  2. Using memory DC compatible to printer DC, and selecting my DIB into it.
  3. Using memory DC compatible to printer DC, and using dedicated DIB onto which I copy my original backbuffer DIB. etc.

但是结果是一样的.下面是我创建DIB的代码.我认为DIB格式可能是问题所在,因此如果存在问题,请提出建议.我尝试了24位和32位作为bmiHeader.biBitCount的值.

But the results are same. Below is the code where i create the DIB. I think the DIB format might be the problem, so please advice if there is something wrong with it. I tried both 24 bits and 32 bits as values for 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的代码(这里没什么特别的):

Also here is the code for StretchBlt (nothing special here):

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返回true,(pDC->GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT)也是如此.

StretchBlt returns true, also (pDC->GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT) is true as well.

更新:在Adrian发表评论之后,我将代码更改为使用StretchDIBits.问题还是一样的!下面是我当前正在使用的代码:

UPDATE: After Adrian's comment, I changed my code to use StretchDIBits. The problem is still the same! Below is the code I'm using currently:

// 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)打印机一起使用,在实际打印机上打印时会失败.什么鬼?....

It still behaives like the source coordinates are incorrect. It either prints one of first few pages (no matter what page I select), or prints almost-fully-black pages. The print preview is working perfectly, so this makes me think there should be no problems with my coordinate-calculation code. It works in preview, it works with virtual (pdf) printer, it fails when printing on actual printer. What the hell?....

推荐答案

请确保您一次没有将DIBSECTION选择为多个DC.这可能会导致各种不可预测的行为.

Make sure you don't have the DIBSECTION selected into more than one DC at a time. That can cause all sorts of unpredictable behavior.

对于打印,如果您方便使用bmipBitmapRawBits,则可以完全绕开内存DC.确保未将DIBSECTION选入 any DC中,然后调用

For printing, you can probably bypass the memory DC altogether if you keep your bmi and pBitmapRawBits handy. Make sure the DIBSECTION is not selected into any DC, and then call SetDIBitsToDevice or StretchDIBits to transfer the image to the printer DC.

如果仍然有问题,则可能需要检查打印机的功能.并非所有驱动程序都支持所有位图传输方法.我相信打印系统应该向您隐藏这些差异,但也许不是.在打印机上调用 GetDeviceCaps DC,然后在RASTERCAPS中查看RC_BITBLT和朋友.

If you're still having problems, you might want to check the capabilities of your printers. Not all the drivers support all the bitmap transfer methods. I believe the printing system is supposed to hide those differences from you, but perhaps not. Call GetDeviceCaps on your printer DC, and check the RASTERCAPS for RC_BITBLT and friends.

这篇关于如何在打印机上打印DIB后备缓冲区-GDI,MFC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆