В своей простейшей форме групповой блок помечается как статический прямоугольник, визуально группирующий другие управляющие
элементы.
Конструктор TListBox имеет 7 стандартных параметров конструктора объекта управляющего элемента (родительское окно, идентификатор ресурса, размеры и положение управляющего элемента, необязательный идентификатор библиотеки), плюс текстовую строку,
помечающую группу.
Обычно групповой блок объединяет другие управляющие элементы, однако он может также логически объединять группы кнопок. Эти
логические группы выполняют автоматическую отмену выбора (BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON). Чтобы добавить к групповому блоку кнопку с зависимой или независимой фиксацией, передайте указатель на объект группового блока при вызове конструктора кнопки.
При наступлении события, которое может изменить выбор в
групповом блоке Windows посылает родительскому окну группового
блока уведомляющее сообщение. Родительское окно может перехватывать сообщение для группового блока в целом, а не отвечать на выбор отдельных кнопок. Для определения задействованного управляющего элемента вы можете получить текущее состояние каждой кнопки.
Объединение точек останова в группы позволяет разрешать,
запрещать или удалять их одним действие. Кроме того, одной командой можно задать группу точек останова для всех функций (или
функций-элементов) модуля.
Команда Group в локальном меню окна Breakpoint активизирует
диалоговое окно Edit Breakpoint Groups, с помощью которого вы можете создать или модифицировать точки останова.
[*] Edit Breakpoint groups
Group
1 #BCDEMO#38 #BCDEMO#39 OK
3 #BCDEMO#40
Help
Add... Delete Enable Disable
Группа точек останова идентифицируется положительным целым
числом, которое автоматически генерируется отладчиком или назначается вами. Отладчик автоматически присваивает групповое число
каждой создаваемой точке останова. Генерируемый номер группы
представляет собой наименьший еще не использованный номер. Таким
образом, если номера 1, 2 и 5 уже используются группами, то следующей создаваемой точке останова автоматически присваивается номер группы 3. После создания точки останова вы можете модифицировать статус ее группы с помощью команды Breakpoint Groups.
Кнопка Add окна Edit Breakpoints активизирует диалоговое окно Add Group, содержащее один блок списка и набор кнопок с зависимой фиксацией. Блок списка Module/Class выводит список модуле или классов текущей программы. Посветите нужных модуль или класс
и выберите OK. Все устанавливаемые таким образом точки останова
объединяются в одну группу. Кнопка Delete удаляет подсвеченную
группу, а Enable/Disable разрешают или временно запрещают данную
группу.
Кнопки с зависимой фиксацией позволяют выбрать тип функций,
выводимых в блоке Module/Class: кнопка Modules выбирает все модули в текущей программе, а кнопка Classes - все ее классы.
Handler for тип_1 hidden by previous handler for тип_2
Предупреждение компилятора
Такое предупреждение выводится, когда обработчик для производного от B типа D задан после обработчика для B, так как обработчик для D в этом случае вызываться не будет.
спецификатор has already been included
Сообщение об ошибке этапа компиляции
(спецификатор уже был включен)
Данный спецификатор типа встречается в объявлении более одного раза. Удалите или измените один из них.
Hexadecimal value contains more than 3 digits
Предупреждение этапа компиляции
(шестнадцатиричное значение содержит более 3 цифр)
В старых версиях Си шестнадцатиричная управляющая последовательность могла иметь не более трех цифр. Новый стандарт ANSI
допускает любое число цифр, лишь бы значение помещалось в байт.
Это сообщение выдается, когда шестнадцатиричная управляющая последовательность имеет много ведущих нулей (например, "\x00045").
Старые версии Си интерпретировали бы данную строку иначе.
функция_1 hides virtual function функция_2
Предупреждение этапа компиляции
(функция_1 скрывает виртуальную функцию_2)
Виртуальная функция базового класса обычно переопределяется
объявлением в производном классе. В данном случае объявление того
же имени с другими типами аргументов делает функцию недоступной
последующим производным классам.
Каждый документ и объект отображаемого элемента содержит
список характеристик, а также функции, которые вы можете использовать для опроса и изменения этих характеристик. Характеристики
содержат информацию об объекте и его свойствах. Когда администратор документа создает или уничтожает документ или объект отображаемого элемента, он посылает приложению уведомляющее событие.
Для определения нужных действий приложение может опросить характеристики объекта. Отображаемые документы также имеют доступ к
характеристикам соответствующего документа.
Кроме атрибутов интерфейсного элемента интерфейсные объекты
имеют характеристики объекта ObjectWindows. С помощью функций
SetFlag, ClearFlag и IsFlagSet вы можете запросить и изменить эти
характеристики. При работе с данными функциями можно использовать
следующие флаги:
| wfAlias | Указывает, является ли объект псевдонимом |
| wfAutoCreate | Указывает, разрешено ли для объект
автоматическое создание. |
| wfFromResource | Показывает, загружен ли интерфейсны
элемент из ресурса |
| wfShrinkToClient | Задает сжатие окна-рамки до размер
клиентного окна |
| wfMainWindow | Указывает, что окно является основным |
| wfPredefinedClass | Определяет, что окно является предопределенным классом Windows. |
| wfTransfer | Показывает, может ли окно использовать механизм передачи данных. |
TWindow предусматривает также пару функций, которые позволяют вам изменять ресурсы и характеристики интерфейсного элемента.
Так как TWindow обеспечивает общие для большого числа объектов
функции, никаких специальных функций для управления характеристиками и ресурсами в нем не предусмотрено. Дополнительно к функциональным возможностям TWindow предусмотрены следующие функции:
SetCaption - устанавливает заголовок окна.
GetWindowTextTitle - возвращает строку, содержащую заголовок текущего окна.
SetCursor - устанавливает в экземпляре курсор, идентифицируемый параметром TModule (курсор передается в параметре в виде ресурса).
Присвоив Attr.AccelTable идентификатор ресурса (строку или
целое число), вы можете задать для окна таблицу акселераторов.
Каждый управляющий элемент VBX имеет ряд характеристик. С их
помощью вы можете, например, изменять цвета различных частей управляющего элемента, его размер и расположение, заголовок и т.д.
В изменении этих характеристик заключается обычно основной способ
манипулирования управляющим элементом VBX. Характеристики управляющего элемента VBX должны быть полностью описаны в руководствах
по библиотекам управляющих элементов.
TVbxControl предусматривает ряд методов для получения информации о характеристиках. С помощью функции GetNumProps вы можете
получить общее число характеристик.
Получить имя характеристики в данном диапазоне вы можете с
помощью функции-элемента TVbxControl GetPropName, которая имеет
один параметр (индекс) и возвращает строку с именем характеристики. Индекс характеристики по ее имени можно получить с помощью
GetPropIndex.
Получить значение характеристики вы можете по ее имени или
индексу. Хотя индекс использовать эффективнее, применение имени
понятнее. Вы можете использовать тот или иной метод по своему усмотрению.
Для получения характеристик управляющего элемента TVbxControl предусматривает функцию GetProp, которая позволяет получать
характеристики, используя индекс или имя.
Устанавливать значение характеристики также можно по ее индексу или имени. Для этого в TVbxControl предусмотрена функция
SetProp.
Эта переменная содержит длину ближней динамически распределяемой области памяти в малых моделях данных (tinu. small, medium) и описывается следующим образом:
extern unsigned _heaplen;
В моделях small и medium размер сегмента данных вычисляется
следующим образом:
сегмент данных [small,medium] = глобальные данные +
динамически распределяемая область + стек
где размер стека можно настроить с помощью _stklen.
Если _heaplen установлена в 0 (по умолчанию), то программа
выделяет для сегмента данных 64К, и размером динамически распределяемой области будет:
64K - (глобальные данных + стек)
В модели tiny все (включая код) находится в одном и том же
сегменте, поэтому размер сегмента данных вычисляется следующим
образом (с учетом 256 байт для PSP):
сегмент данных [tiny] = 256 + глобальные данные +
динамически распределяемая область + стек
Если в модели tiny _heaplen = 0, то фактический размер динамически распределяемой области вычисляется вычитанием из 64К PSP,
кода, глобальных данных и стека.
В моделях compact и large ближней динамически распределяемой
области нет, и стек имеет собственный сегмент, поэтому сегмент
данных вычисляется так:
сегмент данных [compact, large] = глобальные данные
В модели huge стек находится в отдельном сегменте, и каждый
модуль имеет собственный сегмент данных.
Identifier expected
Сообщение об ошибке этапа компиляции
(требуется идентификатор)
Здесь ожидался идентификатор, но не был найден. В Си это может случиться в списке параметров старого заголовка функции, после резервируемых слов struct или union при отсутствии фигурных
скобок, а также при отсутствии имени поля структуры или объединения (за исключением битовых полей нулевой длины). В С++ после
двойного двоеточия (::) и после резервируемого слова operator при
отсутствии символа операции идентификатор также требуется в списке базовых классов, производным от которых является данный.
Identifier идентификатор cannot have a type qualifier
Сообщение об ошибке этапа компиляции:
(идентификатор "идентификатор" не может иметь квалификатор
типа)
Квалификатор С++ класс::идентификатор здесь неприменим. Квалификатор не разрешен для имен typedef, объявлений функций (за
исключением определения на уровне файла) или локальных переменных
и параметров функций, либо для элементов класса, за исключением
использования как квалификатора собственного имени класса (избыточно, но допустимо).
If statement missing (
Сообщение об ошибке этапа компиляции
(в операторе if отсутствует ()
В операторе if компилятор не нашел левой (открывающей) круглой скобки после ключевого слова if.
If statement missing )
Сообщение об ошибке этапа компиляции
(В операторе if отсутствует ))
В операторе if компилятор не нашел правой (закрывающей)
круглой скобки после выражения проверки.
If statement too long
Сообщение об ошибке утилиты MAKE
(слишком длинный оператор if)
Оператор if превышает 4096 символов.
Ifdef statement too long
Сообщение об ошибке утилиты MAKE
(слишком длинный оператор ifdef)
Оператор ifdef превышает 4096 символов.
Ifndef statement too long
Сообщение об ошибке утилиты MAKE
(слишком длинный оператор ifndef)
Оператор ifndef превышает 4096 символов.
Ignored модуль, path is too long
Предупреждение утилиты TLIB
(модуль игнорируется, слишком длинный маршрут)
Характерным для Borland C++ и для других реализаций языка
является учет регистра букв в идентификаторах. Последние могут
содержать буквы от A до Z и от a до z, символ подчеркивания (_) и
цифры от 0 до 9 и должны начинаться с буквы.
Константы
Константами называются лексемы, представляющие собой фиксированные числовые или символьные значения. Borland C++ поддерживает четыре класса констант: константы с плавающей точкой, целочисленные константы, константы перечислимого типа и символьные константы (включая строковые).
Целочисленные константы представлены десятичным, восьмиричным и шестнадцатиричным форматом.
Символьные константы записываются одним или более символами,
заключенными в одинарные кавычки, например 'F', '=', '\n'.
Наследование может использоваться множество раз при порождении
объектов. Порожденные классы могут наследовать готовые функции элементы своих классов-предков, набирая при каждом порождении все больше
и больше функций элементов.
Окно
^
Наследование Панель Порождение
классов
v
Меню
Вы можете также порождать несколько классов из базового класса:
^ Меню
Насле- Порождение
дование > < классов
v
Вертикальное Горизонтальное
Вертикальное и Горизонтальное меню имеют одного предка - Меню.
Общее свойство, унаследованное от Меню - это список элементов, расположение. Порождение нескольких классов из одного корня позволяет
использовать текст программ для многих классов.
Используя наследование, можно наращивать иерархию классов, создавая как-бы древовидные формы. Еще более сложные иерархии образуются
через множественное наследование.
Иерархия классов постоянных потоков представляется следующей
схемой:
pstream
^ ^ ^
TStreamable
^ ^
ipstream opstream fpbase
^ ^ ^ ^
ofpstream
ifstream
Двойная стрелка указывает, что TStreamableBase - это дружественный класс.
Характеристики каждого класса закодированы в имени контейнера. Например, TDequeueAsDoubleList - это прямой контейнер, использующий схему управления памятью и реализующий двусвязанный
список.
| T | Префикс библиотечного класса Borland. |
| M | Контейнер управления памятью, предусматриваемый
пользователем. |
| I | Косвенный контейнер. |
| C | Счетный контейнер. |
| S | Отсортированный контейнер. |
Библиотеки BIDS не содержат всех возможных комбинаций
ADT/FDS. Предусмотренные комбинации указаны в следующей таблице:
ADT Sorted Dictiona-
FDS Stack Queue Dequeue Bag Set array Array ry
Вектор * * * * * * *
Список *
Двойной * *
список
Таблица *
хеширования
Двоичное
дерево
Для построения собственных реализаций ADT/FDS вы можете использовать шаблоны классов.
Чтобы импортировать класс из одного проекта AppsExpert в
другой, сделайте следующее:
Переместите или скопируйте исходный файл и файл заголовка,
который определяет класс, в исходный каталог и каталог заголовка проекта. Все исходные файлы проекта должны находиться в каталоге исходных файлов проекта (.CPP) или заголовков (.H). Эти каталоги создаются при генерации объекта
AppsExpert.
Добавьте в проекте IDE в качестве зависимого узла под
целью AppsExpert исходный файла класса (используйте команду Add node оперативного меню).
В окне проекта выберите цель AppsExpert, щелкните правой
кнопкой "мыши", затем выберите Special Rescan.
Информация о пользовательской динамически распределяемой области памяти USER и динамической памяти GDI показывается, какой
процесс динамической памяти USER и GDI был доступен во время исключительной ситуации.
Утилита DFA записывает файл только в том случае, если в кадре стека для файла присутствует информация отладчика Turbo Debugger. Выходной файл DFA (DFA.OUT) содержит трассировку стека, аналогичную файлу регистрации WinSpector. Кроме того, там находится следующее:
имена функции;
номера строк;
локальные и глобальные переменные;
сегменты данных и их значения (включая сегмент стека).
Во время сеанса работы в Windows записывается только один
файл WINSPCTR.BIN, поэтому построцессорная обработка файла выполняется с подсказкой. При этом вы можете удалить или переименовать
файлы DFA.OUT и WINSPCTR.LOG, что позволит отследить за один сеанс более одной исключительной ситуации.
После настройки TDW для удаленной отладки загрузите программу с помощью диалогового окна Load a New Program to Debug. TDW
выводит уведомляющее сообщение. После установления связи выводится обычный экран отладчика, и команды его работают так же. Однако
вывод программы на экран и ввод с клавиатуры происходит на удаленной системе.
По умолчанию TApplication::InitMainWindow создает окно-рамку
с тем же именем, что и объект приложения. Это оно не особенно полезно, так как не может воспринимать и обрабатывать ввод от пользователя. Вы должны переопределить InitMainWindow и создать новый объект окна, обрабатывающий ввод от пользователя. Обычно InitMainWindow создает TFrameWindow или производный от него объект и
вызывает функцию SetMainWindow, которая воспринимает один параметр (TFrameWindows*) и возвращает указатель на старое основное окно (в случае нового приложения возвращается 0).
С помощью элемента данных nCmdShow, соответствующего параметру с таким же именем функции WinMain, вы можете изменить характер вывода на экран основного окна приложения. Эту переменную можно установить, как только начинает выполнение функция Run, или
пока вы не вызовите TApplication::InitInstance. По существу это
означает, что вы можете установить значение nCmdShow либо в InitApplication, либо в функции InitMainWindow.
Для изменения основного окна при выполнении приложения вы
можете использовать функцию SetMainWindow, которая имеет один параметр, TFrameWindow*, и возвращает указатель на старое основное окно (или 0). Этот указатель можно использовать для сохранения старого основного окна (и его последующего восстановления), либо
для удаления объекта окна.
Для инициализации приложения ObjectWindows требуется построить объект приложения и инициализировать приложение, каждый новый
экземпляр и основное окно.
Для запуска приложения объект TApplication вызывает свои
функции-элементы InitApplication, InitInstance и InitMainWindows.
Вы можете переопределить любые из этих функций и задать собственную инициализацию. Для получения полезного приложения можно также
переопределить InitMainWindow. Для переопределения функции TApplication нужно построить собственный производный от TApplication
класс.
Конструктор класса приложения должен вызывать конструктор
TApplication. Библиотека ObjectWindows обеспечивает собственные
средства для обработки ошибок и исключительных ситуаций (в функции WinMain). Любую инициализацию можно выполнять в функции OwlMain, которая вызывается заданной по умолчанию функцией WinMain.
Для построения объекта приложения создайте в функции OwlMain экземпляр класса приложения.
Хотя вы можете вызывать собственную функцию WinMain, поместив ее в исходный файл, делать этого не нужно. Все что требуется,
можно сделать в вызываемой ей функции OwlMain или в функциях-элементах инициализации TApplication.
Если вы решили создать свою собственную функцию WinMain,
TApplication поддерживает во втором своем конструкторе передачу
обычных параметров функции WinMain.
Пользователи одновременно могут выполнять несколько копий
приложения. С точки зрения 16-разрядных приложений инициализация
первого экземпляра выполняется только когда не работает вторая
копия приложения. Инициализация экземпляра происходит каждый раз,
когда пользователь запускает приложение. Если пользователь запускает и закрывает приложение, запускает его снова и т.д., то каждый экземпляр будет первым экземпляром, так как они работают не одновременно.
В случае 32-разрядных приложений каждое приложение работает
в своем собственном адресном пространстве без разделяемых данных,
поэтому каждый экземпляр выглядит как первый экземпляр. Таким образом, при инициализации 32-разрядного приложения оно выполняет и
инициализацию первого экземпляра, и инициализацию каждого экземпляра.
Если текущий экземпляр является первым экземпляром (на что
указывает hPrevInstance = 0), то вызывается InitApplication. В
производном классе приложения вы можете переопределить InitApplication (по умолчанию InitApplication не несет никакой функциональной нагрузки).
Пользователи могут одновременно выполнять несколько копий
(экземпляров) приложения. Для выполнения любой необходимой инициализации можно переопределить TApplication::InitInstance. InitInstance вызывает InitMainWindow, а затем создает и выводит на экран основное окно. Если вы переопределяете InitInstance, убедитесь, что новая функция InitInstance вызывает TAppliation::InitInstance.
Понятие инкапсуляция означает, что функции элементы и структуры
данных, определяющие некоторые свойства данного класса, рассматриваются в качестве единого целого. Это подразумевает "защиту" данных в
пределах класса таким образом, что только элементы класса получают к
ним доступ. То есть, для того чтобы получить значение одного из элементов данных класса, нужно вызвать функцию элемент этого класса, ко-
торый возвращает необходимое значение. Для присвоения элементу значения, вызывается соответствующая функция элемент данного класса. Вообще, в объектном программировании считается хорошим тоном закрывать
все данные и функции элементы описываемого класса для доступа "извне".
Borland C++ предоставляет программистам три уровня доступа к
элементам объектов:
- public (общий),
- private (приватный),
- protected (защищенный).
Элементы, объявленные общими, будут доступны любому внешнему
элементу класса, любой функции элементу или выражению в программе,
когда объект является видимым.
Приватные элементы доступны только другим элементам своего же
класса. Они не доступны извне, за исключением специальных функций,
называемых "дружественными".
К защищенным элементам имеют доступ лишь некоторые из объектов.
Они доступны только элементам своего класса и любым его потомкам. Поэтому защищенные элементы занимают промежуточное положение между общими и приватными.
Примечание: приватные элементы недоступны потомкам своего класса. Поэтому и понадобились защищенные элементы.
Уровень доступности к элементам класса проиллюстрирован ниже:
Общие элементы
(public)
Защищенные
элементы (protect)
Приватные
элементы
(private)
Умелое использование уровней доступа повышает надежность программ и их способность к изменениям, ослабляя взаимозависимость между
объектами. Правильно описанными функциями элементами типа public можно изменять приватные элементы, не затрагивая программный код других
объектов. В реальной жизни мы подобным образом взаимодействуем с различными предметами: телевизором, будильником, радиоприемником, автомобилем - знание внутреннего устройства которых нам не обязательно.
Однако, нам важны внешние кнопки и ручки управления.
Это средство помогает вам находить записи в алфавитных списках. При наборе каждого символа полоса подсветки перемещается к
первому элементу, начинающемуся с выбранных вами букв. Позиция
курсора указывает, какую часть имени вы уже набрали. После подсветки вы можете нажать Alt+F10 или щелкнуть правой кнопкой "мыши". При этом выводится SpeedMenu, где вы можете выбрать команду,
соответствующую подсвеченному элементу.
Пакет Borland С++ содержит инструментальные средства Windows, инструментальные средства, работающие в режиме командной
строки, и библиотеки, позволяющие разрабатывать приложения для
DOS, Windows, Win32 и Windows NT.
Borland C++ содержит приложения DOS и Windows. Для работы
Borland С++ требуется:
DOS версии 4.01 или старше.
Windows 3.1 или старше, работающая в защищенном режиме
386.
Жесткий диск с 40 мегабайтами свободного пространства
(полная инсталляция требует 80 Мб).
Дисковод на 1.44 Мб или CD-ROM (для инсталляции).
Не менее 4 Мб расширенной памяти.
Совместимая с Windows "мышь".
Наличие 8 мегабайт оперативной памяти и сопроцессора 80х87
значительно улучшит производительность работы (при отсутствии
сопроцессора он эмулируется).
Инструкции перехода рассматриваются отдельно. Поскольку метка не может быть включена в саму команду, переходы выполняются к
меткам Си (см. выше раздел "Использование команд перехода и меток"). В следующей таблице перечислены допустимые инструкции перехода:
Инструкции перехода
ja jge jnc jns loop
jae jl jne jnz loope
jb jle jng jo loopne
jbe jmp jnge jp loopnz
jc jna jnl jpe loopz
jcxz jnae jnle jpo
je jnb jno js
jg jnbe jnp jz
В пакет Borland С++ входят следующие инструментальные средства для работы с ресурсами:
Компиляторы ресурсов BRCC.EXE и BRCC32.EXE. Они компилируют файлы сценариев ресурсов (.RC) и создают двоичный файл
.RES.
Компоновщики ресурсов RLINK.EXE и RLINK32.EXE используются
для компоновки ресурса в файл .RES, .EXE или создают выполняемый файл Windows (через TLINK).
Borland BRC.EXE и BRC32.EXE - это оболочки, позволяющие
запускать BRCC и RLINK за один шаг.
Большинство программ Windows легко использовать, так как они
обеспечивают стандартный интерфейс с пользователем. Например,
большинство программ Windows, позволяющие вам реализовать команды
программы и изменять курсоры, что позволяет указателю "мыши"
представлять большой набор инструментальных средств, таких как
стрелки или кисти.
Меню и курсоры представляют два примера ресурсов программ
Windows. Ресурсы - это данные, записываемые в выполняемый файл
программы (.EXE) отдельно от обычных ее данных. Ресурсы определяются и задаются вне кода программы, а затем добавляются к скомпилированному коду программы для создания выполняемого файла программы.
Ресурсы определяются как внешние для вашего программного кода данные, а затем они подключаются к выполняемому файлу в процессе компоновки. Приложение вызывает ресурсы в память только при
необходимости, что минимизирует использование памяти.
Чаще всего создавать и использовать вы будете следующие
ресурсы:
меню;
диалоговые блоки;
тограммы;
затели;
соры;
елераторы клавиатуры (оперативные клавиши);
овые массивы;
шрифты;
символьные строки.
Файлы сценариев ресурсов - это текстовые файлы, которые описывают конкретный ресурс приложения. Создать ресурсы вы можете с
помощью редактора ресурсов или компилятора ресурсов. В большинстве случаев проще всего использовать редактор ресурсов и визуально создать ресурсы. Однако иногда удобно использовать для компиляции файлов манускрипта, которые встречаются в книгах или журналах, компилятор ресурсов.
Независимо от того, какой подход вы используете, с помощью
RC или BRCC обычно создается файл ресурса (.RES) для каждой прикладной программы. Данный файл ресурсов содержит двоичную информацию для всех меню, диалогов, растровых образов и других ресурсов, используемых в прикладной программе.
Двоичный файл ресурсов, добавляемый к вашей прикладной программе (.EXE) с помощью компилятора ресурсов, описывается в данной
главе ниже. Вы должны также написать код, который загружает ресурсы в память. Каждый ресурс требуется загружать в память отдельно. Это дает вам гибкость, поскольку ваша программа будет использовать память только для тех ресурсов, которые действительно
нужны.
Borland С++ содержит несколько инструментальных средств режима командной строки, позволяющие выполнять те же задачи, что и
IDE. Это компилятор, компоновщик, компилятор ресурсов, библиотекарь, компоновщик проектов (MAKE) и другие средства. Некоторые из
них описаны в файлах оперативного справочника. Эти средства могут
потребоваться вам, если вы работаете с редактором DOS, например,
Brief. Перечислим эти средства:
| BCC.EXE BCC32.EXE | 16-разрядный и 32-разрядный компилятор. |
| TLINK.EXE TLINK32.EXE | Компоновщики, формирующие из файлов .OBJ и
.LIB файлы .EXE и .DLL. |
| IMPLIB.EXE TLIB.EXE | Помогают работать с библиотеками. |
| HC31.EXE | Компилирует файлы для оперативного справочника Help и создает файлы .HLP, используемые большинством приложений Windows. |
| BRCC.EXE
BRCC32.EXE BRC.EXE BRC32.EXE RLINK.EXE | Компиляторы ресурсов. |
| MAKE.EXE MAKER.EXE | Помогают обслуживать проекты и компонуют
только те файлы, которые были изменены после последней генерации программы. |
Среда Turbo Debugger включает в себя набор меню, диалоговых
окон и специальных окон отладчика.
Объекты, представляющие окна, блоки диалога и управляющие
элементы называются объектами интерфейса пользователя, или просто
интерфейсными объектами. В этом разделе обсуждаются общие свойства и требования интерфейсных объектов и их связь с реальными окнами, блоками диалога и управляющими элементами, появляющимися на
экране. Здесь также объясняется взаимосвязь между различными интерфейсными объектами прикладной программы, и описывается механизм ответа на сообщения Windows.
Заметим, что интерфейсный объект фактически находится внутри
объекта приложения. Интерфейсный объект - это класс ObjectWindows, который создается и сохраняется в стеке или динамически
распределяемой области приложения, в то время как интерфейсный
элемент является частью окна.
Следующие подпрограммы реализуют обращения к средствам DOS,
BIOS и специфическым средствам данного компьютера.
| absread | (dos.h) | _dos_freemem | (dos.h) |
| abswrite | (dos.h) | freemem | (dos.h) |
| bioscom | (bios.h) | _harderr | (dos.h) |
| _bios_disk | (bios.h) | harderr | (dos.h) |
| biosdisk | (bios.h) | _hardresume | (dos.h) |
| _bios_keybrd | (bios.h) | hardresume | (dos.h) |
| bioskey | (bios.h) | _hardretn | (dos.h) |
| biosprint | (dos.h) | hardretn | (dos.h) |
| _bios_printer | (dos.h) | keep | (dos.h) |
| _bios_serialcom | (dos.h) | randbrd | (dos.h) |
| _dos_keep | (dos.h) | randbwr | (dos.h) |
После наступления события VBX и вызова функции обработки события функции нужно иметь дело со структурой VBXEVENT в качестве
параметра. В этой структуре задается описатель посылающего событие управляющего элемента, описатель управляющего окна, идентификатор управляющего элемента VBX, индекс события, имя события,
число параметров события и указатель на массив, содержащий указатели на значения параметров для данного события.
Чтобы понять эту структуру, нужно понимать, как работает управляющий элемент VBX. Первые 3 элемента достаточно просты и позволяют вам идентифицировать передающий событие управляющий элемент. Следующие 2 элемента также достаточно просты: каждое событие, которое может посылать управляющий элемент VBX, представляется здесь индексом события и его именем.
Следующие 2 элемента сохраняют события содержат параметры
события. Эти параметры более сложны. Информацию по ним вы можете
найти в руководстве по библиотеке управляющих элементов VBX.
Администратор документа является экземпляром класса, производного от TDocManager или TDocManager, и выполняет ряд задач:
Поддерживает список текущих документов и зарегистрированных шаблонов.
Обрабатывает события стандартного меню File.
Обеспечивает интерфейс для выбора файла.
Для поддержки модели Doc/View администратор документа должен
подключаться к приложению. Это делается путем создания экземпляра
TDocManager и превращения его в администратор документа приложения. К общедоступным данным и функциям администратора документа
можно обращаться с помощью функции GetDocManager, которая не имеет параметров и возвращает TDocManager&. Для создания документов
и отображаемых элементов администратор документа предусматривает
следующие функции:
CreateAnyDoc представляет все видимые шаблоны, в то время
как функция-элемент TDocTemplate CreateDoc представляет
только свой собственный шаблон.
CreateAnyView отфильтровывает список шаблонов для тех
отображаемых элементов, которые поддерживают текущий документ и представляют список имен файлов, а функция-элемент
TDocTemplate CreateView непосредственно строит отображаемый документ, заданный классом шаблона документа.
Для поддержки других средств (например, OLE 2.0) можно использовать специализированный администратор документа.
Процесс создания приложений с помощью AppExpert включает в себя следующие этапы:
Использование AppExpert для определения пользовательского интерфейса, средств приложения и генерации кода.
Использование ClassExpert для добавления классов и обработчиков событий, реализации виртуальных функций и перемещению по существующему программному коду. ClassExpert позволяет также связывать с классами или обработчиками объекты Resource Workshop. ClassExpert окажет вам существенную помощь в обработке событий, реализации виртуальных функций и создании экземпляров переменных.
Использование Resource Workshop для редактирования или добавления ресурсов.
Использование администратора проекта для построения выполняемой программы.
Для каждого приложения AppExpert создает следующие файлы:
| .IDE | Файл проекта. |
| .CPP | Основной исходный файл. |
| .H | Основной файл заголовка. |
| .RC | Файл сценария ресурса. |
| .RH | Файл заголовка ресурса. |
| .APX | Файл базы данных для AppExpert. |
| .RC | Файл сценария ресурса |
| .RTF | Исходные файлы справочника. |
| .HPJ | Файл проекта справочника. |
| .ICO | Файлы пиктограмм. |
| .BMP | Файлы битовых массивов. |
Borland C++ предлагает для каждой из шести моделей памяти
собственную версию библиотеки стандартных подпрограмм. Компилятор
Borland C++ при этом проявляет достаточно "интеллекта", чтобы при
последующей компоновке брать нужные библиотеки и в нужной последовательности, в зависимости от выбранной вами модели памяти. Однако, при непосредственном использовании компоновщика Borland C++
TLINK (как автономного компоновщика) вы должны явно указывать используемые библиотеки.
Данный раздел описывает несколько инструментальных средств,
которые позволяют вам работать с библиотечными файлами. Вы можете
использовать эти инструментальные средства в IDE или в командной
строке.
Утилита IMPLIB создает библиотеки импорта, а IMPDEF - файлы определения модуля (.DEF). Библиотеки импорта и файлы
определения модулей задают для компоновщика информацию об
импортируемых из библиотек DLL функциях.
Утилита TLIB управляет библиотеками отдельных файлов .OBJ.
Библиотека - это удобный инструмент для работы с набором
объектных модулей.
TApplication имеет функции, необходимые для загрузки библиотеки специализированных управляющих элементов Borland (BWCC.DLL
для 16-разрядных приложений и BWCC32.DLL для 32-разрядных) и библиотеки трехмерных управляющих элементов Microsoft (CTL3D.DLL).
Эти DLL широко используются для обеспечения стандартного вида многих приложений.
BWCC можно открыть с помощью функции TApplication::EnableBWCC, которая воспринимает единственный параметр. Когда вы передаете ей True, функция загружает еще не загруженную DLL. При
передаче False DLL выгружается.
После загрузки DLL вы можете использовать обычные функциональные возможности BWCC. EnableBWCC автоматически открывает корректную библиотеку (для 16- или 32-разрядных приложений).
Функция TApplication::EnableCtrl3d позволяет вам загружать и
выгружать библиотеку CTL3D фирмы Microsoft. Определить, загружена
ли эта библиотека, можно с помощью функции TApplication::Ctl2Enabled. Параметров эта функция не имеет, а возвращаемое значение True указывает на загрузку библиотеки.
Определить, загружена ли библиотека CTL3D, можно с помощью
TApplication::Ctl3dEnabled, которая в этом случае возвращает
True. Чтобы использовать функцию EnableCtl3dAutosubclass воспринимает единственный параметр. Если передаете ей True, функция разрешает выделение подклассов (в этом случае все отличные от ObjectWindows диалоги будут иметь трехмерный вид), а если False запрещает.
Вместо создания производного класса вы можете использовать
структуру, представляющую состояния управляющих элементов. Такая
структура называется буфером передачи, так как состояния управляющего элемента передается от управляющих элементов в буфер и в
управляющие элементы из буфера.
Механизм передачи требует для представления управляющих элементов, которым вы хотите передавать данные, использования объектов ObjectWindows. Для использования механизма передачи вам необходимо следующее:
Определите буфер передачи с переменной экземпляра для каждого управляющего элемента, с которым вы хотите обмениваться данными.
Определите соответствующее окно или диалоговый блок.
Передайте данные.
ClassExpert позволяет вам создавать новые классы, редактировать и обновлять реализацию классов, а также перемещаться по
классам в исходном коде приложений AppExpert. Чтобы связать классы с ресурсами, вы можете использовать ClassExpert с Resource
Workshop.
Чтобы использовать диалоговый блок в качестве основного окна, лучше создать окно-рамку с диалоговым блоком в качестве клиентного окна. Для этого создайте производный от Tapplication класс. Кроме конструктора, единственное, что для этого требуется,
это функция InitMeinWindow, в которой строится объект окна-рамки.
Конструктор TFrameWindow включает автоматическое создание объекта
диалогового блока, который вы передаете в качестве клиента.
Требуется также обеспечить, чтобы объект диалогового блока
имел определенные атрибуты:
Уничтожение диалогового объекта не уничтожает рамки. Ее
нужно уничтожать явным образом.
Добавлять ресурсы динамически непосредственно к диалогу
здесь нельзя, так как это не основное окно. Ресурсы нужно
добавить в окно-рамку.
Вы не можете задать заголовок диалогового окна в самом ресурсе. Его нужно задавать через окно-рамку.
Стиль диалогового окна нужно задать как WS_VISIBLE (видимое), WS_CHILD (диалоговое окно), и без кнопок максимизации/минимизации, системных меню или любых других стандартных атрибутов окна-рамки.
Приложению Windows часто требуется выводить подсказку для
ввода пользователем имен файлов, цветов или шрифтов. ObjectWindows предусматривает классы, что облегчает использование диалоговых блоков, включая общие диалоговые окна Windows. Ниже перечислены различные типы диалоговых блоков и класс ObjectWindows, который их инкапсулирует:
| Цвет | TChooseColorDialog |
| Шрифт | TChooseFontDialog |
| Открытие файла | TFileOpenDialog |
| Сохранение файла | TFileSaveDialog |
| Поиск строки | TFindDialog |
| Ввод от пользователя | TInputDialog |
| Диалог прерывания принтера | TPrinterAbortDialog |
| Управление принтером | TPrintDialog |
| Замена строки | TReplaceDialog |
Ниже перечислены типичные формы командной строки, позволяющие использовать DLL-версии библиотек исполняющей системы Borland
и описанные ниже библиотеки классов.
Для 16-битовой компиляции и компоновки с использованием
DLL-версии библиотеки исполняющей системы дайте команду:
bcc -c -D_RTLDLL -ml source.cpp
tlink -C -Twe c0w1 source, source, , import crtldll
Обратите внимание на использование макрокоманды _RTLDLL и
переключателя командной строки -ml. Для 32-битовой версии используются команды:
bcc -c -D_RTLDLL source.cpp
tlink32 -Tpe -ap c0x32 source, source, , import32 cw32i
Для 16-битовой компиляции и компоновки с использованием
DLL-версии библиотеки класса дайте команды:
bcc -c -D_BIDSDLL -ml source.cpp
tlink -C -Twe c0w1 source, source, , import bidsi crtldll
Для 32-битовой компиляции и компоновки с использованием
DLL-версии библиотеки класса дайте команды:
bcc32 -c -D_BIDSDLL -ml source.cpp
tlink32 -Tpe -ap c0x32 source, source,
, import32 bidsfi cw32i
Borland C++, также как и большинство прочих компьютеров и
компиляторов, выполняет математические вычисления с числами в
двоичном представлении (то есть в системе счисления с основанием
2). Это иногда путает людей, привыкших исключительно к десятичной
математике (в системе счисления с основанием 10). Многие числа с
точным представлением в десятичной системе счисления, такие как
0.01, в двоичной системе счисления могут иметь лишь приближенные
представления.
В большинстве прикладных программ двоичные числа предпочтительны, однако в некоторых ситуациях ошибка округления в преобразованиях между системами счисления с основаниями 2 и 10 нежелательна. Наиболее характерным случаем здесь являются финансовые
или учетные задачи, где предполагается сложение центов. Рассмотрим программу, складывающую до 100 центов и вычитающую доллар:
#include <stdio.h>
int i;
float x =0.0;
for (i = 0; i < 100; ++i)
x += 0.01;
x -= 1.0;
print("100*.01 - 1 = %g\1",x);
Правильным ответом является 0.0, однако ответ, полученный
данной программой, будет малой величиной, близкой к 0.0. При вычислении ошибка округления, возникающая во время преобразования
0.01 в двоичное число, накапливается. Изменение типа x на double
или long double только уменьшает ошибку вычисления, но не устраняет ее вообще.
Для решения этой проблемы Borland C++ предлагает специфический для C++ тип bcd (двоично-десятичный), объявленный в файле
bcd.h. В случае двоично-десятичного представления число 0.01 будет иметь точное значение, а переменная x типа bcd даст точное
исчисление центов.
#include <bcd.h>
int i;
bcd x = 0.0;
for (i = 0; i < 100; ++i)
x += 0.01;
x -= 1.0;
cout << "100*0.1 - 1 = " << x << "\n";
При этом необходимо учитывать следующие особенности типа
bcd:
bcd не уничтожает ошибку округления вообще. Вычисление типа 1.0/3.0 все равно будет иметь ошибку округления.
Обычные математические функции, такие как sqrt и log, для
аргументов с типом bcd переопределяются.
Числа типа bcd имеют точность представления около 17 разрядов и диапазон принимаемых значений от 1x10^-125 до 1x10^125.
При работе с большим числом операций или при многократном
повторении определенного числа операций удобно пользоваться файлами подсказки. Файл подсказки представляет собой текстовый файл
в обычном формате ASCII (который может быть создан с помощью редактора системы Borland C++), содержащий все команды утилиты TLIB
или какую-то их часть. С помощью файлов подсказки вы можете создавать команды утилиты TLIB, размер которых превышает размер командной строки DOS (128 символов).
Для использования файла подсказки "имя_маршрута", в любой
позиции командной строки утилиты TLIB нужно задать @"имя_маршрута".
Файл подсказки может состоять из нескольких строк текста;
чтобы показать, что за данной строкой следует еще одна, в
конце текущей строки необходимо набить символ "логического
И" (&).
В файл подсказки не нужно заносить всю команду TLIB; этот
файл может содержать часть командной строки утилиты TLIB, а
остальная часть может задаваться в командной строке.
В одной командной строке утилиты TLIB можно использовать
несколько файлов подсказки.
Формирующий файл содержит описания и отношения, необходимые
программе MAKE для поддержания самых последних версий ваших программ. Вы можете создавать столько формирующих файлов, сколько вам
требуется и присваивать им произвольные имена; MAKEFILE представляет собой лишь имя, используемое по умолчанию, на которое ориентируется утилита MAKE, если при ее запуске имя формирующего файла
не задано.
Формирующий файл можно создать с помощью любого текстового
редактора, который поддерживает формат ASCII, например, встроенного редактора интегрированной среды, редакторов Sрrint,
MicroStar или SideKick. Все правила, описания и директивы завершаются концом строки. Если строка является слишком длинной, то вы
можете продолжить ее на следующей строке, поместив на текущей
строке в качестве последнего символа обратную косую черту (\).
Для разделения соседних идентификаторов (например, при задании последовательностей) и для задания структурного отступа команд внутри правила следует пользоваться пробельными символами
(пробелами и знаками табуляции). Формирующий файл может содержать комментарии, явные и неявные правила, макрокоманды и директивы.
В операторах встроенного ассемблера вы можете ссылаться на
элементы структуры (используя формат "переменная.элемент_структуры"). При этом вы работаете с переменными и можете сохранять и
получать значения элементов структур. Однако, можно также ссылаться на элемент структуры непосредственно по имени (без имени
переменно). Такая ссылка имеет форму числовой константы. При этом
константы приравниваются смещению (в байтах) от начала структуры,
содержащей данный элемент. Рассмотрим фрагмент программы:
struct myStruct {
int a_a;
int a_b;
int a_c;
} myA;
myfumc()
{
...
asm {mov ax, WORD PTR myA.a_b
mov bx, WORD PTR myA.a_c
}
...
}
Этот фрагмент описывает структурный тип с именем myStruct с
тремя элементами a_a, a_b, a_c. Первый оператор встроенного ассемблера перемещает значение, содержащееся в myA.a_b, в регистр
AX. Второй перемещает значение по адресу [di]+offset(a_c) в регистр BX (он берет адрес, записанный в DI, и добавляет его к смещению a_c от начала myStruct). Оператор ассемблера даст следующий
код:
mov ax, DGROUP : myA+2
mov bx, [di+4]
Таким образом, если вы загружаете регистр (такой как DI) адресом структуры типа meStruct, то можете использовать имена элементов структуры для непосредственной ссылки на них. Имя элемента
структуры можно использовать в любой позиции, где вы операторе
языка ассемблера допускается числовая константа.
Элементу структуры должна предшествовать точка. Она указывает, что это имя элемента структуры, а не обычный идентификатор
Си. В выводе ассебмлера имена элементов структуры заменяются соответствующими числовым смещением элемента, а информация о типе
не сохраняется. Такие элементы структуры могут использоваться в
операторах ассебмлера в качестве констант этапа компиляции.
Однако есть одно ограничение: если две используемые во
встроенном ассебмлере структуры имеют элемент с одинаковыми именем, их нужно сделать различными. Укажите между точкой и именем
элемента тип структуры в скобках (как в случае приведения типа),
например:
asm mov bx.[di].(struct tm)tm_hour
Тип void был введен в системы программирования Си в Начале 80-х
годов. Он является стандартным согласно ANSI Си.
В предыдущем разделе мы рассмотрели два случая использования
ключевого слова void: первый - для обозначения пустого списка аргументов, второй - для указания типа функции, не возвращающей какое-либо значение. Рассмотрим еще два способа применения ключевого слова
void: в качестве преобразователя типов и как часть определения указателя.
В первом случае компилятор получает информацию о необходимости и
проигнорировать какое-либо выражение:
//Простейший случай использования ключевого слова void
Более интересным является второй случай, когда void* используется как родовой указатель, т.е. может указывать на объекты любого типа. Однако его значение не может быть присвоено какому-либо другому
указателю, так как компилятор не знает размер объекта на который ссылается void*. Рассмотрим несколько примеров:
void *gp; //родовой указатель
int *ip; // указатель на int
char *cp; // указатель на char
gp=ip; // корректное преобразование
ip=gp; // -"-
cp=ip // некорректное преобразование
*ip=15; // корректное присваивание
*ip=*gp; // некорректное присваивание
Одним из основных способов применения этого типа являются применения этого типа являются формальные параметры. Функция из стандартной библиотеки memcpy, например, определена в string.h как:
void*memcpy(voidf*s1, const void*s2, unsigned int n);
Она копирует n символов из объекта, на который ссылается s2 в
объект, на который указывает s1. Таким образом она работает с объектами любого типа.
Компиляторы BCC.EXE (компилирует 16-разрядные приложения) и
BCC32.EXE (компилирует 32-разрядные приложения) работают одинако-
во, но используют по умолчанию разные параметры. BCC можно ис-
пользовать для передачи файлов TLINK или TASM. Общий синтаксис
команды имеет вид:
BCC [параметр [параметр...]] имя_файла [имя_файла]
Чтобы увидеть список параметров, наберите просто BCC и нажмите Enter. Параметры в командной строке разделяются пробелами, и
перед ними указывается символ - или /. Параметры командной строки
переопределяют параметры, заданные в файле конфигурации.
По умолчанию BCC компилирует файлы без расширений и файла с
расширениями .CPP. Файлы с расширениями .C или с расширениями,
отличными от .CPP, .ASM, .OBJ или .LIB компилируются как файлы
Си.
Некоторые параметры BCC и BCC32 задаются по умолчанию. Чтобы
отключить эти параметры, наберите BCC -параметр-. По умолчанию
BCC пытается выполнить компоновку с файлом определения модуля,
имя которого совпадает с именем исходного файла. Можно использовать несколько файлов определения.
Каждый тип управляющего элемента в чем-то отличен от других.
Ниже рассказывается, как использовать объекты стандартных управляющих элементов ObjectWindows.
Использование контейнеров с шаблонами позволяет вам построить приложение на основе стека (например, используя в качестве
соответствующих структур вектора), что позволяет легко изменить
реализацию связанного списка. Часто для этого требуется только
изменить typedef. Например:
// создать стек целых чисел, загрузить его и вывести содер-
// жимое
#include <classlib\stacks.h>
#include <iostream.h>
// описание контейнерных типов
typedef TStackAsVector<int> IntStack;
int main()
{
IntStack intStack;
for ( int i = 0; i < 10; i++ )
intStack.Push( i );
for ( i = 0; i < 10; i++ )
cout << intStack.Pop() << " ";
cout << endl;
return(0);
}
Вывод будет следующим:
9 8 7 6 5 4 3 2 1 0
Таким образом реализуется стек значений int, а в качестве
соответствующей FDS используется вектор. Если стек нужно реализовать с помощью списка, вы можете заменить typedef:
typedef TStackAsList<int> IntStack;
Все остальное будет работать правильно. Однако, чтобы изменить это на косвенный контейнер, потребуется больше изменений:
// создать стек целочисленных указателей, загрузить стек и
// вывести содержимое
#include <classlib\stacks.h>
#include<iostream.h>
// изменить typedef как обычно
typedef TStackAsVector<int> IntStack;
int main()
{
IntStack intStack;
for ( int i = 0; i < 10; i++ )
intStack.Push( &i ); // воспринимает указатель
for ( i = 0; i < 10; i++ )
cout << *intStack.Pop() << " ";
cout << endl;
return(0);
}
Результат будет тот же.
При вызове макрокоманды в формирующем файле должен соблюдаться следующий формат:
$(имя_макрокоманды)
Круглые скобки должны использоваться во всех случаях вызова
макрокоманд, даже в том случае, если имя макрокоманда состоит из
единственной буквы (за исключением предопределенных макрокоманд).
Данная конструкция - $(имя_макрокоманды) - называется вызовом
макрокоманда.
Когда утилита MAKE обнаруживает вызов макрокоманды, она заменяет ее на текст, раскрывающий макрокоманду (текст макрорасширения). Если текст макрорасширения не определен, то MAKE заменяет
ее пустой (нулевой) строкой.
Использование объектов диалоговых окон во многом аналогично
использованию оконных объектов. Простыми диалоговыми окнами кратковременного вывода вы можете управлять в одной функции-элементе
родительского окна, которая может конструировать, выполнять и
уничтожать функцию-элемент.
Использование объектов диалоговых окон требует следующих шагов:
построения объекта;
выполнения диалогового блока;
закрытия диалогового блока;
уничтожения объекта.