Вывод программы, рассматриваемой в настоящем разделе, приведен на рис. 26.10.
//Приложение 26-5.
11Файл 26-5.rс
myPicture BITMAP "picture.bmp" //Ссылка на файл с растровым изображением
//Файл 26-5.срр
#include <owl\framewin.h>
/*Класс приложения, производный от TApplication (ради InitMainWindow)*/
class MyApp:public TApplication{ public:
virtual void InitMainWindow(void); //Замещаем функцию InitMainWindow };
Обработка сообщения WM_PAINT и интерфейс GDI 241 |
/*Класс главного окна, производный от TFrameWindow (ради Paint) */
class MyWindow:public TFrameWindow{ private:
TBitmap* bitmap;// Создаем указатель на объект - изображение в памяти public:
MyWindow(TWindow*parent,const char far* title):TFrameWindow(parent,title){ Attr.X=0;Attr.Y=0;// Задаем координаты окна Attr.W=::GetSystemMetrics(SM_CXSCREEN) ;//Задаем размеры Attr.H=::GetSystemMetrics(SM_CYSCREEN);// окна - на весь экран bitmap=new TBitmap(GetModule()->GetInstance(),"myPicture");// Загружаем ресурс }
~MyWindow(){delete bitmap;} //Деструктор ради удаления bitmap void Paint(TDC&,bool,TRect&); //Замещаем функцию Paint()
};
/*Замещенная функция InitMainWindow() */ void MyApp::InitMainWindow(void){
MyWindow* myWin=new MyWindow(0,"Программа 26-5");
SetMainWindow(myWin);
}
/*3амещенная функция Paint ()*/ void MyWindow::Paint(TDC&dc,bool,TRect&) {
TMemoryDC memdc (dc); // Создаем совместимый контекст
memdc.SelectObject(*bitmap); //Выбор изображения в совместимый контекст
dc.BitBlt(10,80,bitmap->Width(),bitmap->Height(),memdc,0,0,SRCCOPY);// Копирование /*Далее выполняется вывод в окно текстовых строк*/
TFont font1("Times New Roman",22,О,О,0,FW_BOLD);
TFont font2("Times New Roman",22);
TFont font4("Garamond",36,0,0,0,0,0,true);
TFont font5("Academy",40,0,0,0,FW_BOLD);
dc.SelectObject(font1);
TRect rect1(0,10,GetSystemMetrics(SM_CXSCREEN),50);
char title1[]="Московский инженерно-физический институт";
dc.DrawText(title1, strlen (title1),rect1,DT_CENTER);
dc.SelectObject(font2);
TRect rect2(0,35,GetSystemMetrics(SM_CXSCREEN),70);
char title2[]="(технический университет)";
dc.DrawText(title2,strlen(title2),rect2,DT_CENTER);
TRect rect3(200,150,GetSystemMetrics(SM_CXSCREEN),250);
242 Глава 26
char title3[]="Факультет повышения квалификации\nспециалистов промышленности";
dc.DrawText(title3,strlen(title3),rect3,DT_WORDBREAK|DT_CENTER);
dc.SelectObject(font4);
TRect rect4(0,300,GetSysternMetrics (SM_CXSCREEN),380);
char title4[]="Практический курс";
dc.TextOut(350,320,title4);
dc.SelectObject(font5);
dc.SetTextColor(TColor::Gray);
TRect rect5(0,380,GetSystemMetrics(SM_CXSCREEN),430);
char title5[]="Программирование для Windows";
dc.DrawText(title5,strlen(title5),rect5,DT_CENTER); }
/*Главная функция приложения OwlMain*/ int OwlMain(int,char*[]){
MyApp* myApp=new MyApp;
return myApp->Run();
}.
Вспомним основные этапы процедуры вывода на экран растровых изображений (см. гл. 17).
• Изображение, хранящееся в файле с расширением.BMP, загружается в память (функцией LoadBit-
map()). Система возвращает дескриптор этой области памяти
• Создается контекст памяти, совместимый с нашим окном (функцией CreateCornpatibleDC())
• Дескриптор области памяти с изображением выбирается в совместимый контекст (функцией Se-
lectBitmap())
• Изображение из памяти копируется в окно (функцией BitBlt())
При использовании библиотеки OWL надо сделать, в сущности, то же самое, но с использованием объектов подходящих классов и их функций-членов:
bitmap=new TBitmap(GetModule()->GetInstance(),"myPicture");/ /Загружаем изображение TMemoryDC memdc(dc); //Создаем совместимый с окном контекст памяти
memdc.SelectObject(*bitmap); //Выбор дескриптора изображения в совместимый контекст dc.BitBlt(10,80,bitmap->Width(),bitmap->Height(),memdc,0,0,SRCCOPY); //Копирование
Область памяти с растровым изображением создается конструктором класса TBitmap. Объект этого класса и будет представлять собой требуемую область. Поскольку область памяти с растром можно создать различными способами (копированием, из буфера обмена и др.), в классе TBitmap описано несколько (конкретно 10) конструкторов, отличающихся составом параметров. Для нашей программы мы выбрали конструктор
TBitmap (HINSTANCE, TResID)
который создает область памяти для приложения с указанным дескриптором из заданного ресурса. В текст конструктора (см. файл bitmap.cpp в каталоге source\owl) входит вызов функции API Windows LoadBitmap(), что избавляет нас от необходимости заботиться о загрузке изображения - оно будет загружено автоматически в процессе создания экземпляра класса TBitmap.
Как получить дескриптор приложения, необходимый для вызова конструктора TBitmap? В классах TWindow и TFrameWindow, от которых происходит наш класс MyWindow, нет функций для получения дескриптора экземпляра приложения. Такая (открытая) функция Getlnstance() есть в классе TModule, но чтобы вызвать ее из конструктора класса MyWindow, надо указать объект класса TModule, для которого она вызывается. А вот для получения указателя на этот объект в классе TWindow есть функция GetMod-ule(). Это дает нам возможность получить для конструктора класса MyWindow первый параметр. Вторым параметром служит имя ресурса (у нас - myPicture), как оно записано в файле ресурсов.
Указатель на область памяти, создаваемую с помощью оператора new в конструкторе класса MyWindow, должен быть предварительно описан, как данное-член этого класса. Мы присвоили ему атрибут private, так как обращение к нему будет осуществляться исключительно из функций этого же класса, конкретно, из функции Paint().
Дальнейшие операции, использующие контексты устройств, должны выполняться непосредственно в функции Paint(), обрабатывающей сообщение WM_PAINT. Прежде всего с помощью конструктора класса TMemoryDC создается совместимый с контекстом устройства dc контекст памяти memdc. Далее функцией TMemoryDC::SelectObject() в него выбирается заданный объект. Из описания функции Selec-tObject()
void SelectObject(const TBitmap&)
видно, что в качестве параметра этой функции выступает объект класса TBitmap, передаваемый по ссылке. У нас в программе объявлено не имя объекта, а указатель на него bitmap, из которого сам объект получается снятием ссылки (символ *).
Наконец, последней операцией является копирование изображения из памяти в окно приложения. Для этого используется функция блочной передачи данных класса TDC BitBlt(), по своему назначению и
Обработка сообщения WM_PAINT и интерфейс GDI_______________________ 243
параметрам совпадающую с одноименной функцией API Windows, которую она инкапсулирует. Использованные в примере функции Width() и Height() принадлежат классу TBitmap и позволяют получить ширину и высоту созданное области памяти.
Контекст области памяти memdc, как это подробно описывалось в гл. 17, можно использовать для вывода в эту область, помимо растровых изображений, также и графических элементов, рисуемых с помощью перьев, кистей и шрифтов. Например, предложение
memdc.TextOut(102,4,"0");
(выполненное, разумеется, перед копированием изображения в окно) добавит к нашему изображению символ 0 (рис. 26.11).
Последнее замечание касается уничтожения создаваемых объектов. Все объекты, создаваемые в программе в явном виде оператором new, необходимо в каком-то месте программы уничтожить (оператором delete). Проще всего для этого воспользоваться деструктором соответствующего класса. В нашем примере уничтожение выделенной области памяти осуществляется в деструкторе класса MyWindow:
~MyWindow(){delete bitmap;}/ /Деструктор ради удаления bitmap
Глава 27