nuhop Ответов: 2

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. Как же так? Если вы применяете тот же код к родительскому диалоговому окну, то он отлично работает.

2 Ответов

Рейтинг:
2

strogg

Я думаю, что ваше изображение рисуется, но стирается на WM_PAINT. Попробуйте размыть изображение на WM_PAINT - хорошая идея, если вы рисуете на всем Родительском окне (ваша вкладка ctl). Или же я предлагаю вам сохранить статический контроль над размером & pos, который вы хотите & нарисовать на нем.

Кроме того, убедитесь, что вы рисуете на элементе управления страницей/окне, если вы их поддерживаете, а не на самом элементе управления вкладками, потому что фактический элемент управления вкладками будет находиться за ними.


Рейтинг:
0

nuhop

Спасибо, строгг. - Да, ты прав. WM_PAINT стер мою нарисованную картинку, так как я действительно использовал статический элемент управления, чтобы получить размер прямоугольника перед рисованием, и статический элемент управления был помещен поверх моей картинки в последнем. Поэтому я скрываю статический элемент управления, когда его размеры определены, и только тогда рисуется картинка. Я ценю вашу помощь и благодарю вас за ваше время.


strogg

Спасибо, чувак. Также обратите внимание на расширенный стиль окна WM_EX_TRANSPARENT (информация в CreateWindowEx()). Возможно, Вам это покажется интересным