Почему не хватает OnDraw (в MFC, учебник по Scribble) - PullRequest
0 голосов
/ 15 ноября 2011

Я делаю учебник по Scribble для изучения MFC, и в событии MouseMove есть следующий код:

void CScribbleView::OnMouseMove(UINT nFlags, CPoint point)
{
    // Mouse movement is interesting in the Scribble application
    // only if the user is currently drawing a new stroke by
    // dragging the captured mouse.

    if( GetCapture( ) != this )
        return;        // If this window (view) didn't capture the
    // mouse, the user isn't drawing in this window.

    // Add the new point to the current stroke
    m_pStrokeCur->m_pointArray.Add(point);

    CClientDC dc( this );

    // Draw a line from the previous detected point in the mouse
    // drag to the current point.
    CPen* pOldPen =
        dc.SelectObject( GetDocument( )->GetCurrentPen( ) );
           dc.MoveTo( m_ptPrev );
           dc.LineTo( point );
           dc.SelectObject( pOldPen );

    m_ptPrev = point;

    CView::OnMouseMove(nFlags, point);
}

А это функция рисования обводки (которая вызывается OnDraw представления):

BOOL CStroke::DrawStroke( CDC* pDC )
{
    CPen penStroke;
    if( !penStroke.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0)))
        return FALSE;
    CPen* pOldPen = pDC->SelectObject( &penStroke );
    pDC->MoveTo( m_pointArray[0] );
    for( int i=1; i < m_pointArray.GetSize(); i++ )
    {
        pDC->LineTo( m_pointArray[i] );
    }
    pDC->SelectObject( pOldPen );
    return TRUE;
}

Я проверял, что эта функция вызывается при каждом обновлении кадра. Однако, если я уберу рисунок при перемещении мыши, ничего не произойдет, даже если я регистрирую все штрихи и вызывается функция рисования штрихов. Только тогда, если я внесу изменения в окно (например, максимизация), тогда появится. Если функция

вызывается, почему он не рисует в окне? Я пытаюсь выяснить внутреннюю работу MFC здесь, это не ошибка или что-то в этом роде.

1 Ответ

2 голосов
/ 15 ноября 2011

Когда все или часть ваших окон устарели (они называются «недействительными»), цикл сообщений в итоге получит два сообщения: WM_ERASEBKGND и затем WM_PAINT. Типичный способ рисования для приложений Windows - рисовать все в обработчиках WM_ERASEBKGND и WM_PAINT. (Я не эксперт по MFC, но я считаю, что WM_PAINT соответствует OnDraw в MFC.)

Таким образом, нормальный способ справиться с этим - обработчик перемещения мыши записывает ход (как он это делает), а затем отмечает окно как недействительное. Это в конечном итоге приведет к рисованию линии. Однако возможна небольшая задержка, которая может вызвать мерцание. Задержка, вероятно, незначительна на современном компьютере (но Scribble старый). Существуют различные способы борьбы с мерцанием.

Автор Scribble, похоже, решил обработать задержку и мерцание, рисуя линию непосредственно в обработчике перемещения мыши вместо того, чтобы сделать окно недействительным и позволить OnDraw сделать это позже.

Недействительность является ключом. Вы удалили чертеж из OnMouseMove, чтобы линия там не рисовалась. Но нет ничего, что могло бы сказать Windows, что содержимое окна теперь устарело (недействительно), и поэтому оно не получает сообщение WM_PAINT, и OnDraw не вызывается. (Позже, когда вы делаете что-то вроде изменения размера или увеличения окна, делает его недействительным, вызывается OnDraw и неожиданно появляется строка.)

Если вы хотите удалить чертеж из OnMouseMove, вам придется заменить его вызовом InvalidateRect. Это скажет Windows, что окно должно быть перерисовано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...