Зачем вызывать InvalidateRect() в сообщении WM_PAINT?

#windows #winapi #gdi #repaint #wm-paint

#Windows #winapi #gdi #перерисовать #wm-paint

Вопрос:

Итак, я изучаю Windows API с книгой «Программирование Windows — Чарльз Петцольд (5-е издание)». Если я правильно понимаю, при обработке сообщения WM_PAINT вызывающая функция BeginPaint() проверяет заданную область, которая должна быть обновлена. Однако в этой книге (страница 145 для PDF-версии или страница 128 в печатной версии) вы можете увидеть этот код:

 case WM_PAINT:
          InvalidateRect (hwnd, NULL, TRUE) ;   // what does this line do?
          hdc = BeginPaint (hwnd, amp;ps) ;
          DrawBezier (hdc, apt) ; 
          EndPaint (hwnd, amp;ps) ;
          return 0 ;
  

Это ошибка автора? я думаю, что InvalidateRect() следует вызывать после использования GetDC()/ ReleaseDC(), а не внутри сообщения WM_PAINT.

Комментарии:

1. Это, конечно, не имеет смысла. Система генерирует WM_PAINT сообщение в ответ на то, что часть окна помечена как недопустимая, например, при вызове InvalidateRect . Вызов, за InvalidateRect которым сразу следует BeginPaint , по сути, не выполняется.

2. Спасибо вам всем за ответы. Похоже, автор действительно поместил InvalidateRect() в неправильное сообщение. Есть также три сообщения WM_MOUSE, в которых рисование происходит через GetDC(), и я думаю, что это то место, где следует вызвать InvalidateRect().

Ответ №1:

Единственное, что это делает, это делает недействительным все окно, а не только то, что оказывается недействительным (например, из-за того, что перекрывающееся окно перемещается в сторону).

Я не уверен, что это имеет значение в данном случае, но это то, что выполняет вызов.

Ответ №2:

Согласно документу:

Система не является единственным источником сообщений WM_PAINT. Функция InvalidateRect или InvalidateRgn может косвенно генерировать сообщения WM_PAINT для вашей Windows. Эти функции помечают всю или часть клиентской области как недопустимую (которую необходимо перерисовать).

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

Ответ №3:

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

Спасибо всем за ваши ответы, я очень ценю это!