2015-03-13 65 views
1

我繼承了一個老派的MFC Windows CE程序,並且不得不對其進行一些修改。作爲其中的一部分,我必須創建一個包含文本的單色圖像,並將其顯示在屏幕上,並將圖像的每一行一次發送到打印機。創建,顯示並訪問位圖/ DIB數據(不帶GetBitmapBits())

我最初使用了一個位圖,並且使用DrawText()成功地獲得了一個測試字符串(Hello World)來顯示在屏幕上(這段代碼如圖1所示)。然而,在我期望從位圖中提取換行數據的階段,我碰到了一堵牆。我試圖得到的是1或0表示黑色或白色的數組。我第一次以爲我會使用GetBitmapBits(),但不幸的是,我正在使用的代碼太老了,以至於不支持函數。我想我可以通過使用GetBitmap()來解決這個問題,然後訪問bmBits參數。但是,這似乎始終爲空,這是確認當我找到以下鏈接:Why does GetObject return an BITMAP with null bmBits?

我的下一個嘗試是遵循鏈接中的建議並使用CreateDIBSection()而不是CreateCompatibleBitmap()。這似乎是正確的路徑,我應該可以訪問我想要的數據,但不幸的是我無法顯示DIB(代碼如圖2所示)。我懷疑我在創建DIB頭部時做了錯誤,但我無法弄清楚我的錯誤是什麼。

如果有人對訪問位圖中的數據的方式有任何建議,或者可以看到我在DIB上做了什麼錯誤,我將非常感謝幫助!

***圖1:代碼來創建和顯示位圖

void CRunPage::OnPaint() 
{ 
    CPaintDC dc(this);   // property page device context for painting 
    CBitmap mBmp;    // CBitmap object for displaying built-in bitmaps 
    CDC mDCMem;     // CDC object to handle built-in bitmap 
    int iWidth, iHeight;  // dimension to draw on the screen 

    int icurLabel,    // current label index of open print file 
     iLabelNum;    // number of labels in open print file 
    LPBITMAPINFOHEADER pBMIH; // bitmap header object for current label 
    LPBYTE pImage;    // bitmap data for current label 
    CSize size;     // size of label 
    int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight; 
    CRect Rect; 
    BITMAP bm; 
    LPVOID bmBits=NULL; 

    // Calculate the preview area 
    PreviewLeft=5; 
    PreviewTop=5; 
    GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect); 
    ScreenToClient(&Rect); 
    PreviewWidth=Rect.left-PreviewLeft*2; 
    GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect); 
    ScreenToClient(&Rect); 
    PreviewHeight=Rect.top-PreviewTop*2; 

    CRect textRect; 
    CString testText(_T("Hello World")); 

    CBitmap * pOldBitmap; 
    CBrush whiteBrush, *pOldBrush; 
    CPen blackPen, *pOldPen; 


    mDCMem.CreateCompatibleDC(&dc); 

    mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2); 
    //mBmp.CreateCompatibleBitmap(&dc, PreviewWidth, PreviewHeight); 
    pOldBitmap = mDCMem.SelectObject(&mBmp); 

    blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); 
    whiteBrush.CreateSolidBrush(RGB(255,255,255)); 

    textRect.SetRect(0,0,PreviewWidth, PreviewHeight); 

    // this means behind the text will be a white box w/ a black boarder 
    pOldBrush = mDCMem.SelectObject(&whiteBrush); 
    pOldPen = mDCMem.SelectObject(&blackPen); 

    //these commands draw on the memory-only context (mDCMem) 
    mDCMem.Rectangle(&textRect); 
    mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER); 

    mDCMem.SelectObject(pOldBrush); 
    mDCMem.SelectObject(pOldPen); 

    dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY); 

    mDCMem.SelectObject(pOldBitmap); 

} 

***圖2:想使用DIB代替位圖

void CRunPage::OnPaint() 
{ 

    CPaintDC dc(this);   // property page device context for painting 

    CBitmap mBmp;    // CBitmap object for displaying built-in bitmaps 
    CDC mDCMem;     // CDC object to handle built-in bitmap 
    int iWidth, iHeight;  // dimension to draw on the screen 

    int icurLabel,    // current label index of open print file 
     iLabelNum;    // number of labels in open print file 
    LPBITMAPINFOHEADER pBMIH; // bitmap header object for current label 
    LPBYTE pImage;    // bitmap data for current label 
    CSize size;     // size of label 
    int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight; 
    CRect Rect; 
    BITMAP bm; 

    // Calculate the preview area 
    PreviewLeft=5; 
    PreviewTop=5; 
    GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect); 
    ScreenToClient(&Rect); 
    PreviewWidth=Rect.left-PreviewLeft*2; 
    GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect); 
    ScreenToClient(&Rect); 
    PreviewHeight=Rect.top-PreviewTop*2; 

    CRect textRect; 
    CString testText(_T("Hello World")); 

    CBitmap * pOldBitmap; 
    CBrush whiteBrush, *pOldBrush; 
    CPen blackPen, *pOldPen; 

    LPBYTE pFWandImageMem=NULL, pImageMem=NULL, pTemp=NULL; 
    int i=0,j=0, buffSize=0, numBytesPerRow=0, bitmapWidthPix,bitmapHeightPix; 

    char *numBytesPerRowString; 
    char temp; 
    void ** ppvBits; 
    BITMAPINFOHEADER bmif; 
    BITMAPINFO bmi; 
    HBITMAP myDIB, myOldDIB; 

    mDCMem.CreateCompatibleDC(&dc); 

    //this rect is the area in which I can draw (its x,y location is set by BitBlt or StretchBlt 
    //mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2); 

    bmif.biSize = sizeof(BITMAPINFOHEADER); 
    bmif.biWidth = PreviewWidth+PreviewLeft*2; 
    bmif.biHeight = -(PreviewHeight+PreviewTop*2);//- means top down (I think? I tried both ways and neither worked) 
    bmif.biPlanes = 1; 
    bmif.biBitCount = 1; 
    bmif.biCompression = BI_RGB; // no compression 
    bmif.biSizeImage = 0; // Size (bytes) if image - this can be set to 0 for uncompressed images 
    bmif.biXPelsPerMeter = 0; 
    bmif.biYPelsPerMeter = 0; 
    bmif.biClrUsed =0; 
    bmif.biClrImportant = 0; 

    bmi.bmiColors[0].rgbBlue=0; 
    bmi.bmiColors[0].rgbGreen=0; 
    bmi.bmiColors[0].rgbRed=0; 
    bmi.bmiColors[0].rgbReserved=0; 
    bmi.bmiColors[1].rgbBlue=255; 
    bmi.bmiColors[1].rgbGreen=255; 
    bmi.bmiColors[1].rgbRed=255; 
    bmi.bmiColors[1].rgbReserved=0; 

    bmi.bmiHeader=bmif; 

    myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0); 

    myOldDIB = (HBITMAP)mDCMem.SelectObject(myDIB);//SelectObject(mDCMem, myDIB); 
blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); 
whiteBrush.CreateSolidBrush(RGB(255,255,255)); 

textRect.SetRect(0,0,PreviewWidth, PreviewHeight); 

// this means behind the text will be a white box w/ a black boarder 
pOldBrush = mDCMem.SelectObject(&whiteBrush); 
pOldPen = mDCMem.SelectObject(&blackPen); 

//these commands draw on the memory-only context (mDCMem) 
mDCMem.Rectangle(&textRect); 
mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER); 

mDCMem.SelectObject(pOldBrush); 
mDCMem.SelectObject(pOldPen); 

dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY); 

mDCMem.SelectObject(myOldDIB); 

}

回答

0

所以我對DIB代碼做了兩處小改動,現在它正確地顯示圖像。

首先,我改變了我在我的指針傳遞到CreateDIBSection()的方式:

void ** ppvBits; 

LPBYTE pBits; 

然後,我不得不改變我如何傳遞到這CreateDIBSection。我也明確鑄造CreateDIBSection()的一個HBITMAP回:

myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); 

myDIB = (HBITMAP) CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0); 

我還沒有機會看到,如果我可以訪問圖像數據,但我過去現在最初的問題。感謝任何看過這個的人,如果人們知道如何做第一個(設備相關位圖)方法,我會很有興趣知道。