Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Борьба с мерцанием — более сложный случай


Автор: kometa_triatlon 8.5.2006, 22:55
Уже не раз поднималась тема про двойную буферизацию, но у меня это получалось в более-менее простых случаях - там рисование графика например. Когда весь код прорисовки заключается в dc->LineTo и расположен в OnPaint/OnDraw.

А теперь пишу программу, в которой некий класс сам себя рисует, получая в качестве параметров контексты CPaintDC и CDC. Причем выводит также битмапы. Короче я не смог прикрутить эту буферизацию  smile 
Подскажите как быть? В какое место вообще вставлять эти макросы, где брать указатель на контекст CDC?

Код

void CMyDlg::OnPaint() 
{
    /...

    InvalidateRect(NULL);
    CPaintDC dc(this);
    CDC memDC;
    
    m_board.DrawSelf( &dc, &memDC);
}



void CBoard::DrawSelf( CPaintDC* dc, CDC* memDC )
{
    CPen pen(PS_SOLID, 1, RGB(0,0,0));
    CPen SelectLinePen(PS_SOLID, 2, RGB(255,0,0));
    CBrush brush;
    brush.CreateSolidBrush( ::GetSysColor( COLOR_BTNFACE ) );


    dc->SelectObject(&pen);
    dc->SelectObject( &brush );
    // рисуем рамки
    dc->Rectangle(PADDING-20, PADDING-20, PADDING+8*CELL_WIDTH+20, PADDING+8*CELL_WIDTH+20 );
    dc->Rectangle(PADDING-1, PADDING-1, PADDING+8*CELL_WIDTH+1, PADDING+8*CELL_WIDTH+1 );

    // рисуем клетки
    for( int i=0; i<8; i++ )
        for( int j=0; j<8; j++ )
        {
            dc->FillSolidRect( CRect(
                       PADDING+i*CELL_WIDTH, 
                       PADDING+j*CELL_WIDTH, 
                       PADDING+(i+1)*CELL_WIDTH, 
                       PADDING+(j+1)*CELL_WIDTH), 
                
                ( ((i+j)%2) ? RGB(0,0,0) : RGB(255,255,255) )); // если сумма индексов четная, то белым, иначе черным
        }


    // рисуем шашки
    memDC->CreateCompatibleDC(dc);

    for( int i =0; i<8; i++ )
        for( int j=0; j<8; j++ )
        {
            if( m_board[i][j].m_bHasChecker )
            {
                switch( m_board[i][j].m_CheckerColor ) // в зависимости от цвета шашки выбираем битмап
                {
                case white:
                    memDC->SelectObject( &m_bmpWhiteChecker );
                    break;

                case black:
                    memDC->SelectObject( &m_bmpBlackChecker );
                    break;

                default:break;
                }
                // рисуем
                dc->BitBlt( PADDING+i*CELL_WIDTH, PADDING+j*CELL_WIDTH, CELL_WIDTH, CELL_WIDTH,    memDC,0,0,SRCCOPY);
                if( m_board[i][j].m_bIsSelected  )
                {
                    dc->SelectObject( &SelectLinePen );
                    dc->MoveTo(PADDING+i*CELL_WIDTH+1, PADDING+j*CELL_WIDTH+1);
                    dc->LineTo(PADDING+(i+1)*CELL_WIDTH-1, PADDING+j*CELL_WIDTH+1);
                    dc->LineTo(PADDING+(i+1)*CELL_WIDTH-1, PADDING+(j+1)*CELL_WIDTH-1);
                    dc->LineTo(PADDING+i*CELL_WIDTH+1,  PADDING+(j+1)*CELL_WIDTH-1);
                    dc->LineTo(PADDING+i*CELL_WIDTH+1, PADDING+j*CELL_WIDTH+1);
                }
            }

            if( m_board[i][j].m_bPossibleMove ) 
            {
                dc->SelectObject( &SelectLinePen );
                dc->MoveTo(PADDING+i*CELL_WIDTH+1, PADDING+j*CELL_WIDTH+1);
                dc->LineTo(PADDING+(i+1)*CELL_WIDTH-1, PADDING+j*CELL_WIDTH+1);
                dc->LineTo(PADDING+(i+1)*CELL_WIDTH-1, PADDING+(j+1)*CELL_WIDTH-1);
                dc->LineTo(PADDING+i*CELL_WIDTH+1,  PADDING+(j+1)*CELL_WIDTH-1);
                dc->LineTo(PADDING+i*CELL_WIDTH+1, PADDING+j*CELL_WIDTH+1);
            }
        }


    dc->SetBkColor(::GetSysColor( COLOR_BTNFACE));
    

    // номера по горизонтали
    for( int i=0; i<8; i++ )
    {
        CString str;
        str.Format("%d", i+1 );
        dc->TextOut(PADDING+i*CELL_WIDTH+CELL_WIDTH/2, PADDING-18, str);
    }

}
 

Автор: SergeCpp 10.5.2006, 07:54
Рисуйте не в dc, а в memDC, а потом BitBlt...

Кстати, memDC не просто так создаётся...

Короче, вот файл (+ EXE), где всё это мною делалось в былые времена...

Могу и все исходники выложить, если заинтересуетесь... 

Автор: kometa_triatlon 10.5.2006, 16:10
Код

   CDC * pDCDest=GetDC();    
        CDC dcMem;    
        dcMem.CreateCompatibleDC(pDCDest);    
        CBitmap *pPrevBmpMem=dcMem.GetCurrentBitmap();    
        CRect rCl;    
        GetClientRect(rCl);    
        CBitmap BmpNewMem;    
        BmpNewMem.CreateCompatibleBitmap(pDCDest, rCl.Width(), rCl.Height());    
        dcMem.SelectObject(&BmpNewMem);    
        dcMem.FillSolidRect(rCl, RGB(255,255,255));    
        CDC *pDCTemp=pDCDest;    
        pDCDest=&dcMem;    


             CDC memDC;    
     
             m_board.DrawSelf( pDCDest, &memDC);    


        pDCDest=pDCTemp;    
        pDCDest->BitBlt(rCl.left, rCl.top, rCl.Width(), rCl.Height(), &dcMem,rCl.left, rCl.top, SRCCOPY);    
        dcMem.SelectObject(pPrevBmpMem);
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)