Учебное пособие: Окна приложений в среде Windows

Итак, мы рассмотрим основы оранизации приложения в среде Windows и отметим несколько нюансов:

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

Обычно, хотя это и не обязятельно, функция WinMain реализует следующую схему:

1) выполняются требуемые инициализационные действия

2) создается главное окно приложения, для чего часто регистрируется новый класс окон (оконная функция);

3) организуется цикл обработки сообщений приложения. Обычно цикл завершается при закрытии главного окна приложения (не всегда)

4) после завершения цикла обработки сообщений выполняется “деинициализация” данных и освобождение занятых ресурсов, после чего функция WinMain() закнчивается.

Несколько замечаний:

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

Замечание 2 . В некоторых случаях приложение может обойтись без регистрации класса окон и организации цикла обработки сообщений, применяя в качестве главного окна модальный диалог.

Замечание 3 . В момент вызова функции WinMain() ей, через аргументы, передается несколько параметров, например хендл копии приложения (hInstance). До вызова WinMain() приложение “не знает” этих данных. Поэтому могут возникать сложности с использованием статических конструкторов объектно-ориентрованных языков (C++).

Эта особенность, вообще говоря совершенно неестественна. Дело в том, что функция WinMain() вызывается не непосредственно средой Windows, а промежуточным startup-кодом, являющимся частью run-time библиотеки (как и в DOS-приложениях). Этот код инициализирует стандартные переменные, кучу, стек, обнуляет неинициаизированные статические данные и вызывает конструкторы статических объектов до вызова функции WinMain().

Windows вызывает непосредственно этот startup-код, передавая ему нужные данные через регистры. То есть, в тот момент, когда вызываются конструкторы статических объектов, параметры функции WinMain() уже известны, и, более того, они даже сохранены в статических переменных. Однако по непонятным соображениям эти переменные не декларированы как публичные и являются локальными для startup-кода.

Замечание 4 . Цикл обработки сообщений, в том виде, который рекомендован руководствами, не проверяет наличие окон у приложения. Для его завершения используется сообщение WM_QUIT, извлечение которого из очереди приводит к завершению цикла.

При этом требуется, что бы сообщение WM_QUIT посылалось с помощью функций PostMessage(), PostAppMessage() или PostQuitMessage() (только тогда оно попадает в очередь приложения). Обычно это сообщение посылается при уничтожении главного окна приложения (при обработке сообщения WM_DESTROY направленного этому окну). В более общем случае подразумевается последнее окно приложения.

Вы обязаны сами предусмотреть средства для посылки сообщения WM_QUIT, так как ни один стандартный обработчик не посылет его. Конечно, Вы можете предусмотреть собственные, альтернативные методы для прерывания цикла обработки сообщений. Так, например, Вы можете в цикле обработки сообщений проверять корректность хендла главного окна:

while ( IsWindow( hMainWnd ) ) {

if ( !GetMessage( &msg, NULL, NULL, NULL ) ) break;

TranslateMessage( &msg );

DispatchMessage( &msg );

}

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

Замечание 5 . Windows не является объектно-ориентированной средой. Хотя окно и может быть названо объектом ООП, но лишь с достаточной натяжкой. Самое существенное отличие окна в Windows от объекта ООП заключается в том, что сообщение, обрабатываемое оконной функцией, во многих случаях не выполняет действий, а является “информативным”, указывая на то, что над окном выполняется та или иная операция какиой-либо внешней функцией.

Поясним это на примере создания окна. В случае “чистого” ООП для создания объекта он должен получить сообщение “create”, обработка которого приведет к его инициализации. В Windows сообщение WM_CREATE не выполняет никаких функций по созданию окна. Оно только информирует окно о том, что в это время окно создается средствами обычной функциональной библиотеки, например посредством функции CreateWindowEx(). Вы можете вообще игнорировать это сообщение, возвращать любой результат, вызывать или не вызывать функцию обработки по умолчанию - окно все равно будет создано.

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

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

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

Замечание 6 . В Windows существует определенная путаница терминов. Попробуем разобраться с некоторыми из них. Как известно, окно может находиться в нескольких состояниях:

· максимизированом , то есть быть “распахнутым” на весь экран - при этом внутренняя область окна занимает весь экран, кроме небольших полос сверху - где размещается заголовок и меню, снизу - горизонтальная полоса прокрутки и справа - вертикальная полоса прокрутки; рамка окна находится за пределами экрана, мы ее не видим, перемещение окна невозможно.

--> ЧИТАТЬ ПОЛНОСТЬЮ <--

К-во Просмотров: 324
Бесплатно скачать Учебное пособие: Окна приложений в среде Windows