На этом шаге мы рассмотрим использование функции Paint().
Поэкспериментируем с программой из предыдущего шага. Сперва, находясь в окне, нажмите раз 20 на клавишу мыши, чтобы получить слово "Щелчок!". Окно будет выглядеть, как показано на рисунке 1.
Рис.1. Приложение, отображающее текст
Теперь переместите окно. При этом Windows безо всяких проблеем восстановит изображение. Так происходит потому, что отображаемые данные Windows хранит в области памяти экрана. Когда вы перемещаете окно, Windows просто перерисовывает в новом месте существующее на экране изображение.
Теперь нажмите кнопку максимизации. Ваше окно будет выглядеть так, как показано на рисунке 2.
Рис.2. Максимизированное окно
Когда вы увеличите окно, Windows по-прежнему восстановит изображение в области пользователя окна, поскольку вся необходимая информация все еще хранится в экранной памяти. (Но в новых областях, появившихся благодаря увеличению окна, ничего не рисуется.) Когда вы уменьшите размеры окна, вы увидите, что Windows продолжает поддерживать изображение. Для этого нажмите сначала кнопку восстановления окна, чтобы придать окну прежние размеры. Затем, используя рамку, уменьшите окно.
Хотя Windows не смог уместить все данные в уменьшенном окне, он отобразил все, что мог. Однако, уменьшая окно, вы тем самым урезали часть данных, находящихся в области экранной памяти. Что теперь произойдет, если попытаться снова увеличить окно? Попробуйте сами - и увидите: окно выглядит теперь примерно так, как на рисунке 3.
Рис.3. Окно, после уменьшения и восстановления первоначальных размеров
Могут быть восстановлены лишь те данные, которые были в исходный момент на экране. Остальные пропали.
Поскольку данные, которые необходимо отобразить, уже не доступны через область экрана, Windows не может полностью восстановить окно. Вместо этого он посылает приложению сообщение WM_PAINT о необходимости перерисовки изображения. Окна, имеющие TWindow в качестве базового класса, наследуют из него функцию Paint(), которая автоматически вызывается из OWL при получении сообщения WM_PAINT. Чтобы использовать это, нет необходимости добавлять в таблицу откликов сообщение WM_PAINT. Необходимо только переопределить функцию Paint() класса TWindow. В следующем примере показано, как это сделать.
#include <owl\applicat.h> #include <owl\framewin.h> #include <owl\dc.h> //Класс приложения class TApp: public TApplication { public: TApp():TApplication(){} void InitMainWindow(); }; //Класс основного окна class TWndw:public TFrameWindow { public: TWndw(TWindow *parent, const char far *title); protected: void EvLButtonDown(UINT,TPoint &point); BOOL CanClose(); void Paint(TDC&, BOOL, TRect&); DECLARE_RESPONSE_TABLE (TWndw); }; DEFINE_RESPONSE_TABLE1 (TWndw, TFrameWindow) EV_WM_LBUTTONDOWN, END_RESPONSE_TABLE; TWndw::TWndw(TWindow *parent, const char far *title): TFrameWindow(parent,title) { // Определить расположение и размеры окна. Attr.X=100; Attr.Y=100; Attr.W=400; Attr.H=300; } // TWndw::Paint() // // Эта функция, переопределяющая функцию Paint() // класса TWindow, отвечает на сообщения WM_PAINT, // посылаемые Windows окну при необходимости // его перерисовки. void TWndw::Paint(TDC&, BOOL, TRect&) { MessageBox("Обработка сообщения WM_PAINT", "Сообщение", MB_OK); } void TWndw::EvLButtonDown(UINT,TPoint &point) { // Получить контекст устройства для области // пользовательского окна. TDC *DC= new TClientDC(HWindow); // Вывести текст в месте, указанном пользователем. DC->TextOut(point,"Щелчок!"); // Удалить контекст устройства. delete DC; } BOOL TWndw::CanClose() { int result=MessageBox("Вы действительно хотите закрыть окно?","Закрытие", MB_YESNO | MB_ICONQUESTION); if (result==IDYES) return TRUE; else return FALSE; } void TApp::InitMainWindow() { TFrameWindow *wndw=new TWndw(0,"Пример GDI-окна"); SetMainWindow(wndw); } int OwlMain(int,char *[]) { return TApp().Run(); }
После запуска этой программы вы увидите окно, показанное на рисунке 4.
Рис.4. Результат работы приложения
Когда окно впервые появляется на экране, Windows посылает сообщение WM_PAINT, информируя программу о том, что она может вывести изображение. OWL направляет сообщение WM_PAINT в оконную функцию Paint(), отображающую окно, в котором говорится, что сообщение получено.
Теперь переместите окно. Windows не посылает сообщение WM_PAINT, поскольку со стороны вашей программы никакой помощи по перерисовке окна не требуется. Когда вы уменьшаете размер окна, результат тот же: Windows не посылает сообщение WM_PAINT. Однако, как только вы увеличиваете окно, сообщение WM_PAINT посылается. Оно посылается также в случае, когда вы накрываете окно вашей программы другим окном и затем вновь делаете его видимым, поскольку вся отображаемая область окна должна быть перерисована.
Функция Paint(), перехватывающая в OWL-программе сообщения WM_PAINT, представлена в примере следующим образом:
void TWndw::Paint(TDC&, BOOL, TRect&)
{
MessageBox("Обработка сообщения WM_PAINT", "Сообщение", MB_OK);
}
Эта функция получает в качестве параметра ссылку на контекст устройства, переменную типа boolean, указывающую, требуется ли перерисовка окна, и структуру типа TRect, содержащую координаты текущей области, для которой требуется перерисовка.
Логическая переменная почти всегда равна FALSE, означая тем самым, что "грязный" прямоугольник уже закрашен цветом фона. Она принимает значение TRUE лишь в единственном случае, когда вы обращаетесь к функции InvalidateRect() (обязывающей Windows послать сообщение WM_FAINT) и указываете, что хотите оставить фон. Наконец, прямоугольник в структуре TRect - это отсекающий прямоугольник, ограничивающий для Windows область рисования. Другими словами, рисовать за пределами этого прямоугольника вы не можете.
В данной функции Paint() параметры не используются, поскольку для вывода простого окна сообщений они ей не потребуются. Однако в следующей программе показано, как использовать готовый контекст устройства в Paint() для перерисовки окна.
На следующем шаге мы рассмотрим организацию хранения выводимых данных.