2012-01-26 68 views
1

我正在使用MFC的doc/view體系結構來實現打印。我使用雙緩衝,我將所有東西都繪製到我的後臺緩衝區,這是DIB位圖。比我使用StretchBlt將該DIB複製到打印機DC上。如何在打印機上打印DIB backbuffer - GDI,MFC

奇怪的是 - 打印預覽效果很好!當我在虛擬PDF打印機上打印時,它運行良好!但是當我在實際打印機上打印時(我正在測試兩臺不同的打印機 - 相同的結果) - 它只是打印「垃圾」。 「垃圾」有時意味着它會打印完全黑色的頁面,有時它會重複打印前幾頁,即它會打印DIB的錯誤部分,就像我將座標搞亂到StretchBlt一樣,但我沒有弄亂任何東西,我檢查了多次,再加上爲什麼打印預覽工作完美無瑕呢?

我嘗試了許多變化:

  1. 使用內存DC兼容屏幕DC,打印時。
  2. 使用與打印機DC兼容的內存DC,並選擇我的DIB。
  3. 使用與打印機DC兼容的內存DC,並使用專用的DIB將複製我的原始backbuffer 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返回true,也(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)打印機一起工作,在實際打印機上打印時失敗。這到底是什麼?......

+0

您需要使用設備兼容的位圖而不是我猜測的DIB。 –

+0

我無法使用CreateCompatibleBitmap,因爲它對於大型位圖而言失敗。 –

回答

2

請確保您沒有將DIBSECTION一次選入多個DC。這可能會導致各種不可預知的行爲。

對於打印,如果您方便地保留bmipBitmapRawBits,則可以完全繞過內存直流電。確保DIBSECTION未被選入任何 DC,然後撥打SetDIBitsToDeviceStretchDIBits將圖像傳輸到打印機DC。

如果仍有問題,可能需要檢查打印機的功能。並非所有驅動程序都支持所有的位圖傳輸方法。我相信印刷系統應該隱藏你的差異,但也許不是。請在您的打印機DC上撥打GetDeviceCaps,然後查看RASTERCAPSRC_BITBLT和朋友。

+0

感謝您的回覆。至於GetDeviceCaps的東西,正如我已經說過的,'(pDC-> GetDeviceCaps(RASTERCAPS)&RC_STRETCHBLT)'是真的,所以應該沒有問題。無論如何,我認爲StretchDIBits會糾正這個問題,但我無法讓它工作!我在這裏發佈了另一個問題:http://stackoverflow.com/questions/9030747/unable-to-implement-dib-printing-with-gdi-mfc請給你的想法!再次感謝。 –

+0

更新:最後我得到了StretchDIBits代碼的工作(微軟錯誤的API文檔浪費了我一天的一半!),但是......問題仍然存在! WTF?!...... –

+0

您是否在打印機DC中使用了不尋常的映射模式?不尋常的是,我的意思是「MM_TEXT」以外的任何東西。我也懷疑您更新的代碼示例中的_Ysrc_參數的計算。 –