2012-01-27 5 views
0

MFCドキュメント/ビューアーキテクチャ、GDI描画/印刷。私は表示して印刷する必要があるDIBバックバッファを持っています。GDI(MFC)でDIB印刷を実装できません

私は、CreateDIBSection(CreateCompatibleBitmapで作成されたDDBではなく)で作成されたDIBを使用する必要があると判断し、StretchBltではなくStretchDIBitsでプリンタdcにblitする必要があります。

しかし、私はこのことを動作させることができません。ここで

は、私が何をすべきかです:私の初期化ルーチンで

、Iセットアップバックバッファ、次のように:アンダースコアで

// 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よりも(かなり)大きい私のバックバッファ内の対応するRECT座標を計算します。この計算の詳細は、私はちょうど

CRect rectClipBoxBackBuffer; 

は(バックバッファのピクセル座標における)バックバッファの対応する四角形を表すと言う、ここでは無関係です。

次に、_pMemDcメモリdcを使用してバックバッファに描画します。

最後に、私は問題を抱えている部分があります。ターゲットDc(スクリーンまたはプリンタ)にDIBをブリッティングします。ここでは、私が何をすべきかです:

// 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の兆候を変更しようとしましたが、結果は変わりましたが、何もうまくいかないように動作します。

私は何が間違っていますか?

+0

追加情報: 'StretchDIBits'呼び出しが成功しました。 DIB。私はその数がドキュメントごとに 'rectClipBoxBackBuffer.Height()'と等しくなることを期待しています。これは 'StretchDIBits'が"スキャンライン数**コピー** "を返すと言います。私はこれがどんなヒントかもしれないかどうかわかりません。 –

+0

痛いほど痛いです。 '#include ' –

+0

残念ながらHans、GDI +は自分のやることには遅すぎます。 –

答えて

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を使用する場合は、DCをDIBに/ DCから選択しないでください。 DCにはDDBビットマップしか含めることができません.DIBを指定すると、DCはそれを変換します。

関連する問題