Регистрация класса окна
Задача функции InitApp - регистрация класса окна. На базе этого класса будет создано главное окно приложения.
Если допускается одновременная работа нескольких копий одного приложения, регистрация класса окна должна выполняться только один раз первой копией приложения.
В области локальных переменных функции определены две переменные - aWndClass и wc:
ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна
Переменная aWndClass используется для временного хранения кода возврата функции RegisterClass. Эта функция относится к функциям программного интерфейса Windows, она и выполняет регистрацию класса. В качестве единственного параметра функции необходимо указать адрес соответствующим образом подготовленной структуры типа WNDCLASS:
aWndClass = RegisterClass(&wc);
Приведем прототип функции RegisterClass:
ATOM WINAPI RegisterClass(const WNDCLASS FAR* lpwc);
Таким образом, процедура регистрации класса окна является несложной. Вам достаточно подготовить одну структуру и вызвать функцию RegisterClass.
Для вас, возможно, непривычно использование переменной специального типа ATOM для передачи результата выполнения функции. Однако такое использование не создает никаких дополнительных трудностей. Тип ATOM отображается на тип UINT, который, в свою очередь, отображается на тип unsigned int (см. файл windows.h):
typedef UINT ATOM; typedef unsigned int UINT;
Переменные типа ATOM используются как идентификаторы текстовых строк (атомы), хранящихся в области памяти, принадлежащей операционной системе Windows. Существует набор функций для работы с этими идентификаторами (для работы с атомами), который мы сейчас не будем рассматривать. Отметим только, что в этом наборе есть функции для получения адреса строки, соответствующей идентификатору, для создания и удаления, а также поиска идентификаторов.
В нашем приложении функция InitApp использует переменную типа ATOM для формирования кода возврата:
return (aWndClass != 0);
Если регистрация класса произошла успешно, функция RegisterClass возвращает атом с ненулевым значением, при этом функция InitApp возвращает значение TRUE.
Последнее означает, что инициализация приложения выполнена без ошибок.
Теперь займемся структурой WNDCLASS, которая используется для регистрации класса окна. Эта структура определена в файле windows.h:
typedef struct tagWNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; } WNDCLASS;
Перед регистрацией вам необходимо заполнить все поля в этой структуре.
Поле style определяет стиль класса и задается в виде констант (описанных, как всегда, в файле windows.h), имя которых начинается с префикса CS_, например CS_HREDRAW, CS_VREDRAW. Стиль задает реакцию окна на изменение его размера, на выполнение в окне операции двойного щелчка мышью (double click), а также позволяет определить другие характеристики окна, создаваемого на базе данного класса. Например, если для стиля задать значение CS_HREDRAW | CS_VREDRAW, при изменении вертикального или горизонтального размера окна приложение должно его перерисовать, то есть нарисовать заново все или часть того, что было изображено в окне до изменения размера.
В нашем приложении стиль класса не используется, поэтому для него задается нулевое значение:
wc.style = 0;
В поле lpfnWndProc необходимо записать адрес функции окна, которая будет выполнять обработку сообщений, поступающих во все окна, созданные на базе данного класса. Имя функции окна можно выбрать любое. В нашем случае используется имя WndProc, хотя вы можете использовать другое имя. Запись адреса функции окна должна выполняться следующим образом:
wc.lpfnWndProc = (WNDPROC) WndProc;
Поле lpfnWndProc имеет тип WNDPROC (дальний указатель на функцию), который мы рассмотрим чуть позже, при описании функции окна. Для того чтобы избежать получения от компилятора предупреждающего сообщения о несоответствии типов, вы должны использовать явное преобразование типа.
Поле cbClsExtra используется для резервирования дополнительной памяти, общей и доступной для всех окон, создаваемых на базе данного класса.
Чтобы это было понятно, отметим, что при регистрации класса окна в памяти, принадлежащей операционной системе Windows, резервируется и заполняется некоторая область (структура данных). В этой области хранится вся информация о классе, необходимая для создания окон на базе этого класса. Вы можете увеличить размер области описания класса для хранения своей собственной информации, предназначенной для всех создаваемых на базе этого класса окон. Поле cbClsExtra определяет размер дополнительной памяти в байтах. В программном интерфейсе Windows имеются специальные функции, предназначенные для работы с дополнительной областью памяти.
Наше приложение не создает в описании класса никаких дополнительных областей, поэтому для заполнения поля cbClsExtra используется нулевое значение:
wc.cbClsExtra = 0;
Так же как и при создании нового класса, при создании нового окна Windows резервирует в своей памяти область, описывающую окно. С помощью параметра cbWndExtra вы можете увеличить размер этой области для хранения информации, имеющей отношение к создаваемому окну. В нашем случае размер области описания окна не увеличивается, поэтому для заполнения поля cbWndExtra используется нулевое значение:
wc.cbWndExtra = 0;
Поле hInstance перед регистрацией класса окна должно содержать идентификатор приложения, создающего класс окна. В качестве этого идентификатора следует использовать значение, полученное функцией WinMain в параметре hInstance:
wc.hInstance = hInstance;
Следующее поле имеет имя hIcon и тип HICON. Это идентификатор пиктограммы, в которую превращается окно при уменьшении его размеров до предела (при минимизации окна).
В нашем приложении мы указываем пиктограмму, используемую Windows по умолчанию. Для Microsoft Windows версии 3.1 вид этой пиктограммы приведен на рис. 1.11.
Рис. 1.11. Пиктограмма приложения
Для загрузки пиктограммы в приложении вызывается функция программного интерфейса Windows с именем LoadIcon:
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Прототип функции LoadIcon:
HICON WINAPI LoadIcon(HINSTANCE hinst, LPCSTR pszicon);
Первый параметр функции (hinst) содержит идентификатор приложения, второй (pszicon) - имя ресурса-пиктограммы.
Позже мы научим вас определять для окон собственные пиктограммы, нарисованные с помощью приложения Resource Workshop, входящего в комплект поставки Borland C++ for Windows.
В поле hCursor (имеющем тип HCURSOR) вы можете задать вид курсора мыши при его прохождении над окном. Вы знаете, что курсор мыши меняет свою форму при перемещении над различными окнами приложений Windows. При регистрации класса окна вы можете указать форму курсора, для чего и используется поле hCursor.
В нашем приложении мы задаем курсор в виде стандартной стрелки, для чего вызываем функцию LoadCursor и указываем в качестве второго параметра константу IDC_ARROW:
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
Прототип функции LoadCursor:
HCURSOR WINAPI LoadCursor(HINSTANCE hinst, LPCSTR pszCursor);
Вы можете определить для окна свой курсор, нарисовав его аналогично пиктограмме при помощи такого приложения, как Resource Workshop или Microsoft SDKPaint. Однако пока для простоты мы будем использовать стандартный курсор.
Далее нам необходимо заполнить поле hbrBackground, имеющее тип HBRUSH. Это поле позволяет определить кисть (brush), которая будет использована для закрашивания фона окна. В качестве кисти можно использовать "чистые" цвета или небольшую пиктограмму размером 8 х 8 точек.
В нашем приложении мы использовали системный цвет, который Windows использует для закрашивания фона окон:
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
Системный цвет можно изменять при помощи приложения Control Panel. Позже мы научим вас задавать для фона окна другие цвета и раскрашивать окно при помощи пиктограмм.
Поле lpszMenuName (указатель на строку типа LPCSTR) определяет меню, располагающееся в верхней части окна. Если меню не используется, при заполнении этого поля необходимо использовать значение NULL:
wc.lpszMenuName = (LPSTR)NULL;
Тип LPCSTR определяется как константный дальний указатель на строку символов:
typedef const char FAR* LPCSTR;
Очень важно поле lpszClassName. В это поле необходимо записать указатель на текстовую строку, содержащую имя регистрируемого класса окон:
wc.lpszClassName = (LPSTR)szClassName;
На этом подготовку структуры wc к регистрации класса окна можно считать законченной. Можно вызывать функцию RegisterClass.
После регистрации функция InitApp возвращает управление обратно в функцию WinMain.