Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции -Процедурное программирование в Windows.doc
Скачиваний:
13
Добавлен:
13.09.2019
Размер:
742.91 Кб
Скачать

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

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

возвращается значение TRUE, в противном случае - FALSE. Проверять возвращаемое функцией

RegisterClass() значение желательно, т.к. при неудачной регистрации класса вы не сможете его

использовать. Если по какой-либо причине регистрация класса прошла неудачно, приложение должно прекратить свою работу.

Отметим, что создавая, например, дочерние окна, вы можете пользоваться некоторыми стандартными предопределенными типами окон, вызов RegisterClass() в этом случае опускается.

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

Создание окна осуществляется при помощи функции CreateWindow(). Она создает окно, имеющее указанный тип и принадлежащее указанному классу. При этом указывается несколько параметров: имя класса окна, заголовок окна, тип окна, положение окна, дескриптор «родительского» окна, дескриптор меню окна, дескриптор создающей окно копии приложения и 32 бита дополнительной информации.

Отметим, что если класс окна регистрируется приложением только один раз - при первом запуске - то главное окно приложения создается для каждой его копии, вызванной на выполнение. Ниже приводится пример создания окна приложения, принадлежащему к классу «Simple» (класс «Simple» мы уже зарегистрировали ранее):

hWnd = CreateWindow ( szName, // Имя класса

" Application", // Заголовок окна

WS_OVERLAPPEDWINDOW, // Тип окна

CW_USEDEFAULT, // X - координата

CW_USEDEFAULT, // Y - координата

CW_USEDEFAULT, // Ширина окна

CW_USEDEFAULT, // Высота окна

NULL, // Дескриптор копии-родителя

NULL, // Дескриптор меню

hInstance, // Дескриптор копии

NULL); // Дополнительная информация

При создании окна функцией CreateWindow() определяются текущие характеристики окна.

В приведенном выше примере создается окно, принадлежащее классу окна szName.

Строка " Application" является заголовком окна.

Третий параметр WS_OVERLAPPEDWINDOW является комбинацией битовых флагов, определенных во включаемом файле windows.h. Все константы типов (или «стилей») окон начинаются с букв WS (Window Style). Комбинируя их при помощи булевой операции «ИЛИ» (|), можно определять нужные типы окон приложения. Типы окон Windows и допустимые флаги будут рассмотрены более подробно ниже .

После указания типа окна задаются начальные геометрические размеры создаваемого окна: координаты левого верхнего угла относительно экрана, ширина и высота окна в пикселях. Если при задании этих параметров использовать константу CW_USEDEFAULT, то Windows установит наиболее подходящие, с его точки зрения, значения этих полей.

При создании окна указывается также дескриптор его «родителя» (используется с органами управления и дочерними окнами) и меню окна. Перекрывающееся окно не может иметь «родителя», поэтому соответствующему параметру в примере выше присваивается значение NULL. Перекрывающемуся окну может быть назначено меню, однако в примере параметр NULL говорит о том, что требуется только системное меню (меню класса). Если меню класса не определено, то окно не будет иметь меню вообще.

При создании окна необходимо указать, какая копия приложения создает окно с тем, чтобы при работе с окном использовались данные именно этой копии, а не какие-либо другие. Последний параметр используется для передачи окну дополнительных данных. В примере никаких дополнительных данных окну не передается, этот параметр устанавливается в NULL.

Если функция CreateWindow () создает окно успешно, возвращается дескриптор на новое окно. Этот дескриптор указывается при вызове функций, выполняющих какие-либо действия над самим окном или в его пользовательской (несистемной) области.

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

В случае успешного создания окна функция CreateWindow() возвратит индекс окна. Если CreateWindow() возвращает нуль, то окно не создано:

if (! hWnd) // Создание окна прошло успешно?

return NULL; // Если нет, тогда завершаем приложение

Окно не отображается на экране сразу после создания; для отображения окна используется функция ShowWindow().

Отображение и обновление окна.

Хотя функция CreateWindow() и создает окно, это не значит, что оно будет автоматически отображаться на экране дисплея. Для отображения окна следует воспользоваться функцией ShowWindow(), а для обновления окна функцией UpdateWindow(). Эти функции вызываются, как правило, сразу же после создания окна функцией CreateWindow():

ShowWindow (hWnd, nCmdShow) ; // Отображение окна

UpdateWindow (hWnd) ; // Обновление окна

Функция ShowWindow() отображает окно, дескриптор которого передается ей в качестве первого параметра (практически для всех функций работы с окнами первым параметром должен быть указан дескриптор окна). Второй передаваемый параметр определяет, как отображается окно - в виде пиктограммы или полностью. Если параметр nCmdShow равен SW_SHOWNORMAL, то окно отображается открытым, а если он равен SW_SHOWMINNOACTIVE, то окно отображается в виде пиктограммы.

Функция UpdateWindow() передает функции окна, заданного параметром hWnd, сообщение WM_PAINT. Получив это сообщение, функция окна обновляет содержимое окна.

Таким образом, для отображения окна на экране необходимо:

  • Зарегистрировать класс окна функцией RegisterClass().

  • Создать окно функцией CreateWindow().

  • Отобразить окно функцией ShowWindow().

  • Обновить окно функцией UpdateWindow().

Такое разделение на ряд этапов имеет большое значение.

Во-первых, зарегистрировав класс окна, программа может создавать не одно, а несколько окон, несколько копий.

Во-вторых, порядок и место вызова функций ShowWindow() и UpdateWindow() не является обязательным. Окно может быть отображено не в момент создания, а позже.

Создание цикла обработки очереди сообщений

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

Простейшая петля обработки очереди сообщений состоит из функций GetMessage() и DispatchMessage():

MSG Msg;

.

.

.

while (GetMessage (&Msg, NULL, NULL, NULL))

DispatchMessage (&Msg);

Функция GetMessage() извлекает сообщение из очереди приложения, помещая его в структуру Msg. Указание вторым аргументом NULL говорит о том, что следует обрабатывать все сообщения. Каждое получаемое приложением сообщение (за исключением WM_QUIT) принадлежит одному из окон приложения.

Поскольку приложение не должно прямо вызывать функцию обработки окна, для передачи сообщения нужному окну используется специальная функция DispatchMessage(), которая указывает Windows, что данное сообщение должно быть передано соответствующей функции окна. При этом принадлежность сообщения данному окну отслеживается и поддерживается Windows автоматически.

В зависимости от того, какие функции будет выполнять ваше приложение, цикл обработки очереди сообщений может усложниться. Перед функцией DispatchMessage() могут быть помещены специальные функции, производящие над помещенными в очередь сообщениями какие-то действия. Например, при помощи функции TranslateMessage() можно привести все сообщения, пришедшие с клавиатуры, к стандарту ANSI. Работая с очередью приложения, можно назначать на те или иные действия (команды) приложения произвольные комбинации клавиш.

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

  • п еремещении курсора мыши в окне;

  • нажатии или опускании клавиши мыши тогда, когда курсор мыши находится в окне;

  • н ажатии или опускании клавиши на клавиатуре тогда, когда данное окно активно.

Администратор окон сначала помещает все сообщения в системную очередь, а затем копирует нужные сообщения в очередь соответствующего приложения.

Когда функция GetMessage() возвращает NULL, извлекая из очереди приложения сообщение WM_QUIT, происходит выход из цикла обработки очереди сообщений. Сообщение WM_QUIT, таким образом, является средством завершения работы приложения. Оно обычно помещается в очередь приложения одной функцией главного окна данного приложения.

Передача управления

Передав управление приложению, Windows не может забрать управление обратно и ждет, пока приложение не освободит процессор. Таким образом, в Windows возможен захват процессора неправильно работающим приложением и вызванное этим «зависание» системы.

Для того чтобы обеспечить более равномерное разделение вычислительных ресурсов процессора между приложениями, при отсутствии сообщений в очереди приложения функция GetMessage() автоматически передает управление Windows. Таким образом, если приложение в данный момент времени не задействовано, Windows может передать управление другому приложению. Поскольку все приложения имеют цикл обработки очередей сообщений, такая неявная передача управления в какой-то степени обеспечивает разделение вычислительных ресурсов процессора. В большинстве случаев механизм передачи управления функции GetMessage() вполне удовлетворительно разделяет время процессора. Однако, если ваше приложение, например, пишет на диск большие объемы данных или производит большую вычислительную работу, другие задачи не будут работать, пока ваше приложение не передаст управление Windows.

В WIN32 проблемы захвата процессора приложением не возникает, так как WIN32 работает с приложениями в режиме разделения времени. В этом режиме работы каждое приложение обрабатывается установленный квант времени после чего запоминаются состояния регистров и WIN32 переходит к обработке очередного приложения в течении того же кванта времени. Такой процесс продолжается все время циклически. Переходя к обработке очередного приложения WIN32 восстанавливает состояние регистров и продолжает работу с приложением с прерванной точки.

Завершение работы приложения

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

Однако после входа в цикл обработки очереди сообщений единственным способом завершить приложение является посылка в очередь приложения сообщения WM_QUIT. Это делается в функции главного окна вызовом специальной функции PostQuitMessage(). Когда функция GetMessage() извлекает из очереди приложения это сообщение, она возвращает NULL, что приводит к завершению работы приложения. По умолчанию сообщение WM_QUIT посылается только функцией главного окна.

Хотя при завершении приложения в функциях PostQuitMessage() и WinMain() указывается возвращаемое значение, в настоящее время Windows его не использует (возвращаемое значение копируется в параметр wParam сообщения WM_QUIT):

return msg. wParam; // возвращаемое значение копируется из сообщения // WM_QUIT

При завершении приложения следует аккуратно освобождать занятые ресурсы.