我继承了一个老式的MFC Windows CE程序,我不得不对它进行一些修改。作为其中的一部分,我必须创建一个带有文本的单色图像,并将其显示在屏幕上,并将每行图像一次发送到一台打印机。
我最初使用了一个位图,并成功使用了DrawText()并获得了一个测试字符串(Hello World)以显示在屏幕上(此代码如图1所示)。但是,在我想要从位图中提取包装数据的阶段,我碰到了一堵墙。我想要得到的是一个代表黑色或白色的1或0的数组。我首先想到我会使用GetBitmapBits()但不幸的是我正在使用的代码太旧了,以至于还不支持该功能。我以为我可以通过使用GetBitmap()然后访问bmBits参数来解决这个问题。但是,这似乎始终为null,当我找到以下链接时确认: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 :(得分: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);
我没有机会看到我是否可以访问图像数据,但我现在已经过了最初的问题。感谢任何看过这个的人,如果有人知道如何做第一个(设备相关的位图)方法,我很想知道。