Я унаследовал программу MFC Windows CE старой школы, и мне нужно внести в нее некоторые изменения. В рамках этого я должен создать монохромное изображение с текстом на нем, и оба отображать его на экране, а также отправлять каждую строку изображения на принтер по одному.Создание, отображение, а затем доступ к данным растрового изображения/DIB (без GetBitmapBits())
Первоначально я использовал растровое изображение и имел успех с использованием 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);
}