Статья: Создание консольных приложений с помощью мастера в Visual C++ 6 - 2

Практически каждое приложение, разрабатываемое в Visual C++, содержит один файл ресурсов, одноимённый с самим приложением и имеющий расширение .rc . В нашем случае это Listing4.rc. В нём находятся описания всех ресурсов нашего приложения. У нас здесь будет только таблица строковых ресурсов. В этом и есть высокое предназначение нашей заготовки - она выводит на экран строчку «Hello from MFC!», оформленную как строковый ресурс. Среда ведь на самом деле может сама (с нашей помощью конечно) объявить все необходимые ресурсы, дать им идентификаторы (уникальные имена), связать идентификаторы с конкретными числовыми значениями и т.д. На самом деле это очень удобно, например, для русификации приложения не понадобиться искать в программном коде места где выводятся строчки, а просто в таблице взять и поменять текст с английского на русский, сохранив при этом все идентификаторы и численные значения. В программном коде-то у нас прописаны идентификаторы. Так что умная среда, обеспечив нам такую политику, может избавить нас от значительного геморроя. И это лишь один пример халявы, которую дарит нам Visual C++. При попытке открыть файл Listing4.rc у нас открывается окошко ResourceView. Тут у нас и есть таблица строк. В ней мы можем изменить строку соответствующую данному идентификатору, или создать новый строковый ресурс, поставив ему в соответствие новый идентификатор. Просекаете логику? То-то!

В файле Resource.h просто, используя директиву #define , каждому идентификатору ставится в соответствие численное значение. Здесь же мы можем его поменять или указать его для нового ресурса.

Попробуйте запустить программу, поздоровайтесь с MFC и убедитесь, что приложение работает. Если поздоровались, значит работает. Между тем в нашем рабочем пространстве появилась папочка «External Dependencies» с файлом basetsd.h внутри. В нём, если хотите знать, нам показывают определения базовых типов данных. Это на случай, если нам вздумается (или придётся) использовать 64-битные типы данных.

Между тем и в уже известных нам файлах произошли значительные изменения. Давайте начнем теперь с файла StdAfx.h. В начале всё те же, что и в Listing4.h стражи включения, далее всё та же проверка версии MFC, дальше идёт строчка:

#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

- она для ускорения процесса компиляции (за счёт отказа от некоторых возможностей)

далее идут строчки с подключением основных MFC-шных файлов: afx.h, afxwin.h, afxext.h, afxdtctl.h, afxcmn.h.

Кстати, если будете программировать, используя MFC, очень советую посмотреть эти заголовочные файлы. Если вы знаете язык С++, то должны увидеть там не фигу, а полезную информацию по MFC-классам и функциям и т.д. Бывает ничуть не хуже справочников. А в качестве справочника очень советую MSDN Library.

Ниже расположено место, куда мы подключаем заголовочные файлы, которые редко изменяются и будут использоваться как перекомпилированные (я говорил об этом выше, в начале статьи). Zabot’ливая среда Visual C++ 6.0 уже подключила там <iostream>.

А вот теперь давайте смотреть самое интересное - кончено же Listing4.cpp. Тут у нас вот чего уже готово:

Разбираем по порядку. Как обычно, подключаем stdafx.h, а вместе с ним и Listing4.h . Он подключается здесь, а не в файле stdafx.h, потому что ожидается, что мы этот файл (Listing4.h) будем достаточно часто ковырять. Следующий блок из пяти строчек может оказаться малопонятным. Пожалею я вас и не буду сейчас мозги пудрить, подробно разъясняя эту запись, просто скажу, что она, можно сказать, каноническая, и менять её, как правило, не стоит. Применяется в основном в отладочных целях и во избежание некоторых трудностей с ключевыми словами и именами. Дальше как раз интересное и начинается!

Итак, дальше у нас идёт объявление объекта класса нашего приложения. А именно объявление объекта theApp класса CWinApp. Класс CWinApp является производным от CWinThread. Поэтому класс CWinApp представляет и основной поток выполнения программы, и само приложение. Таким образом, в любом MFC-приложении существует только один объект класса CWinApp. Нас об этом в комментарии уже предупредили.

Строчка

using namespace std;

говорит нам о том, что в данном блоке программы будет использоваться стандартное пространство имён std. Поясняю. В программе может подключаться очень большое число разных файлов заголовков. В каждом файле заголовка используется большое количество различных имен: переменные, функции, классы, структуры и т.д. Разные библиотеки разрабатывают разные люди, и, конечно же, получается так, что в разных библиотеках могут использоваться одинаковые имена. Если мы будем пользоваться сразу несколькими библиотеками, то может сложиться такая ситуация, когда при попытке использовать имя, которое дублируется и в другом подключаемом файле, компоновщик выдаст сообщение об ошибке: «Identifier multiply defined» (Идентификатор определён несколько раз», где идентификатор - это имя какого-либо элемента). Такая ситуация называется конфликтом имён. Для того, чтобы избежать таких проблем и придумали пространства имён. Пространства имён используются для разделения глобального пространства имён, что позволяет пусть и не всегда устранить, но, по крайней мере, уменьшить количество конфликтов имён.

Пространство имен (namespace) по сути представляет собой логическую группу имен, в пределах которой имена не дублируются. Например, пространство имен стандартной библиотеки std. При обращении к идентификатору (имени), входящему в какое-либо пространство имен надо явно указывать это пространство. Поэтому, обращаясь к cout пространства имен std, мы и пишем std::cout. То быть, пишется название пространства имён (std) и через два двоеточия само имя (cout). Вот почему, пользуясь именами из заголовочных файлов стандартной библиотеки (<iostream>, <string>, <list> и др.) мы должны указывать, что всё это относится пространству имён std. Вы можете создавать и свои пространства имён (ну если вам, например, потребуется назвать свою функцию именем cout), но это разговор отдельной статьи.

Запись using namespace std; говорит о том, что в пределах текущей области действия (обычно в пределах фигурных скобок) будет по умолчанию использоваться пространство имён std (не надо будет перед каждым именем писать std:: , если оно принадлежит к этому пространству). Однако этой штукой надо пользоваться очень осторожно - только если вы уверены, что будете использовать только имена указанного пространства, в противном случае могут возникнуть трудности. Если не уверены - лучше не ленитесь и явно указывайте, к какому пространству имен принадлежит данное имя.

Дальше у нас идет функция _tmain. А почему _tmain? И почему там тип TCHAR* , а не char* ? И что ещё за параметр TCHAR* envp[] ?

Ну что же, для интересующихся растолкую. Функция называется _tmain и тип параметров TCHAR* потому что среда генерирует нам такой код, для того чтобы обеспечить совместимость с различными кодировками текста, разных типов char - одно и многобайтных и т.д. и т.п. Не буду вдаваться во все подробности, да и что нам с того: main или _tmain, char или TCHAR? Для нас сейчас, в общем-то, смысл не меняется: _tmain - главная функция в программе, TCHAR* - строка текста. Обо всех проблемах со стандартами уже поZabot’илась среда. А вот касательно envp ?

Как видите, TCHAR* envp[] - тоже массив строк. Он необходим для работы с переменными окружения. Кто не в курсе про переменные окружения - читайте что-нибудь про MS-DOS (напр., Фигурнов «IBM PC для пользователя»). Поскольку работа с переменными окружения и процессами в консоли (а оно часто для того и надо) не так проста, и не слишком часто используется, то более подробно в этой статье я разъяснять про них не буду. Хватит с нас пока аргументов командной строки.

Ниже идет объявление переменной nRetCode - она будет возвращаться функцией _tmain как код ошибки. Напоминаю, если 0 - выполнение программы завершилось успешно, если не 0 - то неуспешно :)

Затем следует собственно инициализация MFC. Обычно (в GUI-приложениях) это происходит так: при инициализации объекта класса CWinApp (или производного от него) функцией WinMain, являющейся частью библиотеки MFC, вызывается функция AfxWinInit и проверяется возвращаемое ею значение. Но, поскольку консольные приложения не используют функцию WinMain, нам приходится вызывать функцию AfxWinInit непосредственно. А она у нас в таком случае просит четыре параметра:

HINSTANCE hInstance

- дескриптортекущегомодуля;

HINSTANCE hPrevInstance

- дескриптор предыдущей копии приложения; для Win32-приложений этот параметр всегда NULL;

LPTSTR lpCmdLine

- указатель на командную строку текущего процесса;

К-во Просмотров: 316
Бесплатно скачать Статья: Создание консольных приложений с помощью мастера в Visual C++ 6 - 2