Пиктограммы и курсоры

Для демонстрации возможностей включения в прикладную программу собственных пиктограмм (значков) и курсоров ис­пользован видоизмененный соответствующим образом пример 26-1. Приведенный ниже вывод программы (рис. 26-6) отлича­ется от рис. 26.1 только значком в верхнем левом углу окна приложения и формой курсора.

//Приложение 26-4. Пиктограммы и курсоры


//Файл 26-4.rс

myIcon ICON "26-4.ico" //Описание ресурса-значка (ссылка на файл)

myCursor CURSOR "26-4. cur"//Описание ресурса-курсора (ссылка на файл)

//Файл 26-1.срр

#include <owl\framewin.h>

/* Глобальные переменные*/

HICON hIcon;/ /Дескриптор значка

HCURSOR hCursor;// Дескриптор курсора

/*Класс приложения, производный от TApplication (ради InitMainWindow)*/

class MyApp:public TApplication{

public:

virtual void InitMainWindow(void); //Замещаем функцию InitMainWindow

};

/*Класс главного окна, производный от TFrameWindow (ради Paint и GetWindowClass) */ class MyWindow:public TFrameWindow{ public:

MyWindow(TWindow*parent,const char far* title):TFrameWindow(parent,title){


238___________________________________________________ Глава 26

Attr.X=20;Attr.Y=20; //Задаем координаты окна Attr.W=200;Attr.H=60;//Задаем размеры окна

}

void Paint(TDC&,bool,TRect&);//Замещаем открытую функцию TWindow::Paint()

void GetWindowClass(WNDCLASS&); //Замещаем функцию TWindow::GetWindowClass()

}; /*Замещенная функция InitMainWindow()*/

void MyApp::InitMainWindow(void){

MyWindow* myWin=new MyWindow(0,"Программа 26-4");

SetMainWindow(myWin);

hIcon=LoadIcon("myIcon"); //Загружаем значок и получаем его дескриптор

hCursor=LoadCursor("myCursor") ;//Загружаем курсор и получаем его дескриптор

} /*Замещенная функция Paint ()*/

void MyWindow::Paint(TDC&dc,bool,TRect&){

dc.TextOut(10,10,"Строка текста");

}

/*Замещенная функция GetWindowClass()*/ void MyWindow::GetWindowClass(WNDCLASS& wс){

TWindow::GetWindowClass(wс); //Вызываем исходную функцию GetWindowClass()

we.hIcon=hIcon;//Добавляем в wc дескриптор значка

wc.hCursor=hCursor; //Добавляем в wc дескриптор курсора

} /*Главная функция приложения OwlMain*/

int OwlMain(int,char*[]){

MyApp* myApp=new MyApp;

return myApp->Run(); }

Любое уважающее себя приложение обладает собственным значком, по которому файл приложения можно легко отличить от других программ. Многие приложения (в частности, системы программирова­ния Borland C++, текстовый редактор Word и т.д.) содержат в себе не один, а несколько или даже много значков, из которых пользователь может выбрать наиболее привлекательный. Значок приложения ото­бражается в списке файлов при выводе на экран содержимого той или иной папки (каталога); на панели задач в нижней части Рабочего стола Windows; в левом углу заголовка окна, где этот значок выступает в качестве кнопки для вызова системного меню; в ярлыке приложения на рабочем столе или в какой-либо папке, если таковой ярлык был создан пользователем для облегчения нахождения и вызова приложения. Помимо этого, значки иногда выводятся непосредственно в окно приложения в качестве логотипа или заставки.

С курсорами ситуация сложнее в том отношении, что приложение, как правило, использует не один, а много курсоров, в зависимости от режима работы и отображаемых на экране окон. Например, в режиме наблюдения, допускающем увеличение, курсор часто приобретает форму лупы; при проходе по окну с текстом, допускающим редактирование, курсор приобретает форму латинской буквы I; процессы, зани­мающее заметное время, например, чтение или запись файлов, часто меняют форму курсора на изобра­жение песочных или стрелочных часов и т.д. В настоящем разделе приводится простейший пример на­значения конкретному окну (в примере - главному) курсора заданной формы.

Новые изображения значка и курсора удобнее всего создать с помощью специализированного редактора ресурсов Resource Workshop, входяще­го в состав пакетов Borland C++. Файл с изобра­жением значка должен иметь расширение.ICO, файл с изображением курсора - расширение.CUR. Имена обоих файлов описываются в файле ресурсов (в настоящем примере - в файле 26-4.RC, см. текст программы выше). Произвольные имена, с которых начинаются строки описания ресурсов (у нас это myIcon и myCursor) будут в дальнейшем использоваться в программе в каче­стве идентификаторов ресурсов. В процессе ком­пиляции и сборки программы двоичные представ­ления всех значков и курсоров, описанных в фай­ле ресурсов, включаются в загрузочный модуль приложения; первый из значков используется сис­темой Windows в списках файлов и ярлыках (рис.

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

Для придания окну приложения значка и курсора их следует сначала загрузить в память из загрузоч­ного файла приложения (и получить при этом их дескрипторы), а затем поместить эти дескрипторы в


Обработка сообщения WM_PAINT и интерфейс GDI 239

системную структуру типа WNDCLASS, описывающее данное окно. Поскольку мы будем обращаться к дескрипторам ресурсов из разных функций, они описаны в начале программы, как глобальные перемен­ные hIcon и hCursor. OWL-функции загрузки значка LoadIcon() и курсора LoadCursor() включены в со­став класса TModule, поэтому их проще всего вызывать из функций классов, производных от TModule. У нас таким классом является класс приложения МуАрр (см. рис. 25.2), в котором мы переопределили функцию базового класса InitMainWindow(). В текст этой функции можно включить и строки загрузки ресурсов.

Со структурой типа WNDCLASS дело обстоит сложнее, так как во-первых, надо как-то суметь к ней обратиться, и во-вторых, надо сделать это до регистрации класса окна, чтобы сделанные нами исправле­ния зарегистрировались в Windows. Для того, чтобы выполнить требуемую операцию, придется более детально рассмотреть исходные тексты функций OWL, выполняющих создание главного окна приложе­ния (рис. 26.8).

Как уже говорилось, жизнь приложения в значительной степени определяется функцией TApplica-tion::Run(), которая выполняет инициализирующие действия, создает главное окно приложения и органи­зует цикл обработки сообщений. Заместив функцию TApplication::InitMainWindow(), мы получили воз­можность создать объект myWin класса главного окна MyWindow, а также (в настоящем примере) загру­зить необходимые ресурсы - значок и курсор и получить их дескрипторы.

Регистрация класса главного окна выполняется в функции TWindow::Create(), которая вызывает для этого функцию TWindow::Register(). Как видно из рис. 26.8, функция Register() сначала вызывает функ­цию TWindow::GetWindowClass, назначение которой - заполнить структуру WNDCLASS значениями по умолчанию. Далее вызовом функции API Windows RegisterClass выполнятся регистрация класса окна. Желая изменить настройку структуры WNDCLASS, мы должны заместить функцию класса TWindow GetWindowClass(), подставив на ее место собственную функцию с тем же именем. Это замещение вы­полняется при описании прикладного класса MyWindow.

Очевидно, что в нашей функции GetWindowClass() мы прежде всего должны вызвать исходную функцию с тем же именем класса TWindow, чтобы она заполнила все поля структуры WNDCLASS тре­буемыми по умолчанию значениями. Лишь после этого можно изменить значения отдельных полей нуж­ным нам образом. Следует подчеркнуть, что необходимость вызова исходной, замещенной функции в общем случае совсем не очевидна. Так, например, заместив функцию InitMainWindow(), мы не вызывали исходный вариант, а фактически заново написали ее текст в своей программе с удобными для нас изме­нениями. Надо ли вызывать замещенные функции из замещающих (и, кстати, когда их вызывать - в на­чале замещающей функции или, возможно, в конце), а также какие строки допустимо включать в заме­щающие функции, можно определить, лишь детально рассматривая исходные тексты соответствующих классов OWL.

Наша программа выглядит несколько неуклюже из-за наличия в ней глобальных данных частного характера. Текст программы можно сделать заметно компактнее, если перенести операции загрузки ре­сурсов с получением их дескрипторов в функцию GetWindowClass(). В этом случае отпадет необходи­мость объявлять переменные hIcon и hCursor глобальными: их можно переместить в класс MyWindow. Однако функции LoadIcon() и LoadCursor() принадлежат классу TModule, и просто вызвать их из функ-


240 Глава 26

ции класса MyWindow нельзя, необходимо указать объект, для которого они вызываются. В нашей про­грамме указатель на объект производного от TModule класса MyApplication носит название mуАрр, од­нако в функции GetWindowClass() это конкретное имя, разумеется, не может быть известно. Поэтому придется в процессе выполнения функции GetWindowClass() динамически определить указатель на объ­ект приложения. Это можно сделать с помощью функции класса TWindow GetApplication(), которая воз­вращает указатель на объект класса TApplication, с которым связано наше окно. Измененный текст функции GetWindowClass() выглядит следующим образом:

void MyWindow::GetWindowClass(WNDCLASS& wc){

TWindow::GetWindowClass(wc); //Вызываем исходную функцию базового класса wc.hIcon=GetApplication()->TModule::LoadIcon("myIcon"); wc.hCursor=GetApplication()->TModule::LoadCursor("myCursor"); }

Перед функциями LoadIcon() и LoadCursor() пришлось указать их принадлежность к классу TModule, так как мы вызываем их из другого класса. Между прочим, обсуждаемый вариант программы возможен лишь потому, что функции LoadIcon() и LoadCursor() объявлены в классе TModule открытыми. Если бы они были закрытыми или даже защищенными, из другого класса их вызывать было бы нельзя.

Запустив приложение 26-4, можно убедиться в том, что созданный нами значок появляется не только в строке заголовка, но и на панели задач Windows (рис. 26.9).

Рассмотренная процедура придания приложению значка и курсора не является единственной. При­дать приложению значок и курсор можно, например, с помощью функций класса TWindow SetIcon() и SetCursor(). Их можно вызывать в замещающей функции InitMainWindow() после образования объекта класса MyWindow. Функции SetIcon() и SetCursor() являются открытыми, однако, чтобы вызывать их из функции, принадлежащей другому классу, необходимо указать конкретный объект, для которого она вы­зываются, или, как в приведенном ниже фрагменте, указатель на объект:

void MyApp::InitMainWindow(void){

MyWindow* myWin=new MyWindow(0,"Программа 26-4"); SetMainWindow(myWin); myWin->SetIcon(this,"myIcon"); myWin->SetCursor(this,"myCursor"); }

В качестве первого аргумента и той, и другой функции необходимо использовать указатель на объект приложения (производный от класса TModule), для которого осуществляется операция назначения ре­сурсов. У нас этот указатель будет носить имя mуАрр, однако в функции-члене класса использовать имена конкретных объектов, разумеется, нельзя, а можно только вызывать функции Windows для дина­мического, в процессе выполнения программы, получения требуемых имен. Здесь, как и в предыдущем фрагменте, можно воспользоваться функцией GetApplication(), вызывав ее для только что созданного указателя myWin

myWin->SetIcon(myWin->GetApplication(),"myIcon");

однако проще и изящнее использовать указатель this (см. предыдущий фрагмент), который в функции, принадлежащей классу МуАрр, как раз и указывает на текущий объект этого класса.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: