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


Автор: Kolia 22.10.2006, 01:42
Имею void CSaverWnd::OnPaint() (CWnd->CSaverWnd)
Ее могу реализовать в двух вариантах.
Первый. Он работает, но есть мерцание:
Код

void CSaverWnd::OnPaint() 
{
    CPaintDC dc(this); // device context for painting
    this->m_table.DrawTable(&dc);
}



Второй. С буферизацией.
Код

void CSaverWnd::OnPaint() 
{
    CDC *pDC;
    CDC dcMem;
    CBitmap *pOldBmpMem;
    CBitmap BmpNewMem;
    CRect rCl;
    BOOL ret;

    pDC = this->GetDC();
    this->GetClientRect(&rCl);

    dcMem.CreateCompatibleDC(pDC);
    BmpNewMem.CreateCompatibleBitmap(pDC, rCl.Width(), rCl.Height());

    pOldBmpMem = dcMem.SelectObject(&BmpNewMem);

    this->m_table.DrawTable(&dcMem);

    pDC->BitBlt(0, 0, rCl.Width(), rCl.Height(), &dcMem, 0, 0, SRCCOPY);

    dcMem.SelectObject(pOldBmpMem);
    BmpNewMem.DeleteObject();
    dcMem.DeleteDC();
    ReleaseDC(pDC);
}


В программе есть таймер, который через определенное время обновляет данные и заставляет окно перерисовываться. Проблема в том, что если я реализую OnPaint() вторым способом, то никакого обновления данных не происходит. Я вписал в нее строки

Код

...
    this->m_table.CalculateSchedulePos(); //тут что-то меняется с данными
    this->m_table.DrawTable(&dcMem);
...

Тогда все начало меняться. Но делается это естественно не после сообщения таймера. То есть такое чувство, что программа из этой функции не выходит, а в ней и зацикливается. И не реагирует не на какие сообщения таймера. Понимаю, что чего-то не учел, но чего не пойму. smile 

Добавил в конец
Код

CWnd::OnPaint();

и заработало. Может кто пояснит сей факт... smile 

Автор: Step 23.10.2006, 11:24
Цитата(Kolia @  22.10.2006,  01:42 Найти цитируемый пост)
В программе есть таймер, который через определенное время обновляет данные и заставляет окно перерисовываться. Проблема в том, что если я реализую OnPaint() вторым способом, то никакого обновления данных не происходит. Я вписал в нее строки

а как она заставляет

Автор: maxim1000 23.10.2006, 11:41
Цитата(Kolia @ 22.10.2006,  00:42)
Добавил в конец
Код

CWnd::OnPaint();

и заработало. Может кто пояснит сей факт... smile

может, в нём вызывалось EndPaint?

Автор: Earnest 23.10.2006, 13:20
А также BeginPaint().

Во втором варианте сделай так:
Код

CPaintDC dc(this);  // вместо GetDC
dcMem.CreateCompatibleDC(&dc);
// ... и далее по тексту

И не надо никакого CWnd::OnPaint();

Программа не реагирует на таймер, т.к. постоянно занимается обновлением: обрабатывает OnPaint. Без вызова BeginPaint\EndPaint не снимается "инвалидность". А таймер по приоритету - самый последний.

Основное правило: если уж хватаешь OnPaint, то будь любезен сделать валидным окно. Это можно сделать многими способами, но самый простой - создать объект CPaintDC, тем более что тебе в любом случае нужен контекст.

Все дело в волшебных пузырьках... smile 

Автор: Kolia 25.10.2006, 02:05
да прибудет с вами бабмуча! smile 

Спасиба

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