В связи с тем, что сегодня уровень сложности программного обеспечения очень высок, разработка приложений Windows с использованием только какого-либо языка программирования (например, языка C) значительно затрудняется. Программист должен затратить массу времени на решение стандартных задач по созданию многооконного интерфейса. Реализация технологии связывания и встраивания объектов - OLE - потребует от программиста еще более сложной работы.
Чтобы облегчить работу программиста практически все современные компиляторы с языка C++ содержат специальные библиотеки классов. Такие библиотеки включают в себя практически весь программный интерфейс Windows и позволяют пользоваться при программировании средствами более высокого уровня, чем обычные вызовы функций. За счет этого значительно упрощается разработка приложений, имеющих сложный интерфейс пользователя, облегчается поддержка технологии OLE и взаимодействие с базами данных.
Современные интегрированные средства разработки приложений Windows позволяют автоматизировать процесс создания приложения. Для этого используются генераторы приложений. Программист отвечает на вопросы генератора приложений и определяет свойства приложения - поддерживает ли оно многооконный режим, технологию OLE, трехмерные органы управления, справочную систему. Генератор приложений, создаст приложение, отвечающее требованиям, и предоставит исходные тексты. Пользуясь им как шаблоном, программист сможет быстро разрабатывать свои приложения.
Подобные средства автоматизированного создания приложений включены в компилятор Microsoft Visual C++ и называются MFC AppWizard. Заполнив несколько диалоговых панелей, можно указать характеристики приложения и получить его тексты, снабженные обширными комментариями. MFC AppWizard позволяет создавать однооконные и многооконные приложения, а также приложения, не имеющие главного окна
, -вместо него используется диалоговая панель. Можно также включить поддержку технологии OLE, баз данных, справочной системы.Конечно, MFC AppWizard не всесилен. Прикладную часть приложения программисту придется разрабатывать самостоятельно. Исходный текст приложения, созданный MFC AppWizard, станет только основой, к которой нужно подключить остальное. Но работающий шаблон приложения - это уже половина всей работы. Исходные тексты приложений, автоматически полученных от MFC AppWizard, могут составлять сотни
строк текста. Набор его вручную был бы очень утомителен.Нужно отметить, что MFC AppWizard создает тексты приложений только с использованием библиотеки классов MFC (Microsoft Foundation Class library). Поэтому только изучив язык C++ и библиотеку MFC, можно пользоваться средствами автоматизированной разработки и создавать свои приложения в кратчайшие сроки.
MFC – это базовый набор (библиотека) классов, написанных на языке С++ и предназначенных для упрощения и ускорения процесса программирования под Windows. Перед изучением библиотеки MFC и ее использованием для создания Windows-приложений, следует вспомнить, как работает сама Windows и каковы принципы взаимодействия программ с ней, какова структура типичной Windows-программы.
Рассмотрим наиболее важные моменты работы Windows и принципы взаимодействия программ с ней.
Интерфейс вызовов функций в Windows
Благодаря данному интерфейсу доступ к системным ресурсам осуществляется через целый рад системных функций. Совокупность таких функций называется прикладным программным интерфейсом, или API (Application Programming Interfase). Для взаимодействия с Windows приложение запрашивает функции API, с помощью которых реализуются все необходимые системные действия, такие как выделение памяти, вывод на экран, создание окон и т.п.
Библиотека MFC инкапсулирует многие функции API. Хотя программам и разрешено обращаться к ним напрямую, все же чаще это будет выполняться через соответствующие функции-члены. Как правило, функции-члены либо аналогичны функциям API, либо непосредственно обращаются к нужной части интерфейса.
Библиотеки динамической загрузки (DLL)
Поскольку API состоит из большого числа функций, может сложиться впечатление, что при компиляции каждой программы, написанной для Windows, к ней подключается код довольно значительного объема. В действительности это не так. Функции API содержатся в библиотеках динамической загрузки (Dynamic Link Libraries, или DLL), которые загружаются в память только в тот момент, когда к ним происходит обращение, т.е. при выполнении программы. Рассмотрим, как осуществляется механизм динамической загрузки.
Динамическая загрузка обеспечивает ряд существенных преимуществ. Во-первых, поскольку практически все программы используют API-функции, то благодаря DLL-библиотекам существенно экономится дисковое пространство, которое в противном случае занималось бы большим количеством повторяющегося кода, содержащегося в каждом из исполняемых файлов. Во-вторых, изменения и улучшения в Windows-приложениях сводятся к обновлению только содержимого DLL-библиотек. Уже существующие тексты программ не требуют перекомпиляции.
Win16 или Win32
В настоящее время широко распространены две версии API. Первая называется Win16 и представляет собой 16-разрядную версию, используемую в Windows 3.1. Вторая, 32-разрядная версия, называется Win32 и используется в Windows 95 и Windows NT. Win32 является надмножеством для Win16 (т.е. фактически включает в себя этот интерфейс), так как большинство функций имеет то же название и применяется аналогичным образом. Однако, будучи в принципе похожими, оба интерфейса все же отличаются друг от друга. Win32 поддерживает 32-разрядную линейную адресацию, тогда как Win16 работает только с 16-разрядной сегментированной моделью памяти. Это привело к тому, что некоторые функции были модифицированы таким образом, чтобы принимать 32-разрядные аргументы и возвращать 32-разрядные значения. Часть из них пришлось изменить с учетом 32-разрядной архитектуры. Была реализована поддержка потоковой многозадачности, новых элементов интерфейса и прочих нововведений Windows.
Так как Win32 поддерживает полностью 32-разрядную адресацию, то логично, что целые типы данных (intergers) также объявлены 32-разрядными. Это означает, что переменные типа int и unsignerd будут иметь длину 32 бита, а не 16, как в Windows 3.1. Если же необходимо использовать переменную или константу длиной 16 бит, они должны быть объявлены как short. (дальше будет показано, что для этих типов определены независимые typedef-имена.) Следовательно, при переносе программного кода из 16-разрядной среды необходимо убедиться в правильности использования целочисленных элементов, которые автоматически будут расширены до 32 битов, что целочисленных элементов, которые автоматически будут расширены до 32 битов, что может привести к появлению побочных эффектов.
Другим следствием 32-разрядной адресации является то, что указатели больше не нужно объявлять как near и far. Любой указатель может получить доступ к любому участку памяти. В Windows 95 и Windows NT константы near и far объявлены (с помощью директивы #define)пустыми.
Интерфейс GDI
Одним из подмножеств API является GDI (Graphics Device Interfase – интерфейс графического устройства). GDI – это та часть Windows, которая обеспечивает поддержку аппаратно-независимой графики. Благодаря функциям GDI Windows-приложение может выполняться на самых различных компьютерах.
Многозадачность в Windows
Как известно, все версии Windows поддерживают многозадачность. В Windows 3.1 имеется только один тип многозадачности – основанный на процессах. В более передовых системах, таких как Windows 95 и Windows NT, поддерживается два типа многозадачности: основанный на процессах и основанный на потоках. Давайте рассмотрим их чуть подробнее.
Процесс – это программа, которая выполняется. При многозадачности такого типа две или более программы могут выполняться параллельно. Конечно, они по очереди используют ресурсы центрального процессора и с технической точки зрения, выполняются неодновременно, но благодаря высокой скорости работы компьютера это практически незаметно.
Поток – это отдельная часть исполняемого кода. Название произошло от понятия “направление протекания процесса”. В многозадачности данного типа отдельные потоки внутри одного процесса также могут выполняться одновременно. Все процессы имеют по крайней мере один поток, но в Windows 95 и Windows NT их может быть несколько.
Отсюда можно сделать вывод, что в Windows 95 и Windows NT допускается существование процессов, две или более частей которых выполняются одновременно. Оказывается, такое предположение верно. Следовательно, при работе в этих операционных системах возможно параллельное выполнение, как программ, так и отдельных частей самих программ. Это позволяет писать очень эффективные программы.
Есть и другое существенное различие между многозадачностями Windows 3.1 и Windows 95/NT. В Windows 3.1 используется неприоритетная
многозадачность. Это означает, что процесс, выполняющийся в данный момент, получает доступ к ресурсам центрального процессора и удерживает их в течение необходимого ему времени. Таким образом, неправильно выполняющаяся программа может захватить все ресурсы процессора и не давать выполняться другим процессам. В отличие от этого в Windows 95 и Windows NT используется приоритетная многозадачность. В этом случае каждому активному потоку предоставляется определенный промежуток времени работы процессора. По истечению данного промежутка управление автоматически передается следующему потоку. Это не дает возможность программам полностью захватывать ресурсы процессора. Интуитивно должно быть понятно, что такой способ более предпочтителен.Взаимодействие программ и Windows
Во многих операционных системах взаимодействие между системой и программой инициализирует программа. Например, в DOS программа запрашивает разрешение на ввод и вывод данных. Говоря другими словами, не- Windows-программы сами вызывают операционную систему. Обратного процесса не происходит. В Windows все совершенно наоборот: именно система вызывает программу. Это осуществляется следующим образом: программа ожидает получения сообщения от Windows. Когда это происходит, то выполняется некоторое действие. После его завершения программа ожидает следующего сообщения.
Windows может посылать программе сообщения множества различных типов. Например, каждый раз при щелчке мышью в окне активной программы посылается соответствующее сообщение. Другой тип сообщений посылается, когда необходимо обновить содержимое активного окна. Сообщения посылаются также при нажатии клавиши, если программа ожидает ввода с клавиатуры. Необходимо запомнить одно: по отношению к программе сообщения появляются случайным образом. Вот почему Windows-программы похожи на программы обработки прерываний: невозможно предсказать, какое сообщение появиться в следующий момент.
Поскольку архитектура Windows-программ основана на принципе сообщений, все эти программы содержат некоторые общие компоненты. Обычно их приходится в явном виде включать в исходный код. Но, к счастью, при использовании библиотеки MFC это происходит автоматически; нет необходимости тратить время и усилия на их написание. Тем не менее, чтобы до конца разобраться, как работает Windows-программа, написанная с использованием MFC, и почему она работает именно так, необходимо в общих чертах понять назначение этих компонентов.
Функция WinMain()
Все Windows-программы начинают выполнение с вызова функции WinMain(). При традиционном методе программирования это нужно делать явно. С использованием библиотеки MFC такая необходимость отпадает, но функция все-таки существует.
Функция окна
Все Windows-программы должны содержать специальную функцию, которая не используется в самой программе, но вызывается самой операционной системой. Эту функцию обычно называют функцией окна, или процедурой окна. Она вызывается Windows, когда системе необходимо передать сообщение в программу. Именно через нее осуществляется взаимодействие между программой и системой. Функция окна передает сообщение в своих аргументах. Согласно терминологии Windows, функции, вызываемые системой, называются функциями обратного вызова. Таким образом, функция окна является функцией обратного вызова.
Помимо принятия сообщения от Windows, функция окна должна вызывать выполнение действия, указанного в сообщении. Конечно, программа не обязана отвечать на все сообщения, посылаемые Windows. Поскольку их могут быть сотни, то большинство сообщений обычно обрабатывается самой системой, а программе достаточно поручить Windows выполнить действия, предусмотренные по умолчанию.
В большинстве Windows-программ задача создания функции окна лежит на программисте. При использовании библиотеки MFC такая функция создается автоматически. В этом заключается одно из преимуществ библиотеки. Но в любом случае, если сообщение получено, то программа должна выполнить некоторое действие. Хотя она может вызывать для этого одну или несколько API-функций, само действие было инициировано Windows. Поэтому именно способ взаимодействия с операционной системой через сообщения диктует общий принцип построения всех программ для Windows, написанных как с использованием MFC, так и без нее.
Цикл сообщений
Как объяснялось выше, Windows взаимодействует с программой, посылая ей сообщения. Все приложения Windows должны организовать так называемый цикл сообщений (обычно внутри функции WinMain()). В этом цикле каждое необработанное сообщение должно быть извлечено из очереди сообщений данного приложения и передано назад в Windows, которая затем вызывает функцию окна программы с данным сообщением в качестве аргумента. В традиционных Windows-программах необходимо самостоятельно создавать и активизировать такой цикл. При использовании MFC это также выполняется автоматически. Однако важно помнить, что цикл сообщений все же существует. Он является неотъемлемой частью любого приложения Windows.
Процесс получения и обработки сообщений может показаться чересчур сложным, но тем не менее ему должны следовать все Windows-программы. К счастью, при использовании библиотеки MFC большинство частных деталей скрыты от программиста, хотя и продолжают неявно присутствовать в программе.
Класс окна
Как будет показано дальше, каждое окно в Windows-приложении характеризуется определенными атрибутами, называемыми классом окна. (Здесь понятие “класс” не идентично используемому в С++. Оно, скорее, означает стиль или тип.) В традиционной программе класс окна должен быть определен и зарегистрирован прежде, чем будет создано окно. При регистрации необходимо сообщить Windows, какой вид должно иметь окно и какую функцию оно выполняет. В то же время регистрация класса окна еще не означает создание самого окна. Для этого требуется выполнить дополнительные действия. При использовании библиотеки MFC создавать собственный класс окна нет необходимости. Вместо этого можно работать с одним из заранее определенных классов, описанных в библиотеке. В этом еще одно ее преимущество.
Специфика программ для Windows
Структура Windows-программ отличается от структуры программ других типов. Это вызвано двумя обстоятельствами: во-первых, способом взаимодействия между программой и Windows, описанным выше; во-вторых, правилами, которым следует подчиняться для создания стандартного интерфейса Windows-приложения (т.е. чтобы сделать программу “похожей “ на Windows-приложение).
Цель Windows – дать человеку, который хотя бы немного знаком с системой, возможность сесть за компьютер и запустить любое приложение без предварительной подготовки. Для этого Windows предоставляет дружественный интерфейс пользователя. Теоретически, если пользователь сумел запустить одно Windows-приложение, то он сумеет запустить и любое другое. Конечно, на практике придется немного потренироваться, чтобы научиться использовать большинство программ с максимальной эффективностью. Однако это связано исключительно с тем, что программа делает, а не с тем, как ею пользоваться. Ведь, фактически, значительная часть кода Windows-приложения предназначена именно для организации интерфейса с пользователем.
Хотя создание удобного интерфейса “под Windows” является основной задачей при написании любой Windows-программы, такой интерфейс не создается автоматически. То есть вполне можно написать программу, в которой элементы интерфейса используются неэффективно. Чтобы этого избежать, необходимо целенаправленно применять методику, описанную в данной книге. Только программы, написанные таким способом, будут выглядеть и работать действительно так, как надлежит Windows-программам.
Чтобы отойти от философии создания традиционного Windows-интерфейса, должны быть достаточно веские основания. Иначе пользователи этой программы будут разочарованы. В общем, если программист собирается писать приложения для Windows, то он должен дать пользователям возможность работать с обычным интерфейсом и руководствоваться стандартной методикой разработки.
Типы данных в Windows
В Windows-программах вообще (и в использующих библиотеку MFC в частности) не слишком широко применяются стандартные типы данных из С или С++, такие как int или char*. Вместо них используются типы данных, определенные в различных библиотечных (header) файлах. Наиболее часто используемыми типами являются HANDLE, HWND, BYTE, WORD, DWORD, UNIT, LONG, BOOL, LPSTR и LPCSTR. Тип HANDLE обозначает 32-разрядное целое, используемое в качестве дескриптора. Есть несколько похожих типов данных, но все они имеют ту же длину, что и HANDLE, и начинаются с литеры Н. Дескриптор – это просто число, определяющее некоторый ресурс. Например, тип HWND обозначает 32-разрядное целое – дескриптор окна. В программах, использующих библиотеку MFC, дескрипторы применяются не столь широко, как это имеет место в традиционных программах. Тип BYTE обозначает 8-разрядное беззнаковое символьное значение, тип WORD – 16-разрядное беззнаковое короткое целое, тип DWORD – беззнаковое длинное целое, тип UNIT - беззнаковое 32-разрядное целое. Тип LONG эквивалентен типу long. Тип BOOL обозначает целое и используется, когда значение может быть либо истинным, либо ложным. Тип LPSTR определяет указатель на строку, а LPCSTR – константный (const) указатель на строку.
Как уже упоминалось, MFC – это базовый набор (библиотека) классов, написанных на языке С++ и предназначенных для упрощения и ускорения процесса программирования для Windows. Библиотека содержит многоуровневую иерархию классов, насчитывающую около 200 членов. Они дают возможность создавать Windows-приложения на базе объектно-ориентированного подхода. С точки зрения программиста, MFC представляет собой каркас, на основе которого можно писать программы для Windows.
Библиотека MFC разрабатывалась для упрощения задач, стоящих перед программистом. Как известно, традиционный метод программирования под Windows требует написания достаточно длинных и сложных программ, имеющих ряд специфических особенностей. В частности, для создания только каркаса программы таким методом понадобится около 75
строк кода. По мере же увеличения сложности программы ее код может достигать поистине невероятных размеров. Однако та же самая программа, написанная с использованием MFC, будет примерно в три раза меньше, поскольку большинство частных деталей скрыто от программиста.Одним из основных преимуществ работы с MFC является возможность многократного использования одного и того же кода. Так как библиотека содержит много элементов, общих для всех Windows-приложений, нет необходимости каждый раз писать их заново. Вместо этого их можно просто наследовать (говоря языком объектно-ориентированного программирования). Кроме того, интерфейс, обеспечиваемый библиотекой, практически независим от конкретных деталей, его реализующих. Поэтому программы, написанные на основе MFC,
могут быть легко адаптированы к новым версиям Windows (в отличие от большинства программ, написанных обычными методами).Еще одним существенным преимуществом MFC является упрощение взаимодействия с прикладным программным интерфейсом (API) Windows. Любое приложение взаимодействует с Windows через API, который содержит несколько сот функций. Внушительный размер API затрудняет попытки понять и изучить его целиком. Зачастую даже сложно проследить, как отдельные части API связанны друг с другом! Но поскольку библиотека MFC объединяет (путем инкапсуляции) функции API в логически организованное множество классов, интерфейсом становится значительно легче управлять.
Поскольку MFC представляет собой набор классов, написанных на языке С++, поэтому программы, написанные с использованием MFC, должна быть в то же время программами на С++. Для этого необходимо владеть соответствующими знаниями. Для начала необходимо уметь создавать собственные классы, понимать принципы наследования и уметь переопределять виртуальные функции. Хотя программы, использующие библиотеку MFC, обычно не содержат слишком специфических элементов из арсенала С++, для их написания тем не менее требуются солидные знания в данной области.
Замечание. Небольшое число классов, определенных в библиотеке, не связанно непосредственно с программированием под Windows. Это, в частности, классы, предназначенные для создания строк, управления файлами и обработки особых ситуаций. Иногда называемые классами общего назначения, они могут использоваться как Windows-, так и не- Windows-приложениями.
Студия разработчика фирмы Microsoft (Microsoft Developer Studio) - это интегрированная среда для разработки, позволяющая функционировать различным средам разработки, одна из которых Visual C++, другая - Visual J++. В дальнейшем будет идти речь только о среде разработки Visual C++.
В студии разработчика можно строить обычные программы на C и С++, создавать статические и динамические библиотеки, но основным режимом работы является создание Windows-приложений с помощью инструмента
MFC AppWizard (Application Wizard - мастер приложений) и библиотеки базовых классов MFC (Microsoft Foundation Class Library). Такие приложения называются MFC-приложениями. Главная особенность этих Windows-приложений состоит в том, что они работают как совокупность взаимодействующих объектов, классы которых определены библиотекой MFC.Главная часть библиотеки MFC состоит из классов, используемых для построения компонентов приложения. С каждым MFC-приложением связывается определяющий его на верхнем уровне объект theApp, принадлежащий классу, производному от
CWinApp.Как правило, структура приложения определяется архитектурой Document-View (документ-облик). Это означает, что приложение состоит из одного или нескольких документов - объектов, классы которых являются производными от класса
CDocument (класс "документ"). С каждым из документов связаны один или несколько обликов - объектов классов, производных от CView (класс "облик ") и определяющих облик документа.Класс
CFrameWnd ("окна-рамки") и производные от него определяют окна-рамки на дисплее. Элементы управления, создаваемые при проектировании интерфейса пользователя, принадлежат семейству классов элементов управления. Появляющиеся в процессе работы приложения диалоговые окна - это объекты классов, производных от CDialog.Классы
CView, CFrameWnd, CDialog и все классы элементов управления наследуют свойства и поведение своего базового класса CWnd ("окно"), определяющего по существу Windows-окно. Этот класс в свою очередь является наследником базового ласса CObject ("объект").Одна из трудностей в понимании принципов устройства MFC-приложения, заключается в том, что объекты, из которых оно строится, наследуют свойства и поведение всех своих предков, поэтому необходимо знать базовые классы.
У всех Windows-приложений фиксированная структура, определяемая функцией WinMain. Структура приложения, построенного из объектов классов библиотеки MFC, является еще более определенной.
Приложение состоит из объекта
theApp, функции WinMain, и некоторого количества других объектов. Сердцевина приложения - объект theApp - отвечает за создание всех остальных объектов и обработку очереди сообщений. Объект theApp является глобальным и создается еще до начала работы функции WinMain. Работа функции WinMain заключается в последовательном вызове двух методов объекта theApp: InitInstance и Run. В терминах сообщений можно сказать, WinMain посылает объекту theApp сообщение InitInstance, которое приводит в действие метод InitInstance.Получив сообщение InitInstance, theApp создает внутренние объекты приложения. Процесс создания выглядит как последовательное порождение одних объектов другими. Набор объектов, порождаемых в начале этой цепочки, определен структурой MFC практически однозначно - это главная рамка, шаблон, документ, облик. Их роли в работе приложения будут обсуждаться позже.
Следующее сообщение, получаемое theApp, - Run - приводит в действие метод
Run. Оно как бы говорит объекту: "Начинай работу, начинай процесс обработки сообщений из внешнего мира". Объект theApp циклически выбирает сообщения из очереди и инициирует обработку сообщений объектами приложения.Некоторые объекты имеют графический образ на экране, с которым может взаимодействовать пользователь. Эти интерфейсные объекты обычно связаны с Windows-окном. Среди них особенно важны главная рамка и облик. Именно им объект прежде всего распределяет сообщения из очереди через механизм Windows-окон и функцию Dispatch.
Когда пользователь выбирает команду меню окна главной рамки, то возникают командные сообщения. Они отправляются сначала объектом theApp объекту главная рамка, а затем обходят по специальному маршруту целый ряд объектов, среди которых первыми являются документ и облик, информируя их о пришедшей от пользователя команде.
При работе приложения возникают и обычные вызовы одними объектами методов других объектов. В объектно-ориентированной терминологии такие вызовы могут называться сообщениями. В Visual C++ некоторым методам приписан именно этот статус (например, методу OnDraw).
Важное значение имеют также объекты документ, облик и главная рамка. Здесь отметим только, что документ содержит данные приложения, облик организует представление этих данных на экране, а окно главной рамки
- это окно, внутри которого размещены все остальные окна приложения.Наследование - одна из фундаментальных идей объектно-ориентированного программирования. Именно этот механизм наследования позволяет программисту дополнять и переопределять поведение базового класса, не вторгаясь в библиотеку MFC, которая остается неизменной. Все изменения делаются в собственном производном классе. Именно в этом и заключается работа программиста.
Объекты, их которых состоит приложение, являются объектами классов, производных от классов библиотеки MFC. Разработка приложения состоит в том, что программист берет из библиотеки MFC классы
CWinApp, CFrameWnd, CDocument, CView и т.д. и строит производные классы. Приложение создается как совокупность объектов этих производных классов. Каждый объект несет в себе как наследуемые черты, определяемые базовыми классами, так и новые черты, добавленные программистом. Наследуемые черты определяют общую схему поведения, свойственную таким приложениям. Новые же черты позволяют реализовать специфические особенности поведения приложения, необходимые для решения стоящей перед ним задачи.При определении производного класса программист может:
Приложение, построенное на основе библиотеки MFC, - "айсберг", большая часть которого невидима, но является основой всего приложения. Часть приложения, лежащую в библиотеке MFC, - framework - называется каркасом приложения. Рассмотрим работу приложения как процесс взаимодействия между каркасом и частью приложения, разработанной программистом. Совершенно естественно, что в методах, определенных программистом, могут встречаться вызовы методов базового класса, что вполне можно рассматривать как вызов функции из библиотеки. Важнее, однако, что и метод производного класса, определенный программистом, может быть вызван из метода родительского класса. Другими словами, каркас и производный класс в этом смысле равноправны - их методы могут вызывать друг друга. Такое равноправие достигается благодаря виртуальным методам и полиморфизму, имеющимся в арсенале объектно-ориентированного программирования.
Если метод базового класса объявлен виртуальным и разработчик переопределил его в производном классе, это значит, что при вызове данного метода в некоторой полиморфной функции базового класса в момент исполнения будет вызван метод производного класса и, следовательно, каркас вызывает метод, определенный программистом. Точнее говоря, обращение к этому методу должно производиться через ссылку на производный объект либо через объект, являющийся формальным параметром и получающий при вызове в качестве своего значения объект производного класса. Когда вызывается виртуальный метод М1, переопределенный разработчиком, то согласно терминологии Visual C++, каркас посылает сообщение М1 объекту производного класса, а метод М1 этого объекта обрабатывает это сообщение. Если сообщение М1 послано объекту производного класса, а обработчик этого сообщения не задан программистом, объект наследует метод М1 ближайшего родительского класса, в котором определен этот метод. Если же обработчик такого сообщения создан программистом, он автоматически отменяет действия, предусмотренные родительским классом в отсутствие этого обработчика.
С Visual C++ тесно связано еще одно понятие - каркас приложений, которое близко и созвучно понятию каркаса приложения, но в отличие от него относится не к одному конкретному приложению, а к библиотеке, с помощью которой строятся многие приложения. Каркас приложений - это библиотека классов, из которых программист берет не только набор классов, играющих роль
дополнительных типов данных, но и классы, служащие строительными блоками приложения на самом верхнем уровне. С этой точки зрения, каркас приложения является частью каркаса приложений, относящейся к данному приложению. Примеры каркасов приложений - библиотеки классов MFC и OWL.О принципах устройства приложения рассказывалось выше. Теперь рассмотрим, как оно создается с помощью Visual C++. Сначала разберем одно важное понятие - проект. До сих пор приложение рассматривалось, как только как совокупность объектов базовых и производных классов. Но для обеспечения работы приложения требуется нечто большее - наряду с описанием классов необходимо описание ресурсов, связанных с приложением, нужна справочная система и т.п. Термин "проект" как раз и используется, когда имеется в виду такой более общий взгляд на приложение.
В среде Visual C++ можно строить различные типы проектов. Такие проекты после их создания можно компилировать и запускать на исполнение. Фирма Microsoft разработала специальный инструментарий, облегчающий и ускоряющий создание проектов в среде Visual C++. Например, мастер
MFC AppWizard (exe) позволяет создать проект Windows-приложения которое имеет однодокументный, многодокументный или диалоговый интерфейс и использует библиотеку MFC.Создаваемый остов приложения составлен так, что в дальнейшей работе с проектом можно использовать другое инструментальное средство - ClassWizard (мастер классов), предназначенное для создания остовов новых производных классов. Еще одно основное назначение ClassWizard в том, что он создает остовы для переопределяемых методов. Он позволяет показать все сообщения, приходящие классу, и создать остов обработчика любого из этих сообщений. Это только две основные функции ClassWizard. Он не всесилен, но его возможности довольно велики.
В состав компилятора Microsoft Developer Studio встроены средства, позволяющие программисту облегчить разработку приложений. В первую очередь к ним относятся MFC AppWisard, ClassWizard и редактор ресурсов.
Благодаря MFC AppWizard среда разработчика позволяет быстро создавать шаблоны новых приложений. При этом программисту не приходится писать ни одной строчки кода. Достаточно ответить на ряд вопросов, касающихся того, какое приложение требуется создать, и исходные тексты шаблона приложения вместе с файлами ресурсов готовы. Эти тексты можно оттранслировать и получить готовый загрузочный модуль приложения.
Конечно, никакие средства автоматизированной разработки не смогут создать программу полностью без участия программиста. Прикладную часть приложения придется разрабатывать ему.
Для создания ресурсов приложения предназначен редактор ресурсов. Он позволяет быстро создавать новые меню, диалоговые панели, добавлять кнопки к панели управления toolbar и т.д.
Средство ClassWizard позволяет подключить к созданным и отредактированным ресурсам управляющий ими код. Большую часть работы по описанию и определению функций, обрабатывающих сообщения от меню, органов управления диалоговых панелей и т.д., также берет на себя средство ClassWizard.
В среде Visual C++ можно строить различные типы проектов. Такие проекты после их создания можно компилировать и запускать на исполнение. Фирма Microsoft разработала специальный инструментарий, облегчающий и ускоряющий создание проектов в среде Visual C++.
Рассмотрим некоторые типы проектов, которые можно создавать при помощи различных средств (мастеров проектов) Microsoft Visual C++:
MFC AppWizard (exe) – при помощи мастера приложений можно создать проект Windows-приложения которое имеет однодокументный, многодокументный или диалоговый интерфейс. Однодокументное приложеие может предоставлять пользователю в любой момент времени работать только с одним файлом. Многодокументное приложение, напротив, может одновременно представлять несколько документов, каждый в собственном окне. Пользовательский интерфейс диалогового приложения представляет собой единственное диалоговое окно.
MFC AppWizard (dll) – этот мастер приложений позволяет создать структуру DLL, основанную на MFC. При помощи него можно определить характеристики будующей DLL.
AppWizard ATL COM – это средство позволяет создать элемент управления ActiveX или сервер автоматизации, используя новую библиотеку шаблонов ActiveX (ActiveX Template Library - ATL). Опции этого мастера дают возможность выбрать активный сервер (DLL) или исполняемый внешний сервер (exe-файл).
Custom AppWizard – при помощи этого средства можно создать пользовательские мастера AppWizard. Пользовательский мастер может базироваться на стандартных мастерах для приложений MFC или DLL, а также на существующих проектах или содержать только определеямые разработчиком шаги.
DevStudio Add-in Wizard – мастер дополнений позволяет создавать дополнения к Visual Studio. Библиотека DLL расширений может поддерживать панели инструментов и реагировать на события Visual Studio.
MFC ActiveX ControlWizard - мастер элементов управления реализует процесс создания проекта, содержащего один или несколько элементов управления ActiveX, основанных на элементах управления MFC.
Win32 Application – этот мастер позволяет создать проект обычного Window-приложения. Проект создается незаполненным, файлы с исходным кодом в него следует добавлять вручную.
Win32 Console Application – мастер создания проекта консольного приложения. Консольная приложение – это программа, которая выполняется из командной cтроки окна DOS или Windows и не имеет графического интерфейса (окон). Проект консольного приложения создается пустым, предполагая добавление файлов исходного текста в него вручную.
Win32 Dynamic-Link Library – создание пустого проекта динамически подключаемой библиотеки. Установки компилятора и компоновщика будут настроены на создание DLL. Исходные файлы следует добавлять вручную.
Win32 Static Library – это средство создает пустой проект, предназначенный для генерации статической (объектной) библиотеки. Файлы с исходным кодом в него следует добавлять вручную.
Рассмотрим преимущества использования мастеров в процессе создания приложений. Прежде всего, нужно отметить, что создание проекта - это не только творчество, но и большой объем технической работы, требующей внимания и аккуратности.
Например, все Windows-приложения имеют достаточно общую структуру, и, следовательно, можно построить некоторые шаблонные заготовки, подходящие для того или иного типа проектов. Построению таких заготовок способствует то, что приложения, создаваемые на основе MFC, строятся из элементов фиксированных классов. Логическим развитием этой идеи было введение специальных классов и специальной архитектуры построения приложения, которая подходила бы широкому классу приложений. О такой архитектуре уже упоминалось, когда речь шла о библиотеке MFC, - это архитектура Document-View. Она является основной, но не единственной при построении проектов в среде Visual C++.
Суть этой архитектуры в том, что работу многих приложений можно рассматривать как обработку документов. При этом можно отделить сам документ, отвечающий за представление и хранение данных, от образа этого документа, видимого на экране и допускающего взаимодействие с пользователем, который просматривает и (или) редактирует документ. В соответствии с этой архитектурой библиотека MFC содержит два семейства классов, производных от базовых классов CDocument и CView.
В результате появилась двухэтапная технология создания проектов. Вначале создается некая заготовка проекта с общими свойствами, подходящими для многих проектов этого типа. На втором этапе производится уже настройка, учитывающая специфику задачи. Для каждого этапа фирма Microsoft разработала свое инструментальное средство.
Начальная заготовка - остов приложения - создается в диалоге с пользователем инструментальным средством AppWizard. В процессе диалога пользователь определяет тип и характеристики проекта, который он хочет построить. Определив, какие классы из MFC необходимы для этого проекта, AppWizard строит остовы всех нужных производных классов. Построенный AppWizard остов приложения содержит все необходимые файлы для создания стартового приложения
, которое является законченным приложением и обладает разумными функциональными свойствами, общими для целого класса приложений. Естественно, никаких специфических для данного приложения свойств остов не содержит. Они появятся на следующем этапе, когда программист начнет работать с остовом, создавая из заготовки свое собственное приложение. Тем не менее стартовое приложение можно транслировать и запускать на исполнение.Термин остов (приложения, класса, функции) применяется для заготовок, создаваемых инструментальными средствами AppWizard и ClassWizard. Нужно подчеркнуть - остов приложения и каркас приложения - разные понятия.
Создаваемый остов приложения составлен так, что в дальнейшей работе с проектом можно использовать другое инструментальное средство - ClassWizard (мастер классов).
Средство ClassWizard предоставляет широкий спектр услуг. Он позволяет не только добавлять к существующему классу новые методы и данные.
Создание нового класса. При помощи ClassWizard можно добавить новый класс, созданный на основе базовых классов. В качестве базового класса можно использовать классы, наследованные от класса
CCmdTarget или класса CRecordset. Для наследования классов от других базовых классов использовать средства ClassWizard нельзя. Такие классы надо создавать вручную, непосредственно в текстовом редакторе.Объекты, порожденные от класса
CCmdTarget, могут обрабатывать сообщения Windows и команды, поступающие от меню, кнопок, акселераторов. Класс CCmdTarget и другие наследованные от него классы имеют таблицу сообщений (Message Map) - набор макрокоманд, позволяющий сопоставить сообщения Windows и команды метода класса.Полученная заготовка класса полностью работоспособна. Ее можно дополнить по своему усмотрению новыми методами и данными. Эту работу можно выполнить вручную, но гораздо лучше и проще воспользоваться услугами ClassWizard. За счет использования ClassWizard процедура создания собственного класса значительно ускоряется и уменьшается вероятность совершить ошибку во время объявления методов.
Включение в класс новых методов. Очень удобно использовать ClassWizard для включения в состав класса новых методов. Можно добавлять к классу методы, служащие для обработки сообщений Windows и команд от объектов, а также методы, переопределяющие виртуальные методы базовых классов.
ClassWizard не только позволяет добавить в класс новые методы, но и удалить их. ClassWizard самостоятельно удалит объявление метода из класса.
Включение в класс новых элементов данных. ClassWizard позволяет включать в класс не только новые методы, но и элементы данных, связанные с полями диалоговых панелей, форм просмотра и форм для просмотра записей баз данных и полей наборов записей. ClassWizard использует специальные процедуры, чтобы привязать созданные им элементы данных к класса к полям диалоговых панелей. Эти процедуры носят названия "обмен данными диалоговой панели" и "проверка данных диалоговой панели" (Dialog Data Exchange and Dialog Data Validation - DDX/DDV). Чтобы привязать поля из наборов записей к переменным, используется процедура обмена данными с полями записей (Record Field Exchange - RFX).
Процедуры DDX/DDV и RFX значительно упрощают программисту работу с диалоговыми панелями. Они позволяют связать поля диалоговых панелей и переменные. Когда пользователь редактирует поля диалоговых панелей, процедуры DDV проверяют введенные значения и блокируют ввод запрещенных значений. Затем процедуры DDX автоматически копируют содержимое полей диалоговых панелей в привязанные к ним элементы данных класса. И наоборот, когда приложение изменяет элементы данных класса, привязанные к полям диалоговой панели, процедуры DDX могут сразу отобразить новые значения полей на экране компьютера.
Библиотека MFC содержит большое количество классов, структур, констант и т.д. Для того, чтобы текст MFC-приложений был более легким для понимания, принято применять ряд соглашений для используемых имен и комментариев.
Названия всех классов и шаблонов классов библиотеки MFC начинаются с заглавной буквы C. При наследовании классов от классов MFC можно давать им любые имена. Рекомендуется начинать их названия с заглавной буквы C. Это сделает исходный текст приложения более ясным для понимания.
Чтобы отличить элементы данных, входящих в класс, от простых переменных, их имена принято начинать с префикса m_. Названия методов классов, как правило, специально не выделяются, но обычно их начинают с заглавной буквы.
Библиотека MFC включает в себя, помимо классов, набор служебных функций. Названия этих функций начинаются с символов Afx, например
AfxGetApp. Символы AFX являются сокращением от словосочетания Application FrameworkX, означающих основу приложения, его внутреннее устройство.Символы AFX встречаются не только в названии функций MFC. Многие константы, макрокоманды и другие символы начинаются с этих символов. В общем случае AFX является признаком, по которому можно определить принадлежность того или иного объекта (функция, переменная, ключевое слово или символ) к библиотеке MFC.
Когда приложение разрабатывается средствами MFC AppWizard и ClassWizard, они размещают в исходном тексте приложения комментарии следующего вида:
//{{AFX_ ... //}}AFX_
Такие комментарии образуют блок кода программы, который управляется только средствами MFC AppWizard и ClassWizard. Пользователь не должен вручную вносить изменения в этом блоке. Для этого необходимо употреблять средства ClassWizard.
В следующей таблице представлено краткое описание некоторых блоков //{{AFX_:
Блок | Описание |
//{{AFX_DATA | Включает объявление элементов данных класса. Используется в описании классов диалоговых панелей. |
//{{AFX_DATA_INIT | Включает инициализацию элементов данных класса. Используется в файле реализации классов диалоговых панелей. |
//{{AFX_DATA_MAP | Включает макрокоманды DDX, предназначенные для связывания элементов данных класса и органов управления диалоговых панелей. Используется в файле реализации классов диалоговых панелей. |
//{{AFX_MSG | Включает описание методов, которые предназначены для обработки сообщений. Этот блок используется при описании класса. |
//{{AFX_MSG_MAP | Включает макрокоманды таблицы сообщений класса. Используются совместно с AFX_MSG. |
//{{AFX_VIRTUAL | Включает описание переопределенных виртуальных методов класса. Блок AFX_VIRTUAL используется при описании класса. |
MFC AppWizard и ClassWizard помогают разрабатывать приложения. Они создают все классы и методы, необходимые для его работы. Программисту остается дописать к ним свой код. В тех местах, где можно вставить свой код, MFC AppWizard и ClassWizard, как правило помещают комментарии:
//TODO:
Электронная библиотека InfoCityАвтор и координатор проекта:Михаил ПинкусУ Вас есть документация, которой нет в нашей библиотеке? Присылайте. |