OnPaint обновляется слишком часто

У меня проблема с методом OnPaint CFrameWnd, и я не могу понять, что происходит. OnPaint вызывается примерно каждые 10 мс, что приводит к зависанию компьютера. Проверено использование процессора и это приложение занимает 50%!

Приложение представляет собой очень простое приложение MFC, которое написано в одном файле.

// Includes are done here...

class MFC_Tutorial_Window : public CFrameWnd
{
std::string data;

public:
    MFC_Tutorial_Window()
    {
         this->data = "";
         Create(NULL, "Data Win");  // Create window
    }

    void OnPaint()
    {   
        CDC* pDC = GetDC();

        CString s = CString(this->data.c_str());
        RECT rc;

        HWND hwnd = this->m_hWnd;
        if(hwnd != NULL) {
            ::GetWindowRect(hwnd, &rc);

            rc.top = rc.bottom/2;

            if(pDC != NULL && pDC->m_hDC != NULL) {
                pDC->DrawText(s, &rc, DT_CENTER);
            }
        }
    }

    void UpdateWithNewData(std::string up) {
        this->data = up;
        Invalidate();
    }


    DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(MFC_Tutorial_Window, CFrameWnd)
    ON_WM_PAINT()       
END_MESSAGE_MAP()

// App class
class MyApp :public CWinApp
{
    MFC_Tutorial_Window *wnd;

    BOOL InitInstance()
    {
        wnd = new MFC_Tutorial_Window();
        m_pMainWnd = wnd;
        m_pMainWnd->ShowWindow(3);

                       wnd->UpdateWithNewData("Hello world!");          
             return 1;
    }
};

Кто-нибудь знает, почему OnPaint спамится системой? Я смотрел на этот код целую вечность, и я просто не могу его найти.

2 ответа

Решение

Деструктор CPaintDC должен быть вызван для сброса флага перерисовки. Вам нужно позвонить beginPaint(); а также endPaint(); на ваше CDC который на самом деле должен быть изменен на CPaintDC, Что еще важнее, не звонить endPaint(); приведет к перерисовке контекста, несмотря ни на что.

WM_PAINT сообщение генерируется всякий раз, когда в очереди сообщений и в области обновления окна нет других сообщений (см. InvalidateRect) не пусто. При обращении с WM_PAINT сообщение приложение сигнализирует, что область обновления была перекрашена путем вызова EndPaint, Неспособность позвонить EndPaint не будет помечать регион обновления как обработанный, поэтому в следующий раз, когда приложение запросит сообщение, WM_PAINT является действительным кандидатом.

В MFC функционал для вызова BeginPaint а также EndPaint заключен в CPaintDC Класс Стандартный обработчик сообщений MFC для WM_PAINT выглядит так:

void OnPaint()
{
    CPaintDC dc(this);  // calls BeginPaint()
    // Perform rendering operations on dc
    // ...
} // CPaintDC::~CPaintDC() calls EndPaint()

Более подробную информацию об использовании контекстов устройства можно найти в разделе Контексты устройства.

Другие вопросы по тегам