Программы, управляемые событиями
В этом уроке мы с помощью Studio .NET научимся разрабатывать традиционные приложения Win32, основанные на использовании функций API (Application Programming Interface). Вы, конечно, знаете, что приложения для Windows можно разрабатывать как с использованием библиотеки классов MFC, так и на основе набора инструментов, объединенных в разделе SDK (Software Development Kit) студии разработчика. Обширную документацию по SDK вы можете найти в MSDN (Microsoft Developer's Network), которая поставляется вместе со студией. Отдельные выпуски MSDN, зачастую содержат еще более свежую информацию по SDK. Без MSDN успешная деятельность в рамках студии разработчика просто немыслима.
Использование всей мощи MFC облегчает процесс разработки приложений, однако далеко не все возможности Win32 API реализованы в библиотеке MFC, многие из них доступны только средствами API. Поэтому каждому разработчику необходимо иметь представление о структуре и принципах функционирования традиционного Windows-приложения, созданного на основе API-функций. Другими доводами в пользу того, что существует необходимость знать и постоянно углублять свои познания в технологии разработки приложений с помощью SDK, могут быть следующие:
- каркас MFC-приложения, так или иначе, содержит внутри себя структуру традиционного Windows-приложения;
- многие методы классов MFC содержат, инкапсулируют вызовы API-функций;
- накоплен огромный банк готовых решений на основе SDK, которые достаточно просто внедряются в приложения на основе MFC, и не пользоваться которыми означает обеднять себя.
В состав API входят не только функции, более 2000, но и множество структур, более 800 сообщений, макросы и интерфейсы. Цель настоящей главы:
- показать традиционную структуру Windows-приложения;
- продемонстрировать способы управления таким инструментом подсистемы GDI (Graphics Driver Interface), как перо Windows.
Основной чертой всех Windows-приложений является то, что они поддерживают оконный интерфейс, используя при этом множество стандартных элементов управления (кнопки, переключатели, линейки, окна редактирования, списки и т. д.). Эти элементы поддерживаются с помощью динамических библиотек (DLL), которые являются частью операционной системы (ОС). Именно поэтому элементы доступны любым приложениям, и ваше первое приложение имеет почти такой же облик, как и любое другое. Принципиально важным отличием Windows-приложений от приложений DOS является то, что все они – программы, управляемые событиями (event-driven applications). Приложения DOS – программы с фиксированной последовательностью выполнения. Разработчик программы последовательность выполнения операторов, и система строго ее соблюдает. В случае программ, управляемых событиями, разработчик не может заранее предсказать последовательность вызовов функций и даже выполнения операторов своего приложения, так как эта последовательность определяется на этапе выполнения кода.
Программы, управляемые событиями, обладают большей гибкостью в смысле выбора пользователем порядка выполнения операций. Характерно то, что последовательность действий часто определяется операционной системой и зависит от потока сообщений о событиях в системе. Большую часть времени приложение, управляемое событиями, находится в состоянии ожидания событий, точнее сообщений о них. Сообщения могут поступать от различных источников, но все они попадают в одну очередь системных сообщений. Только некоторые из них система передаст в очередь сообщений вашего приложения. В случае многопотокового приложения сообщение приходит активному потоку (thread) приложения. Приложение постоянно выполняет цикл ожидания сообщений. Как только придет адресованное ему сообщение, управление будет передано его окопной процедуре.
Примечание
Если вы хотите получить более полное представление о процессах и потоках в Windows, то обратитесь к последней главе этой книги, которая носит более познавательный, чем практический характер.
Наступление события обозначается поступлением сообщения. Все сообщения Windows имеют стандартные имена, многие из которых начинаются с префикса WM_ (Windows Message). Например, WM_PAINT именует сообщение о том, что необходимо перерисовать содержимое окна того приложения, которое получило это сообщение. Идентификатор сообщения WM_PAINT – это символьная константа, обозначающая некое число. Другой пример: при создании окна система посылает сообщение WM_CREATE. Вы можете ввести в оконную процедуру реакцию на это сообщение для того, чтобы произвести какие-то однократные действия.
Программист может создать и определить какие-то свои собственные сообщения, действующие в пределах зарегистрированного оконного класса. В этом случае каждое новое сообщение должно иметь идентификатор, превышающий зарезервированное системой значение WM_USER (0x400). Допустим, вы хотите создать сообщение о том, что пользователь нажал определенную клавишу в тот момент, когда клавиатурный фокус находится в особом окне редактирования с уже зарегистрированным классом. В этом случае новое сообщение можно идентифицировать так:
#define WM_MYEDIT_PRESSED WM_USER + 1
Каждое новое сообщение должно увеличивать значение идентификатора по сравнению с WM_MYEDIT_PRESSED. Максимально-допустимым значением для идентификаторов такого типа является число 0x7 FFF. Если вы хотите создать сообщение, действующее в пределах всего приложения и не конфликтующее с системными сообщениями, то вместо константы WM_USER следует использовать другую константу WM_APP (0x8000). В этом случае можно наращивать идентификатор вплоть до 0xBFFF.