首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用GDI (MFC)实现DIB打印

无法使用GDI (MFC)实现DIB打印
EN

Stack Overflow用户
提问于 2012-01-27 16:40:18
回答 2查看 1.1K关注 0票数 0

MFC文档/视图架构,GDI绘图/打印。我有一个DIB后台缓冲区,我需要显示和打印。

经过漫长而痛苦的过程后,我得出的结论是,我需要使用由CreateDIBSection创建的DIB (而不是使用CreateCompatibleBitmap创建的DDB ),并且我必须使用StretchDIBits (而不是StretchBlt)将其写入打印机dc。

但我没法让这玩意儿动起来。

下面是我要做的:

在我的初始化例程中,我设置了后台缓冲区,如下所示:

代码语言:javascript
复制
// 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);

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

代码语言:javascript
复制
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覆盖中所做的事情:

首先,我将绘制的区域如下所示(简化代码):

代码语言:javascript
复制
CRect rectClipBoxPlayground;

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

然后,我在后台缓冲区中计算相应的rect坐标,它通常比DC大得多。这个计算的细节在这里无关紧要,我只想说

代码语言:javascript
复制
CRect rectClipBoxBackBuffer;

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

然后,我使用_pMemDc内存dc绘制我的后台缓冲区。

最后是我遇到麻烦的地方:把我的DIB传输到目标dc (屏幕或打印机)。下面是我要做的:

代码语言:javascript
复制
// 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。请注意,我首先暂时从DIB的内存dc中取消选择,这样它就不会与任何dc关联。然后我使用了StretchDIBits,但就是不能工作!输出是混乱的,就像我给出了错误的坐标一样,区域的绘制偏离了它们应该绘制的位置,有时完全是黑色的。所以我一定遗漏了一些东西(可能是非常微不足道的东西)。帮助!我尝试更改rectClipBoxBackBuffer.top和bitmapInfo.bmiHeader.biHeight的符号,结果发生了变化,但没有任何东西像它应该的那样工作。

我做错了什么??

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-29 04:01:06

微软关于StretchDIBits的文档是完全错误的。我发现Y轴的方向必须改变。现在,以下代码可以正常工作:

代码语言:javascript
复制
// 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);

附言:现在它可以用于屏幕绘图和打印预览,但在实际打印时失败,这是我在这里讨论的原始问题:How to print DIB backbuffer on printer - GDI, MFC

票数 0
EN

Stack Overflow用户

发布于 2012-01-29 01:24:43

如果要使用StretchDIBits,请不要选择DIB into/out DC。DC只能包含DDB位图,如果您提供DIB,DC将对其进行转换。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9030747

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档