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


Автор: SmarTi 20.9.2006, 21:33
Всем доброго времени суток. Сразу прошу меня извинить за создание такой темы. Но прочитав всё что мне удалось найти на форуме, я так и не понял как решить мою проблему.
Проблема заключается в следущем : 
Я рисую сетку  в SDI и заполняю её очень быстро квадратами (до 20 раз в секунду),кто писал "Жизнь" тот поймёт в чём речь. Естественно при перерисовке окна появляется мерцание smile 
На сколько я понял BitBlt работает только для битмапов... так как же избавится от мерцаний ?
Можно както сделать сетку постоянным фоном ?

Автор: vinter 20.9.2006, 22:22
используй двойную буферизацию..
суть такова: сначала создаешь контекст в памяти, потом в нем рисуешь, а потом BitBlt на основной контекст.
пример
Код

CFont *OldFont;
    CDC dcMemory;
    dcMemory.CreateCompatibleDC(&FontDC);
    CRect rect;
    GetClientRect(&rect);
    CBitmap bitmap, *pBitmap;
    bitmap.CreateCompatibleBitmap(&FontDC, rect.right, rect.bottom);
    pBitmap = dcMemory.SelectObject(&bitmap);
    dcMemory.SetBkMode(TRANSPARENT);
    dcMemory.SetBkColor(RGB(255, 255, 255));
    dcMemory.Rectangle(rect);
    LOGFONT lfFont = {
        100,
            0,
            100,
            100,
            FW_EXTRABOLD,
            0,
            0,
            0,
            DEFAULT_CHARSET,
            OUT_DEFAULT_PRECIS,
            CLIP_DEFAULT_PRECIS,
            PROOF_QUALITY,
            VARIABLE_PITCH | FF_DONTCARE,
            "Arial"
    };
    m_Font.CreateFontIndirect(&lfFont);
    OldFont = dcMemory.SelectObject(&m_Font);
    dcMemory.SetTextColor(RGB(255,0,0));
    lfFont.lfEscapement = -100;
    m_Font.DeleteObject();
    m_Font.CreateFontIndirect(&lfFont);
    dcMemory.SelectObject(&m_Font);
    dcMemory.SetTextColor(RGB(255,255,0));
    dcMemory.TextOut(20, 200, _T("Версия "));
    m_Font.DeleteObject();
    lfFont.lfEscapement = 0;
    m_Font.CreateFontIndirect(&lfFont);
    dcMemory.SelectObject(&m_Font);
    dcMemory.SetTextColor(RGB(0,255,0));
    dcMemory.TextOut(200, 350, _T(" 1.0"));
    FontDC.BitBlt(0, 0, rect.right, rect.bottom, &dcMemory, 0, 0, SRCCOPY);
    dcMemory.SelectObject(OldFont);
    m_Font.DeleteObject();

Автор: SergeCpp 20.9.2006, 22:42
Жизнь!!! Завтра прикреплю сюда свои исходники smile

И exe-шник smile

P.S. Словарь Жизни есть? Ссылку давать?

Добавлено @ 22:51 
Вспомнил! http://forum.vingrad.ru/index.php?showtopic=88787&view=findpost&p=682081 я уже выкладывал!

Сетка не нужна! Квадраты — их два вида — уже должны содержать в себе сетку

На границах. В исходнике есть всё. Если чего не будет, пишите ПМ. Всё расскажу!

Занимался этой задачей smile

500 в секунду smile (зависит от размеров, конечно же)

Удачи!

Автор: Sartorius 20.9.2006, 22:57
 А я тоже как-то жизнь писал...потом сделал, что бы клетки были нескольких видов(цветов). Очень интересно наблюдать как одна популяция вытесняет другую и т.п. 
SmarTi , можешь потом усложнить так...

Автор: SergeCpp 20.9.2006, 23:16
http://forum.vingrad.ru/index.php?showtopic=102936&view=findpost&p=782253, но архив почему-то больше

Скачайте оба и сверьте, может, где что пропустил

http://psoup.math.wisc.edu/Life32.html, хоть и старая, хоть и на Дельфи (не моя)
user posted image

http://pentadecathlon.com/dictionary/dictionary.php

http://rendell-attic.org/gol/tm.htm

http://rendell-attic.org/gol/turing_js_r.gif
user posted image

http://beluch.boom.ru/lifelex/lexr.htm

Автор: SmarTi 20.9.2006, 23:34
Цитата(vinter @ 20.9.2006,  22:22)
суть такова: сначала создаешь контекст в памяти, потом в нем рисуешь, а потом BitBlt на основной контекст.

Вот как я делаю : 
Код

void CLife1View::OnDraw(CDC* pDC)
{
    CLife1Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    
    CRect rect;
    GetClientRect(&rect);
    
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    CPen pen;
    pen.CreatePen(0,1,RGB(170,170,170));
    memDC.SelectObject(pen);
    //Рисую сетку
    for(int i=1;i<m_lMaxHor/4;i++)
    {
        memDC.MoveTo(i*4,0);
        memDC.LineTo(i*4,(int)m_lMaxVert);
    }
    for(i=1;i<m_lMaxVert/4;i++)
    {
        memDC.MoveTo(0,i*4);
        memDC.LineTo((int)m_lMaxHor,i*4);
    }
    pen.DeleteObject();
    //рисую квадраты там где нужно
    pen.CreatePen(0,1,RGB(0,0,0));
    memDC.SelectObject(pen);
    for(int i=0;i<=(int)m_lMaxHor/4;i++)
    {
        for(int j=0;j<=(int)m_lMaxVert/4;j++)
        {
            if(mas[i][j] == 1)
            {
                memDC.Rectangle(i*4-4,j*4-4,i*4,j*4);
            }
        }
    }
    //ну и собственно BitBlt
    pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);
}

И в результате просто белый экран... какбудто я и ничего не рисую... В чем может быть проблема ? 
SergeCpp, всё таки хочется разобратся с двойной буферизацией, а твоя "Жизнь" классная  smile 

Автор: SergeCpp 21.9.2006, 00:11
OnEraseBkgnd выброшена?

Сразу же return TRUE нужно

Добавлено @ 00:20 
P.S. спать хочу smile пока smile

Автор: SmarTi 21.9.2006, 00:20
Цитата(SergeCpp @ 21.9.2006,  00:11)
OnEraseBkgnd выброшена?

Сразу же return TRUE нужно

Если так делать то вообще каша получается... а рисовать то что нужно не хочет.

Автор: SmarTi 21.9.2006, 01:03
УРАААА! Получилось ! Я просто думал что Битмап тут не при чём smile
Получается так : 
Код

void CLife1View::OnDraw(CDC* pDC)
{
    CLife1Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    
    CRect rect;
    GetClientRect(&rect);
    
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    CBitmap bitmap, *pBitmap;
    bitmap.CreateCompatibleBitmap(pDC,(int)m_lMaxHor,(int)m_lMaxVert);
    pBitmap = memDC.SelectObject(&bitmap);
    memDC.SetBkMode(TRANSPARENT);
    memDC.SetBkColor(RGB(255, 255, 255));
    memDC.Rectangle(0,0,(int)m_lMaxHor,(int)m_lMaxVert);
    CPen pen;
    
    pen.CreatePen(0,1,RGB(170,170,170));
    memDC.SelectObject(pen);
    //Рисую сетку
    for(int i=1;i<m_lMaxHor/4;i++)
    {
        memDC.MoveTo(i*4,0);
        memDC.LineTo(i*4,(int)m_lMaxVert);
    }
    for(i=1;i<m_lMaxVert/4;i++)
    {
        memDC.MoveTo(0,i*4);
        memDC.LineTo((int)m_lMaxHor,i*4);
    }
    pen.DeleteObject();
    //рисую квадраты там где нужно
    pen.CreatePen(0,1,RGB(0,0,0));
    memDC.SelectObject(pen);
    for(int i=0;i<=(int)m_lMaxHor/4;i++)
    {
        for(int j=0;j<=(int)m_lMaxVert/4;j++)
        {
            if(mas[i][j] == 1)
            {
                memDC.Rectangle(i*4-4,j*4-4,i*4,j*4);
            }
        }
    }
    //ну и собственно BitBlt
    pDC->BitBlt(0,0,(int)m_lMaxHor,(int)m_lMaxVert,&memDC,0,0,SRCCOPY);
}

ну и конечно обработчик : 
Код

BOOL CLife1View::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

Вот если бы я сразу натнулся на примерно вот такой код.... эээх. Ладно, всем огромное СПАСИБО. Тема закрыта! иду спать smile

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