2012-01-27 74 views
0

MFC文档/视图体系结构,GDI绘图/打印。我有一个DIB backbuffer,我需要显示和打印。无法使用GDI执行DIB打印(MFC)

经过漫长而痛苦的道路之后,我得出了比我需要使用CreateDIBSection创建的DIB(而不是使用CreateCompatibleBitmap创建的DDB)的结论,并且我必须用StretchDIBits(而不是StretchBlt)将其粘贴到打印机dc上。

但我无法得到这个东西的工作。

这里是我做的:

在我的初始化程序,我安装后备缓冲,就像这样:

// Prepare device context: 

CClientDC aDC(this); 
OnPrepareDC(&aDC); 

// Setup proper backbuffer: 

_pMemDc = new CDC; 
_pMemDc->CreateCompatibleDC(&aDC); 

memset(&_bitmapInfo, 0, sizeof(BITMAPINFO)); 

_bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
_bitmapInfo.bmiHeader.biWidth = _sizeBackBuffer.cx; 
_bitmapInfo.bmiHeader.biHeight = -_sizeBackBuffer.cy; // top-down 
_bitmapInfo.bmiHeader.biPlanes = 1; 
_bitmapInfo.bmiHeader.biBitCount = 24; // Maybe 32? 
_bitmapInfo.bmiHeader.biCompression = BI_RGB; 

HANDLE hMemBitmap = CreateDIBSection(aDC.GetSafeHdc(), &_bitmapInfo, DIB_RGB_COLORS, (void**)&_pBitmapRawBits, 0, 0); 

_hOldSelBitmap = (HBITMAP)_pMemDc->SelectObject(hMemBitmap); 

变量用下划线(私有)成员变量,声明如下:

CDC *_pMemDc; // Backbuffer memory dc 
HBITMAP _hOldSelBitmap; 

BITMAPINFO _bitmapInfo; // Backbuffer DIB (header-only) 
unsigned char *_pBitmapRawBits; // Pointer to pixel data of DIB 

SIZE _sizeBackBuffer; // Size of backbuffer, i.e. size of that DIB 

现在下面是我在我的OnDraw覆盖做:

杉木stly我得到的面积要绘制这样(简化代码):

CRect rectClipBoxPlayground; 

if (pDC->IsPrinting()) 
{ 
    rectClipBoxPlayground = _printingParams.pPrintInfo->m_rectDraw; 
} 
else 
{ 
    pDC->GetClipBox(&rectClipBoxPlayground); 
} 

然后,我计算我的后备缓冲,这通常是(多)比DC大相应的矩形坐标。这个计算的细节是无关紧要的这里,我只想说,

CRect rectClipBoxBackBuffer; 

表示后备缓冲区相应的矩形(像素后备缓冲的坐标)。

然后我使用_pMemDc内存直接绘制到我的后缓冲区。

终于出现了我有麻烦的部分:将我的DIB转移到目标dc(屏幕或打印机)上。这是我做的:

// Copy back buffer to screen/printer dc: 

pDC->SetStretchBltMode(HALFTONE); 
SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0); 

// BELOW COMMENTED CODE OF StretchBlt WORKS(!) INSTEAD OF StretchDIBits. 
// 
//BOOL bSuccess = pDC->StretchBlt(rectClipBoxPlayground.left, rectClipBoxPlayground.top, 
// rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), 
// _pMemDc, rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, 
// rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), SRCCOPY); 

HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap); 

DWORD dwLines = StretchDIBits(pDC->GetSafeHdc(), 
    rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), 
    rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), 
    _pBitmapRawBits, &_bitmapInfo, DIB_RGB_COLORS, SRCCOPY); 

_pMemDc->SelectObject(hMemBitmap); 

的问题是,StretchBlt函数被注释掉的代码完美的作品(除了某些打印机上打印),但因为某些打印机有它的烦恼,我不能使用它。所以我必须使用StretchDIBits。请注意,我首先暂时从内存dc中取消选择DIB,以便它不与任何直流相关联。然后我使用StretchDIBits,但事情不起作用!输出被搞乱了,就像我给出了不正确的坐标一样,区域从它们应该绘制的位置偏移,有时甚至全是黑色。所以我必须错过一些东西(也许是很平凡的东西)。帮帮我!我尝试改变rectClipBoxBackBuffer.top和bitmapInfo.bmiHeader.biHeight的符号,结果改变,但没有任何工作应该如此。

我在做什么错?

+0

其他信息:'StretchDIBits'调用成功 - 它返回的数字等于总高度DIB。我希望这个数字等于'rectClipBoxBackBuffer.Height()'根据文档,它说'StretchDIBits'返回“扫描行数**复制**”。我不知道这是否可以提示... – 2012-01-27 09:16:03

+0

有点痛苦的看。你已经准备好进入'#include ' – 2012-01-27 11:00:42

+0

不幸的是,汉斯,GDI +对于我所做的事情来说太慢了。 – 2012-01-27 11:25:35

回答

0

有关StretchDIBits的Microsoft文档是完全错误的。我发现Y轴的方向必须改变。现在下面的代码工程:

// 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); 

P.S.:现在它适用于屏幕绘图和打印预览,但实际打印失败,这是我在此讨论的原始问题:How to print DIB backbuffer on printer - GDI, MFC

0

如果您要使用StretchDIBits,则不要选择DIB输入/输出DC。 DC只能包含DDB位图,如果您提供DIB,DC会将其转换。