#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().
Спасибо всем за ваши ответы, я очень ценю это!