Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛекцииЯзыки прогрИб.doc
Скачиваний:
27
Добавлен:
12.11.2019
Размер:
922.11 Кб
Скачать

3.1. Классификация программных продуктов

Visual C++ - это язык программирования C++, служащий для разработки 32-разрядных Windows-приложений и .NET- приложений на базе программной платформы Microsoft Visual Studio 2005.

Visual Studio – это единая среда разработки и инструментарий, служащие для создания программного кода на различных языках программирования: Visual C++, Visual C#, Visual Basic, Visual Java Script. Наша цель – изучение разработки Windows-приложений на последней версии Visual C++ , входящей в состав Visual Studio 2005.

В состав Visual Studio .NET входят средства разработки, позволяющие эффективно и на более высоком уровне создавать C++-программы.

Основу программирования в Visual C++ составляет библиотека классов Microsoft Foundation Classes (MFC), содержащая много стандартных функций для Windows-программирования. Применение библиотеки MFC позволит:

  • освободить программиста от рутинной работы, связанной с написанием общих функций, например, главной функции WinMain, и стандартных каркасов функций приложения;

  • обеспечить программиста более простой, структурированной библиотекой MFC по сравнению с библиотекой Win32 API;

  • уменьшить размер исходного кода (приблизительно в 2-3 раза).

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

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

Язык Visual C++ по сравнению с другими языками характеризуется высоким быстродействием написанных программ, наличием больших библиотек функций. Согласно информации сайта www.optim.ru проведенное тестирование продуктов таких фирм как Borland, Intel, Microsoft показало, что компилятор Visual C++ создает наиболее быстрые приложения. Сравнение компиляторов Visual C++ и Borland C++ 5.02 выявило преимущество Visual C++ не только в компактности программного кода, но и в оптимизации откомпилированных кодов.

Модель программирования в Windows значительно отличается от модели программирования в MS-DOS. Самое главное отличие – это обработка сообщений. Например, в Windows-приложении нельзя использовать напрямую функции чтения данных с клавиатуры, а требуется обработка сообщения. На любое событие, например, нажатие клавиши или кнопки мыши, порождается сообщение. Сообщения – это основной элемент программирования в Windows, для обработки которых требуется написать функции-обработчики. Главная функция WinMain обнаруживает последовательность сообщений и вызывает необходимые функции-обработчики.

Интегрированная среда разработки (Integrated Development Environment) - это общая рабочая область средств работы с языками и библиотеки MSDN, входящие в комплект Visual Studio. Visual C++ является одним из компонентов пакета Visual Studio. Проект – это создаваемое приложение: совокупность файлов заголовков, кодов, ресурсов, а также файлов, содержащих информацию об установках и конфигурации проекта. По умолчанию каждый проект расположен в папке, одноименной с именем проекта. Решение – это приложение, состоящее из одного или нескольких проектов.

При запуске Visual Studio 2005 появляется стартовая страница Start Page. Вкладка Open Projects позволяет открыть существующий проект из списка проектов, вкладка Create Project - открыть новый проект.

3.2. Основные понятия Visual C++

Библиотека классов MFC

Библиотека классов Microsoft Foundation Classes (MFC) содержит более 200 уже написанных классов для Windows - программирования.

Функции классов MFC внутри себя вызывают функции библиотеки Windows Win32 API (1000 функций), т.е. можно сказать, что в MFC включен Win32 API. Преимущество MFC по сравнению с Win32 API заключаются в упрощении и ускорении разработки Windows-приложений.

Библиотека классов MFC имеет следующие преимущества:

  • использует удобно внутри себя библиотеку Win 32 API;

  • упрощает и ускоряет разработку Windows-приложений;

  • создает компактность программного кода;

  • сокращает время разработки графического интерфейса пользователя;

  • значительно упрощает применение прогрессивных технологий программирования: технологии ActiveX, поддержку баз данных с технологиями ODBC и DAO; технологий для работы в Internet.

Библиотека MFC – иерархическая совокупность классов C++ (граф типа дерева), реализующая методы инкапсуляции, наследования и полиморфизма. Все классы MFC разделены на две группы. В первой группе содержатся классы, находящиеся в иерархической зависимости, производные от базового класса CObjekt. Вторую группу составляют независимые классы.

Класс CObject является базовым для большинства классов MFC, обеспечивая их функциями поддержки сериализации (сохранение и восстановление объектов в/из файла), диагностики, отладки и др.

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

Классы MFC можно разделить на несколько категорий:

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

  • пользовательский интерфейс: классы фреймов окон, блоков диалога и элементов управления;

  • вывод данных: классы контекста устройства, графических объектов;

  • наборы данных: классы массивов, простых и ассоциативных списков;

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

  • технология ActiveX: контейнерные и серверные классы для поддержки операций с составными документами;

  • файлы и базы данных: классы файлов ввода/вывода, для доступа с технологиями ODBC и DAO;

  • интернет и сети: классы технологий WinInet API, Internet Server API, Windows Socket.

Ознакомление с функциями классов библиотеки MFC производится в соответствующих главах и параграфах.

Библиотеки MFC и API для идентификации переменных используют соглашение, называемое Венгерской нотацией (автор – венгерский программист Чарлз Симони). Имя переменной состоит из префикса (буквы, обозначающей тип переменной) и описательной части из одного или нескольких слов, причем каждое слово начинается с заглавной буквы. Например, n, i - целое число (тип int), l - длинный тип (long), d - число с двойной точностью (double), c - символьный тип (char), s - строковая переменная и т.д.

Типы приложений

Генератор приложений AppWizard позволяет создавать много разных типов приложений, использующих разные технологии программирования. Для создания приложения и выбора типа проекта в стартовой странице Start Page следует щелкнуть на кнопке New Project (или на пункте меню File->New->Project) и в диалоговом окне New Project на панели Project Types выбрать тип проекта Visual C++ Projects, а на панели Templates – тип шаблона приложения.

Visual C++ создает следующие типы приложений в соответствии с типами проектов и шаблонами:

-Шаблоны типа проекта Visual C++ Project ATL

ATL Project – библиотека активных шаблонов (Active Template Library), используемая для создания приложений с элементами управления ActiveX с более компактным программным кодом по сравнению с использованием библиотеки MFC.

ATL Server Project – создание Web- приложения или XML Web-сервисов.

ATL Server Web Service - создание Web- приложения или XML Web-сервисов. Отличие от предыдущего -в установках.

-Шаблоны типа проекта Visual C++ Project MFC

MFC ActiveX Control – создание элементов управления ActiveX, реализованные классами MFC.

MFC Application – создание наиболее часто используемого типа приложения на основе библиотеки классов MFC, поддерживающего графический интерфейс. Настройка приложения выполняется в 6 этапов:

1. количество окон приложения - SDI-приложение (однодокументный интерфейс), MDI- приложение (многодокументный интерфейс), Dialog based (диалоговое приложение);

2. операции с базами данных (None, без просмотра, с просмотром и без операций с файлами, с просмотром и с операциями);

3. операции с составными документами – это технология ActiveX (None, контейнер, мини-сервер, сервер + автономно контейнер и сервер,);

4. внешний вид приложения, элементов пользовательского интерфейса (панель инструментов, панель состояния, печать и предварительный просмотр, справка, объемный дизайн, почтовый интерфейс, доступ к Internet);

5. включение комментарий, выбор динамически связываемой библиотеки DLL (Dynamic-Link Library) или статически прикомпонованной (statically linked library);

6. подтверждение имен файлов и классов.

В результате настройки создается заготовка выполняемой программы (EXE-файл).

MFC DLL – создание динамической библиотеки функций на основе библиотеки классов MFC.

MFC ISAPI Extension DLL – создание ISAPI- приложения. ISAPI - Internet Server Application Programming Interface (интерфейс программирования приложений интернет-сервера).

-Шаблоны типа проекта Visual C++ Project Win32

Win32 Console Projects – создание консольного приложения. Приложение напоминает DOS-программу, имеет функцию main() и интерфейс, управляемый клавишами клавиатуры.

Win32 Project - создание приложения без использования MFC и AppWizard.

-Шаблоны типа проекта Visual C++ Project General

Custom Wizard – создание собственного шаблона приложения.

Extended Stored Procedure Dll – создает расширенные хранимые процедуры для программированияSQL-сервера.

Makefile Project – создает make-файл, по которому проект собирается утилитой make.exe вместо Visual Studio и позволяет отобразить файлы проекта в окне проекта.

-Шаблоны типа проекта Visual C++ Project .NET

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

Структура и этапы работы приложения

Рассмотрим структуру приложения, создаваемого AppWizard, на примере проекта lab1_2 (SDI-приложение).

Базовая концепция MFC и AppWizard – это понятие “Документ - Представление”. Принято предположение, что любое приложение что-то имеет, что необходимо хранить на диске. Эту совокупность информации обозначили как Документ, а просмотр информации обозначили как Представление.

После выполнения 6 этапов настройки параметров проекта будут созданы следующие главные классы и файлы приложения, представленные в табл. 3.1.

Табл. 3.1.

Класс

Имя класса

Базовый класс

Файлы

Документ

CLab1_2Doc

CDocument

Lab1_2Doc.h

Lab1_2Doc.cpp

Представление

CLab1_2View

CView

Lab1_2View.h

Lab1_2View.cpp

Главное окно

CMainFrame

CFrameWnd

MainFrame.h

MainFrame.cpp

Приложение

CLab1_2App

CWinApp

Lab1_2.h

Lab1_2.cpp

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

Итак, имеем 4 главных класса и 4 пары файлов, представленных выше. Ознакомимся с содержимым файлов Приложения: Lab1_2.h и Lab1_2.cpp.

Файл Lab1_2.h - главный файл заголовков для приложения lab1_2. В начале файла используется директива #if !defined для защиты файла заголовка, то есть для запрета повторного включения файла заголовков в файл кодов.

Главное назначение файла заголовков Lab1_2.h - это объявление класса CLab1_2App, который является наследником класса CWinApp. Класс CLab1_2App объявляет пустой конструктор, виртуальную функцию InitInstance() и функцию OnAppAbout(). AppWizard генерирует странный на первый взгляд, комментарий вокруг объявления InitInstance(). Эти комментарии будут использованы ClassWizard для включения новых переопределений виртуальных функций. Следующая часть текста файла Lab1_2.h - это карта сообщений, в которой объявляется функция OnAppAbout().

В файле Lab1_2.cpp AppWizard генерирует текст элементов- функций класса CLab1_2App: конструктора, InitInstance(), OnAppAbout(). Директива #include <stdafx.h> подключает прекомпилированный файл StdAfx.h, который включает в себя наиболее используемые заголовочные файлы. Это и файл AfxWin.h, который содержит описания классов MFC.

При запуске приложения можно выделить 5 этапов выполнения приложения:

- объявление объекта класса приложения CLab1_2App и вызов конструктора класса;

- вызов функции WinMain();

- вызов функции Initinstance() функцией WinMain;

- выполнение цикла обработки сообщений функцией WinMain;

- выход из WinMain и уничтожение приложения.

На 1-ом этапе вызывается конструктор класса CWinApp.

SDI-приложение определяет один объект своего класса приложения:

////////////////////////////////// файл Lab1_2.cpp///////

//Единственный объект класса CLab1_2App

CLab1_2App theApp;

//...

Объект класса CLab1_2App определен глобально, поэтому, сначала вызывается конструктор класса перед вызовом главной функции WinMain(). Конструктор CLab1_2App() ничего не выполняет (в файле Lab1_2.cpp):

////////////////файл Lab1_2.cpp////

// конструктор Clab2App

CLab1_2App::CLab1_2App

{

//TODO: здесь добавьте код конструктора

// Инициализация наиболее важных переменных и функций

// должна выполняться в InitInstance

}

Такой конструктор по умолчанию вызывает конструктор базового класса CWinApp, который выполняет следующие задачи:

- проверка того, что программа объявляет только один (theApp) объект приложения, принадлежащий классу CLab1_2App или CWinApp;

- сохранение адреса объекта theApp в глобальном указателе, объявленном в MFC; MFC может позже вызывать элементы-функции класса CLab1_2App; вызовы этих функций будут представлены на этапе 3.

Подход к инициализации объектов, используемый в Microsoft - это так называемая двухэтапная инициализация. В файле Lab1_2.cpp AppWizard генерирует текст элементов-функций CLab1_2App() (конструктора) и InitInstance(). На этом этапе выполняется инициализация конструктором, а на 3-ем этапе будет инициализация функцией InitInstance().

На 2-ом этапе вызывается функция WinMain().

Этой функции нет в наших файлах приложения, она определена внутри кода MFC, связывается с приложением Lab1_2 при построении исполняемого файла.

К большому облегчению программистов, теперь они могут не отвлекаться на написание и набивку текста WinMain(), поскольку за них это сделает AppWizard.

Типичная функция WinMain() выглядит следующим образом:

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR IpCmdline,

int nCmdShow)

{

MSG msg;

if (!InitApplication(hInstance))//инициализ. прилож. и регистрации

return (FALSE); //класса окна

if(!InitInstance(hInstance, nCmdShow)) //создание главного окна

return (FALSE); // приложения

while(GetMessage(&msg, NULL, 0,0))//цикл обраб. сообщений

{ //функция GetMessage() присваивает msg код сообщения

TranslateMessage(&msg); //обраб. сообщения от клавиатуры

DispatchMessage(&msg); //

}

return(msg.wParam);

}

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

На 3-ем этапе функция WinMain() вызывает функцию InitInstance(). WinMain() вызывает эту функцию, используя адрес объекта CLab1_2App, сохраненный конструктором CLab1_2App() на этапе 1 в указателе CWinApp. Вызывается переопределенная функция InitInstance() производного класса CLab1_2App, а не базового класса CWinApp, т.к. функция InitInstance() виртуальная. Назначение функции – инициализация приложения. Функция создает шаблон документа, который хранит информацию о классе документа программы, о классе представления и о классе главного окна-рамки. Шаблон документа также содержит идентификатор ресурсов программы, используемых для отображения и управления документом (меню, пиктограмма и т.д.).

На 4-ом этапе функция WinMain() выполняет цикл обработки сообщений. Управление все время остается внутри цикла.

При поступлении сообщения WM_QUIT выполняется 5-ый этап, т.е. . выход из WinMain и закрытие приложения.

Сообщения

Сообщение - это средство, с помощью которого операционная система сообщает приложению о произошедшем событии. Например, пользователь что-то нажал на клавиатуре или щелкнул кнопкой мыши Сообщения WINDOWS управляют всем процессом функционирования приложений..

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

Сообщение - это вход в приложение, представляет собой событие, на которое, должно реагировать приложение. Каждое сообщение связывается с конкретным окном, с каждым из которых, в свою очередь, связана собственная оконная функция. Эта функция вызывается для обработки сообщения. Механизм сообщений в WINDOWS реализуется при помощи очереди сообщений.

Для идентификации событий WINDOWS использует целые числа, но в тексте программы используются текстовые идентификаторы для удобства программирования и читабельности программы. Большое количество директив связывают символьные идентификаторы и соответствующие числа - # define <симв. идент.> <код>, например:

# define WM_PAINT 0X000F # define WM_COMMAND 0X0111

Существуют почти 900 различных сообщений.

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

BM_ ,BN_ - кнопка (button), EM_ ,EN_ - текстовое поле (edit box), WM_ - окно как таковое (generic window).

Примеры сообщений с префиксом WM _ (оконное сообщение):

WM_CHAR - нажатие видимых символов,

WM_KEYDOWN - нажатие невидимых символов (→,←, функциональные клавиши F1…F12).

Все сообщения в MFC разделены на три основные категории:

1. Стандартные сообщения WINDOWS – это сообщения с префиксом WM_, за исключением WM_COMAND, информируют приложение о создании или уничтожении окна, о сообщениях клавиатуры и мыши, предназначены для обработки окнами и представлениями, могут содержать параметры, которые определяют алгоритм обработки сообщения. Сюда входят, например, аппаратные сообщения, сообщения обслуживания окна и др.

2. Командные сообщения (команды) – это сообщения WM_COMMAND , называемые командами, от объектов интерфейса пользователя, которые включают меню, кнопки панелей инструментов, клавиши-акселераторы.

3. Командные сообщения обновления пользовательского интерфейса – это сообщения, которые сообщают приложению об изменении состояния опций меню, кнопок панели инструментов, клавиш-акселераторов, например, сделать опции меню недоступными или помеченными.

4. Извещения элементов управления - это извещения от элементов управления и других дочерних окон, направляемые своему родительскому окну. Например, элемент управления LIST VIEW, просмотр списка, посылает своему родительскому окну сообщение WM_COMMAND , содержащее код извещения LVN_SETDISP-INFO, когда требуется обновить информацию об элементах списка. Оконная процедура отвечает за полученное извещение заполнением структуры LV_DISPINFO и передаёт её обратно в элемент управления.

Обработка сообщений. Карта сообщений

Сердцем любого приложения Windows является цикл обработки сообщений, находящийся в функции WinMain().

В библиотеке MFC использован следующий подход: для обработки каждого отдельного сообщения используется специальная функция-обработчик. Все функции-обработчики являются элементами-функциями какого-либо класса.

Но каким образом сопоставляются сообщение и соответствующая ему функция-обработчик? В традиционных Windows- программах для обработки сообщений используется в функции WndProc() оператор switch с многочисленными ветвями, что крайне не эффективно. В Visual C++ реализация взаимосвязи основана на понятии карты сообщения (message map). Каждый класс, который может получить сообщение, должен иметь свою карту сообщений.

Карта сообщений состоит из двух частей: одна в файле заголовков, другая - в файле кодов.

Пример из Lab2_1 (чтение символа с клавиатуры)

// CLab2_1View.h – файл заголовков

class CLab2_1View::public CView //определение класса представления

{

// Реализация

//{{AFX_MSG (CLab2_1View) //имя класса-владельца карты

//сообщений

afx_msg void OnChar (UINT nChar, //значение символа

UINT nRepCut, //кол-во нажатий

UINT nFlags); //бит состояния перехода

//}} AFX_MSG // //{{ и //}} – скобки-комментарии для ClassWizard

DECLARE_MESSAGE_MAP() //макрос объявл. карты сообщений

}; // конец класса.

Здесь объявляется прототип функции-обработчика OnChar().

Специальным образом оформленный комментарий позволяет ClassWizard определить, какие именно сообщения перехватываются этим классом (классом Clab3aApp).

В конце объявления класса, использующего карту сообщений, размещается макрос DECLARE_MESSAGE_MAP() (объявление карты сообщений). Этот макрос, расширяемый препроцессором компилятора VC++, объявляет карту сообщений, переменные и функции, участвующие в перехвате сообщения.

Вторая часть карты (определение карты сообщений) находится в файле кодов Lab2_1View.cpp.

//CLab2_1View.cpp – файл кодов

...

BEGIN_MESSAGE_MAP(CLab2_1View, CView)//макрос начала карты с.

//{{ AFX_MSG_MAP(CLab2_1View)

On_WM_CHAR()

//}}AFX_MSG_MAP

//стандартные команды печати.

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

END_MESSAGE_MAP//макрос конца определения карты сообщ.

Структура карты сообщений представляет собой набор макросов, называемых компонентами карты сообщений.

Для каждого стандартного сообщения Windows (1-ая категория сообщений) определен свой макрос в форме: ON_ WM_XXX, где XXX -имя сообщения, например: ON_WM_CHAR.

Имена функций - обработчиков определяются при распаковке параметров каждого сообщения Windows на основе следующего простого соглашения. Имя функции-обработчика состоит из префикса On и имени соответствующего сообщения (без WM).

Например: afx_msg void OnChar(…) - это обработчик для сообщения WM_CHAR (нажата клавиша видимого символа). За формирование параметров функции-обработчика отвечает соответствующий макрос.

Для командных сообщений (2-ая категория сообщений) определен макрос в форме:

ON_COMMAND (Id, Fn) , где Id - идентификатор командного сообщения, Fn -функция-обработчик.

Пример, из нашего приложения:

ON_COMMAND (ID_FILE_PRINT, CView::OnFilePrint)

Для командных сообщений обновления пользовательского интерфейса (3-я категория сообщений) определен макрос в форме:

ON_UPDATE_COMMAND_UI (Id, Fn)

Для обработки извещений от элементов управления (4-ая категория сообщений) определен макрос в форме:

ON_XXX (…), где XXX – название извещения.

Например, для обработки извещений, введенных программистом, применяются макросы ON_CONTROL и ON_ NOTIFY:

ON_CONTROL (cod, id, Fn)

, где cod – код извещения от элемента управления, id – идентификатор извещения, Fn – функция.

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

ON_MESSAGE - обработка сообщений, созданных программистом.

Существует более 100 макросов, по одному на каждое сообщение, которые направляют сообщения функциям-обработчикам.

Пример из lab1_2. Если выбрать команду меню Help->About, выводится сообщение об авторских правах.

//lab1_2.h

class CLab1_2App::public CWinApp

{...

//реализация

//{{AFX_MSG (CLab1_2App)

afx_msg void OnAppAbout();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

}; ...

// lab1_2.cpp

BEGIN_MESSAGE_MAP (Clab1_2App, CWinApp)

//{{AFX_MSG_MAP(CLab1_2App)

ON_COMMAND (ID_APP_ABOUT, OnAppAbout)

//}} AFX_MSG_MAP

ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)

//стандартные

ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen)

//файловые

ON_COMMAND(ID_FILE_PRINT_SETUP, //команды

CWinApp::OnFilePrintSetup)

END_MESSAGE_MAP

Но что же происходит с картой сообщений?

В цикле обработки сообщений при поступлении сообщения вызывается (как и без MFC) функция WndProc() (теперь AfxWndProc()) того окна, для которого предназначено сообщение.

Эта функция знает дескриптор окна hWnd, для которого предназначено сообщение. Библиотека MFC, в свою очередь, имеет карту дескрипторов - таблицу дескриптовых окон и указателей объектов. Таким образом, программа может найти указатель объекта CWnd*. Далее она вызывает виртуальную функцию этого объекта класса (WindowProc()). А эта функция вызывает OnWndMsg() - функцию C++, которая обрабатывает сообщение, выполняя маршрутизацию команд. Во-первых, она проверяет, что же это было - сообщение, команда или код извещения. Предположим, потупило сообщение. Тогда функция просматривает карту сообщений для своего класса и определяет функцию-обработчика. Если не находится, то просматривается базовый класс, если нет, то - обработка по умолчанию.

Большое преимущество MFC - наличие готовых классов, которые перехватывают и обрабатывают большинство распространенных сообщений.