Версия для печати


Системное сообщение WM_PAINT.
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=93

Елена Филиппова
дата публикации 23-10-1999 00:00

Системное сообщение WM_PAINT.

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

Основной принцип перерисовки: Save and Paint - сохраняй и прорисовывай.
Windows не хранит в памяти нарисованное изображение в виде растрового рисунка. Система перерисовывает ту часть окна , которая в каждый конкретный момент в этом нуждается.

Когда Windows ( или другое приложение) посылает запрос на перерисовку окна или его части, этому окну посылается сообщение WM_PAINT.

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

Сообщение WM_PAINT относится к сообщениям с низким приоритетом, поэтому оно будет обработано в самую последнюю очередь.

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

В соответствии с общим подходом, принятым в Windows, перерисовываться будет не все окно, а только та часть, которая в этом нуждается. Так называемая область модификации - Update Region. К области модификации добавляется только некорректно отображаемая часть - Invalid Area , именна та часть окна, которая нуждается в перерисовке.

Область окна установливается как некорректная (Invalid area) методами Invalidate, InvalidateRect, или InvalidateRgn, а так же после того, как окно передвигают, изменяют его размеры или выполняют любою другою операцию, которая воздействует на клиентскую область окна.
Метод Invalidate объявляет некорректной всю клиентскую область окна.
Метод InvalidateRect ( и InvalidateRgn ) объявляет некорректной клиентскую область внутри данного прямоугольника, добавляя этот прямоугольник к текущей области модификации (Update Region).
Удалить некоторую область из Update Region можно методами ValidateRect или ValidateRgn.
Таким образом, некорректные области накапливаются в Update Region, пока эта область не будет обработана при следующем сообщении WM_PAINT , или пока она не будет объявлена корректной принудительно, методом ValidateRect или ValidateRgn.

Как уже отмечалось выше, установка непустой области модификации Update Region не заставляет приложение немедленно перерисоваться. Вместо этого, приложение продолжает получать сообщения из очереди, пока все сообщения не будут обработаны. Затем Windows проверяет область модификации, и если область не пустая, посылает сообщение WM_PAINT окну. При проверке области модификации могут быть посланы так же сообщения WM_NCPAINT и WM_ERASEBKGND, если требуется перерисовать рамку ( неклиентскую часть) окна или необходимо очистить окно.

Например, при увеличении размера окна будут посланы все три сообщения : WM_NCPAINT , WM_ERASEBKGND и WM_PAINT. При уменьшении размеров, окну придет только два сообщения из этой группы, сообщение WM_NCPAINT и WM_ERASEBKGND. По смыслу ситуации это резонно - при уменьшении окна клиентская часть его только урезается, следовательно стереть ее надо, а рисовать, вообще говоря, нечего...

Метод UpdateWindow требует немедленной перерисовки клиентской области в обход общей очереди. Предварительно проверяется состояние области модификации: если область модификации не пустая, окну будет послано сообщение WM_PAINT. Если область модификации пуста сообщение WM_PAINT, наоборот, не будет послано.
Если эта область была помечена для стирания, то окну предварительно будет послано сообщение WM_ERASEBKGND.

Для получения более подробной информации смотрите Help WinAPI по темам:
  • WM_PAINT
  • WM_NCPAINT
  • WM_ERASEBKGND
  • UpdateWindow
  • InvalidateRect , InvalidateRgn
  • GetUpdateRect , GetUpdateRgn
  • BeginPaint & EndPaint

Все вышеперечисленные методы являются методами класса CWnd, доступного через WinAPI.
Для перерисовки окон в Delphi применяются два метода :
TWinControl.RePaint 
TWinControl.ReFresh
Метод RePaint заключается в объявлении всей области окна как некорректной и немедленного запроса на перерисовавание окна. Достаточно привести реализацию этого метода из модуля Controls.pas, чтобы это увидеть:
procedure TWinControl.Repaint;
begin
  Invalidate;
  Update;
end;
Метод Refresh является модификацией метода RePaint. Для класса TWinControl метод Refresh повторяет вызов RePaint.

Таким образом, если Вам необходимо немедленно обновить окно, воспользуйтесь методом RePaint, если в этом нет необходимости и перерисовку нужно запросить, но в порядке общей очереди, лучше использовать метод Invalidate;

Для получения более подробной информации смотрите реализацию методов:
  • TWinControl.Invalidate
  • TWinControl.Update
  • метод Refresh для разных компонент, наследников от TWinControl.

В качестве практического примера использования системного сообщения WM_PAINT смотрите проект Антона Григорьева:
«Окно с изменяемой степенью прозрачности».