OnEraseBkgnd стирает нарисованную картинку.
У меня есть диалог и управление вкладками на нем. Мне нужно нарисовать картинку в определенном прямоугольнике на странице элемента управления Tab. Поэтому я объявляю объект класса, который отвечает за работу с растровыми изображениями, например CDIBitmap m_bmpBackground. Растровый файл загружается с помощью:
BOOL CDIBitmap :: Load( CFile* pFile ) { ASSERT( pFile ); BOOL fReturn = TRUE; try { delete [] (BYTE*)m_pInfo; delete [] m_pPixels; m_pInfo = 0; m_pPixels = 0; DWORD dwStart = pFile->GetPosition(); // // Check to make sure we have a bitmap. The first two bytes must // be 'B' and 'M'. BITMAPFILEHEADER fileHeader; pFile->Read(&fileHeader, sizeof(fileHeader)); if( fileHeader.bfType != 0x4D42 ) throw TEXT("Error:Unexpected file type, not a DIB\n"); BITMAPINFOHEADER infoHeader; pFile->Read( &infoHeader, sizeof(infoHeader) ); if( infoHeader.biSize != sizeof(infoHeader) ) throw TEXT("Error:OS2 PM BMP Format not supported\n"); // Store the sizes of the DIB structures int cPaletteEntries = GetPalEntries( infoHeader ); int cColorTable = 256 * sizeof(RGBQUAD); int cInfo = sizeof(BITMAPINFOHEADER) + cColorTable; int cPixels = fileHeader.bfSize - fileHeader.bfOffBits; // // Allocate space for a new bitmap info header, and copy // the info header that was loaded from the file. Read the // the file and store the results in the color table. m_pInfo = (BITMAPINFO*)new BYTE[cInfo]; memcpy( m_pInfo, &infoHeader, sizeof(BITMAPINFOHEADER) ); pFile->Read( ((BYTE*)m_pInfo) + sizeof(BITMAPINFOHEADER), cColorTable ); // // Allocate space for the pixel area, and load the pixel // info from the file. m_pPixels = new BYTE[cPixels]; pFile->Seek(dwStart + fileHeader.bfOffBits, CFile::begin); pFile->Read( m_pPixels, cPixels ); CreatePalette(); m_bIsPadded = TRUE; #ifdef _DEBUG } catch( TCHAR * psz ) { TRACE( psz ); #else } catch( TCHAR * ) { #endif fReturn = FALSE; } return fReturn; }
Затем я вызываю функцию Invalidate() и попадаю в OnEraseBkgnd, где на самом деле рисуется картинка:
BOOL CAtmNcr::OnEraseBkgnd(CDC* pDC) { if(m_bmpBackground.GetPixelPtr() != 0) { CRect rc; m_myWnd.GetWindowRect(rc); ScreenToClient( &rc ); int x = 0, y = 0; // center the bitmap /* CDialog::OnEraseBkgnd(pDC); x = (rc.Width() - m_bmpBackground.GetWidth()) / 2; y = (rc.Height() - m_bmpBackground.GetHeight()) / 2; m_bmpBackground.DrawDIB(pDC, x, y); */ // stretch m_bmpBackground.DrawDIB(pDC, rc.left, rc.top, rc.Width(), rc.Height()); } else // no bitmap set. behave like a normal dialog return CDialog::OnEraseBkgnd(pDC); return true; }
DrawDIB определяется следующим образом:
// DrawDib uses StretchDIBits to display the bitmap. void CDIBitmap :: DrawDIB( CDC* pDC, int x, int y, int width, int height ) { ASSERT( pDC ); HDC hdc = pDC->GetSafeHdc(); if( m_pInfo ) StretchDIBits( hdc, x, y+GetHeight(), width, -height, 0, 0, GetWidth(), GetHeight(), GetPixelPtr(), GetHeaderPtr(), DIB_RGB_COLORS, SRCCOPY ); }
Загруженная картинка определенно нарисована в прямоугольнике, и вы видите ее, но до тех пор, пока не останется OnEraseBkgnd. Как же так? Если вы применяете тот же код к родительскому диалоговому окну, то он отлично работает.