Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

29

Это объявление в начале программы необходимо потому, что в тексте функции WinMain имеются ссылки на функцию WndProc.

В программе на языке С, написанной для традиционной среды, точкой входа является функция main. С этого места программа начинает выполняться. (Фактически функция main является точкой входа в ту часть программы, которая пишется программистом. Обычно компилятор С должен вставить некоторый стартовый код в исполняемый файл. Этот код и вызывает функцию main.) Точкой входа программы для Windows является функция WinMain. WinMain всегда определяется следующим образом:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

Эта функция использует последовательность вызовов WINAPI и, по своему завершению, возвращает операционной системе Windows целое. Функция называется WinMain. В ней есть четыре параметра.

Параметр hInstance называется описателем экземпляра (instance handle). Это уникальное число, идентифицирующее программу, когда она работает под Windows. Может так случиться, что пользователь запустит под Windows несколько копий одной и той же программы. Каждая копия называется "экземпляром" и у каждой свое значение hInstance. Описатель экземпляра можно сравнить с "идентификатором задачи" или "идентификатором процесса" — обычными терминами многозадачных операционных систем.

Параметр hPrevInstance — предыдущий экземпляр (previous instance) — в настоящее время устарел. В ранних версиях Windows он относился к самому последнему, предшествующему данному, описателю экземпляра той программы, которая все еще активна. Если в данный момент времени не было загружено никаких копий программы, то hPrevInstance = 0 или NULL. Под Windows 95 этот параметр всегда равен NULL.

Параметр szCmdLine — это указатель на оканчивающуюся нулем строку, в которой содержатся любые параметры, переданные в программу из командной строки. Вы можете запустить программу для Windows с параметром командной строки, вставив этот параметр после имени программы в командной строке MS-DOS или указать имя программы и параметр в окне диалога Run, которое вызывается из меню Start.

Параметр iCmdShow — число, показывающее, каким должно быть выведено на экран окно в начальный момент. Это число задается при запуске программы другой программой. Программисты достаточно редко обращаются к этому числу, но при необходимости такая возможность существует. В большинстве случаев число равно 1 или 7. Но лучше не думать об этом значении как о единице или как о семерке. Лучше думайте о них как об идентификаторе SW_SHOWNORMAL (заданном в заголовочных файлах Windows равным 1) или идентификаторе SW_SHOWMINNOACTIVE (заданном равным 7). Префикс SW в этих идентификаторах означает "показать окно" (show window). Параметр показывает, необходимо ли запущенную пользователем программу выводить на экран в виде окна нормального размера или окно должно быть изначально свернутым.

Регистрация класса окна

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

На основе одного класса окна можно создать несколько окон. Например, все окна-кнопки в Windows создаются на основе одного и того же класса окна. Класс окна определяет оконную процедуру и некоторые другие характеристики окон, создаваемых на основе этого класса. Когда вы создаете окно, вы определяете дополнительные характеристики окна, уникальные для него.

Перед созданием окна для вашей программы необходимо зарегистрировать класс окна путем вызова функции RegisterClassEx. Это расширенная (на что указывает окончание названия Ex, т. е. extended — расширенный) версия функции RegisterClass из предыдущих версий Windows. Тем не менее функция RegisterClass продолжает работать и под Windows 95.

У функции RegisterClassEx имеется один параметр: указатель на структуру типа WNDCLASSEX. Структура WNDCLASSEX определяется в заголовочных файла Windows следующим образом:

typedef struct tagWNDCLASSEX

{

UINT

cbSize;

UINT

style;

WNDPROC

lpfnWndProc;

int

cbClsExtra;

int

cbWndExtra;

HINSTANCE

hInstance;

HICON

hIcon;

HCURSOR

hCursor;

30

HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; HICON hIconSm;

} WNDCLASSEX;

Несколько замечаний о некоторых из представленных здесь типах данных и о венгерской нотации: префиксы LP и lp означают "длинный указатель" (long pointer), являющийся пережитком 16-разрядной Windows, в которой программисты могли различать короткие (или близкие, near) 16-разрядные указатели и длинные (или дальние, far) 32-разрядные указатели. В Windows 95 все указатели имеют длину в 32 разряда. В представленных в этой книге программах все префиксы l для типов указателей убраны, но несомненно вы встретите их где-нибудь в другом месте.

Обратите также внимание на некоторые новые случаи использования венгерской нотации: приставка lpfn означает "длинный указатель на функцию" (long pointer to a function). Приставка cb означает "счетчик байтов" (counter of bytes). Префикс hbr — это "описатель кисти" (handle to a brush).

В WinMain вы должны определить структуру типа WNDCLASSEX, обычно это делается следующим образом:

WNDCLASSEX wndclass;

Затем задаются 12 полей структуры и вызывается RegisterClassEx:

RegisterClassEx(&wndclass);

Наиболее важными являются второе от конца и третье поля. Второе от конца поле является именем класса окна (который в программах, создающих одно окно, обычно совпадает с именем программы). Третье поле (lpfnWndProc) является адресом оконной процедуры, которая используется для всех окон, созданных на основе этого класса (в HELLOWIN.C оконной процедурой является функция WndProc). Другие поля описывают характеристики всех окон, создаваемых на основе этого класса окна.

Поле cbSize равно длине структуры. Инструкция:

wndclass.style = CS_HREDRAW | CS_VREDRAW;

осуществляет объединение двух идентификаторов "стиля класса" (class style) с помощью поразрядной операции OR языка С. В заголовочных файлах Windows, идентификаторы, начинающиеся с префикса CS, задаются в виде 32-разрядной константы, только один из разрядов которой установлен в 1. Например, CS_VREDRAW задан как 0x0001, а CS_HREDRAW как 0x0002. Заданные таким образом идентификаторы иногда называют "поразрядными флагами" (bit flags). Объединяются поразрядные флаги с помощью операции OR языка С.

Эти два идентификатора стиля класса показывают, что все окна, созданные на основе данного класса должны целиком перерисовываться при изменении горизонтального (CS_HREDRAW) или вертикального (CS_VREDRAW) размеров окна. Если вы измените размер окна HELLOWIN, то увидите, что строка текста переместится в новый центр окна. Эти два идентификатора гарантируют, что это случится. Далее мы подробно рассмотрим, как оконная процедура уведомляется об изменении размера окна.

Третье поле структуры WNDCLASSEX инициализируется с помощью инструкции:

wndclass.lpfnWndProc = WndProc;

Эта инструкция устанавливает оконную WndProc как оконную процедуру данного окна, которая является второй функцией в HELLOWIN.С. Эта оконная процедура будет обрабатывать все сообщения всем окнам, созданным на основе данного класса окна. Как уже упоминалось, приставка lpfn означает "длинный указатель на функцию".

Следующие две инструкции:

wndclass.cbClsExtra = 0;

wndclass.cbWndExtra = 0;

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

В следующем поле находится просто описатель экземпляра программы (который является одним из параметров

WinMain):

wndclass.hInstance = hInstance;

Инструкции:

wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

31

и

wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

устанавливают значок для всех окон, созданных на основе данного класса окна. Значок — это просто маленькая битовая картинка, которая появляется на панели задач Windows и слева в заголовке окна. Позже из этой книги вы узнаете, как создавать пользовательские значки для ваших программ под Windows. Сейчас для простоты воспользуемся стандартным значком.

Для получения описателя стандартного значка, вы вызываете LoadIcon, установив первый параметр в NULL. (При загрузке вашего собственного пользовательского значка, этот параметр должен быть установлен равным описателю экземпляра программы.) Второй идентификатор, начинающийся с префикса IDI ("идентификатор для значка" — ID for icon) определяется в заголовочных файлах Windows. Значок IDI_APPLICATION — это просто маленькое изображение окна. Функция LoadIcon возвращает описатель этого значка. Фактически нам не важно конкретное значение этого описателя. Оно просто используется для установки значений полей wndclass.hIcon и wndclass.hIconSm. Эти поля определяются в структуре WNDCLASSEX как поля типа HICON, что означает

"описатель значка" (handle to an icon).

Инструкция:

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

очень похожа на две предыдущие инструкции. Функция LoadCursor загружает стандартный курсор IDC_ARROW и возвращает описатель курсора. Этот описатель присваивается полю hCursor структуры WNDCLASSEX. Когда курсор мыши оказывается в рабочей области окна, созданного на основе данного класса, он превращается в маленькую стрелку.

Следующее поле задает цвет фона рабочей области окон, созданных на основе данного класса. Префикс hbr имени поля hbrBackground означает "описатель кисти" (handle to a brush). Кисть — это графический объект, который представляет собой шаблон пикселей различных цветов, используемый для закрашивания области. В Windows имеется несколько стандартных, или предопределенных (stock) кистей. Вызов GetStockObject, показанный здесь, возвращает описатель белой кисти:

wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);

Это означает, что фон рабочей области окна будет плотного белого цвета, что является стандартным выбором.

Следующее поле задает меню класса окна. В приложении HELLOWIN меню отсутствует, поэтому поле установлено в NULL:

wndclass.lpszMenuName = NULL;

На последнем этапе классу должно быть присвоено имя. Для простой программы оно может быть просто именем программы, которым в нашем случае является строка "HelloWin", хранящаяся в переменной szAppName:

wndclass.lpszClassName = szAppName;

После того как инициализированы все 12 полей структуры, HELLOWIN регистрирует класс окна путем вызова функции RegisterClassEx. Единственным параметром функции является указатель на структуру WNDCLASSEX:

RegisterClassEx(&wndclass);

Создание окна

Класс окна определяет основные характеристики окна, что позволяет использовать один и тот же класс для создания множества различных окон. Когда вы, вызывая функцию CreateWindow, фактически создаете окно, вы, таким образом, детализируете информацию об окне.

Новички в программировании для Windows иногда путают понятия класс окна и окно, и не понимают, почему нельзя все характеристики окна задать за один раз. Фактически же, делить таким образом информацию очень удобно. Например, все окна-кнопки создаются на основе одного и того же класса окна. Оконная процедура, связанная с этим классом окна, находится в самой операционной системе Windows. Класс окна определяет для этих кнопок процесс ввода информации с клавиатуры, а также с помощью мыши, и одновременно регламентирует отображение кнопок на экране. Все кнопки, таким образом, работают одинаково. Но, в то же время, сами кнопки не одинаковы. Они могут отличаться по размеру, располагаться в разных местах экрана, иметь отличные друг от друга надписи. Эти последние характеристики и задаются при определении окна, а не класса окна.

Вместо использования структуры данных, как это делается в случае использования функции RegisterClassEx, вызов функции CreateWindow требует, чтобы вся информация передавалась функции в качестве параметров. Далее представлен вызов функции CreateWindow в HELLOWIN.C:

32

hwnd = CreateWindow(

//имя класса окна

szAppName,

"The Hello Program",

//заголовок окна

WS_OVERLAPPEDWINDOW,

//стиль окна

CW_USEDEFAULT,

//начальное положение по x

CW_USEDEFAULT,

//начальное положение по y

CW_USEDEFAULT,

//начальный размер по x

CW_USEDEFAULT,

//начальный размер по y

NULL,

//описатель родительского окна

NULL,

//описатель меню окна

hInstance,

//описатель экземпляра программы

NULL

//параметры создания

);

Для удобства восприятия, использовались символ // и однострочные комментарии для описания параметров функции CreateWindow.

Параметр с комментарием "имя класса окна" — szAppName содержит строку "HelloWin", являющуюся именем только что зарегистрированного класса окна. Таким образом, этот параметр связывает окно с классом окна.

Окно, созданное нашей программой, является обычным перекрывающимся окном с заголовком, системным меню слева на строке заголовка, иконками для сворачивания, разворачивания и закрытия окна справа на строке заголовка и рамкой окна. Это стандартный стиль окон, он называется WS_OVERLAPPEDWINDOW и помечен комментарием "стиль окна". Комментарием "заголовок окна" отмечен текст, который появится в строке заголовка.

Параметры с комментариями "начальное положение по x" и "начальное положение по y" задают начальные координаты верхнего левого угла окна относительно левого верхнего угла экрана. Устанавливая для этих параметров идентификатор CW_USEDEFAULT, мы сообщаем Windows, что хотим использовать для перекрывающегося окна задаваемое по умолчанию начальное положение. (CW_USEDEFAULT задается равным 0x80000000.) По умолчанию Windows располагает следующие друг за другом перекрывающиеся окна, равномерно отступая по горизонтали и вертикали от верхнего левого угла экрана. Примерно также задают ширину и высоту окна параметры с комментариями "начальный размер по x" и "начальный размер по y". CW_USEDEFAULT снова означает, что мы хотим, чтобы Windows использовала задаваемый по умолчанию размер окна.

Параметр с комментарием "описатель родительского окна" устанавливается в NULL, поскольку у нашего окна отсутствует родительское окно. (Если между двумя окнами существует связь типа родительское-дочернее, дочернее окно всегда появляется только на поверхности родительского.) Параметр с комментарием "описатель меню окна" также установлен в NULL, поскольку у нашего окна нет меню. В параметр с комментарием "описатель экземпляра программы" помещается описатель экземпляра, переданный программе в качестве параметра функции WinMain. И наконец, параметр с комментарием "параметры создания" установлен в NULL. При необходимости этот параметр используется в качестве указателя на какие-нибудь данные, на которые программа в дальнейшем могла бы ссылаться.

Вызов CreateWindow возвращает описатель созданного окна. Этот описатель хранится в переменной hwnd, которая имеет тип HWND (описатель окна — handle to a window). У каждого окна в Windows имеется описатель. В вашей программе описатель используется для того, чтобы ссылаться на окно. Для многих функций Windows в качестве параметра требуется hwnd, благодаря этому Windows знает, к какому окну применить функцию. Если программа создает несколько окон, то каждое из них имеет свой описатель. Описатель окна — это один из важнейших описателей, которыми оперирует программа для Windows.

Отображение окна

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

ShowWindow(hwnd, iCmdShow);

Первым параметром является описатель только что созданного функцией CreateWindow окна. Вторым параметром является величина iCmdShow, передаваемая в качестве параметра функции WinMain. Он задает начальный вид окна на экране. Если iCmdShow имеет значение SW_SHOWNORMAL (т. е. 1), на экран выводится обычное окно. Если iCmdShow имеет значение SW_SHOWMINNOACTIVE (т. е. 7), то окно не выводится, а на панели задач появляются его имя и иконка.

Функция ShowWindow выводит окно на экран. Если второй параметр ShowWindow имеет значение SW_SHOWNORMAL, то фон рабочей области окна закрашивается той кистью, которая задана в классе окна. Вызов функции:

UpdateWindow(hwnd);

Соседние файлы в предмете Операционные системы