В данном разделе обсуждаются конструкции (введенные в
Windows 3.1), обеспечивающие переносимость кода Windows. Существующий 16-разрядный код Windows можно переносить с минимальными
изменениями в Win32 и Windows NT. Большинство изменений предусматривают подстановку вместо старых новых макрокоманд и типов и
замену специфических 16-разрядных вызовов API аналогичными API
Win32. После внесения этих изменений ваш программный код сможет
компилироваться и выполняться в 16-разрядной и 32-разрядной среде
Windows.
Чтобы облегчить создание переносимого кода, предусмотрена
переменная среду этапа компиляции STRICT. Windows 3.1 поддерживает определение STRICT в windows.h. Например, если не определена
переменная STRICT, то передача HWND функции, требующей HDC, не
приведет к выводу компилятором предупреждающего сообщения. Если
вы определите STRICT, то получите ошибку компиляции.
Использование STRICT позволяет:
выполнять строгую проверку типов;
корректировать и согласовывать описания типа параметра и
возвращаемого значения;
создавать прототипы определений типов для функций обратного вызова (оконные, диалоговые и специальные процедуры);
согласовывать с ANSI описания структур COMM, DCB и
COMSTAT.
STRICT обладает обратной совместимостью с Windows 3.0, то
есть ее можно использовать для создания приложений, работающих в
Windows 3.0. Определение STRICT поможет вам находить и корректировать несовместимость типов при переносе программ в 32-разрядную среду и поможет обеспечить переносимость между 16- и 32-разрядной Windows.
Чтобы вы могли изменить свою программу в соответствии со
STRICT, предусмотрены новые типы, константы и макрокоманды
| CALLBACK | Используется вместо FAR PASCAL в подпрограммах обратного вызова (например, оконных и диалоговых процедурах). |
| LPARAM | Описывает все 32-разрядные полиморфические параметры. |
| LPCSTR | То же, что LPSTR, но используется для доступ-
ных только по чтению строковых указателей. |
| LRESULT | Описывает все 32-разрядные возвращаемые значения. |
| UINT | Переносимый беззнаковый целочисленный тип,
размер которого определяется целевой средой. (В Windows 3.1 представляет 16-битовое значение, а в Win32 - 32-битовое.) |
| WINAPI | Используется вместо FAR PASCAL для описаний API. Если вы пишете DLL с экспортируемыми точками входа API, то можете использовать ее для описаний API. |
| WPARAM | Описывает 16-битовые полиморфические параметры. |
| RELDOFFSET(тип, поле) | Вычисляет смещение поля в структуре. "Тип" - это тип структуры, а "поле" - это имя поля. |
| WAKELP(селект,смещ) | Воспринимая селектор и смещение, создает FAR VOID*. |
| WAKELPARAM(мин,макс) | Из двух 16-битовых значений создает LPARAM. |
| WAKELRESULT(мин,макс) | Из двух 16-битовых значений создает LRESULT. |
| OFFSETOF(указ) | Выделяет из дальнего указателя смещение и возвращает UINT. |
| SELECTOROF(указ) | Выделяет из дальнего указателя селектор и возвращает UINT. |
| HACCEL | Описатель таблицы акселератора. |
| HDRVR | Описатель драйвера (Windows 3.1). |
| HDWP | Описатель DeferWindowPost(). |
| HFILE | Описатель файла. |
| HGDIOBJ | Общий описатель объекта GDI. |
| HGLOBAL | Глобальный описатель. |
| HINSTANCE | Описатель экземпляра. |
| HLOCAL | Локальный описатель. |
| HMETAFILE | Описатель метафайла. |
| HMODULE | Описатель модуля. |
| HPSRC | Описатель ресурса. |
| HTASK | Описатель задачи. |
Декомпрессор, работающий в посимвольном режиме будет выглядеть
так:
int decompressor_next(decompressor* dc)
{
if (dc->rcnt && dc->rcnt-- > 0) /* Контроль декомпрессии */
return dc->c; /* Возврат повторного символа */
if (!dc->srclen || dc->srclen-- <= 0) /* Пропуск ... */
return -1;
dc->c = *(dc->p)++; /* Обработка следующего символа буфера */
if (dc->c == 0xff) {
dc->rcnt = (*(dc->p)++)-1; /* Сброс первого символа в записи */
dc->c = *(dc->p)++; /* Здесь повторить символ */
dc->srclen -= 2;
}
return dc->c;
}
Наследование - это способность брать существующий - базовый
класс и порождать из него новый класс - потомок, с наследованием всех
его атрибутов и поведения. Это пожалуй самая впечатляющая возможность
объектно-ориентированного программирования и, возможно, единственное
коренное отличие С++ от Си.
Рассмотрим отвлеченный пример из реальной жизни - классификационную схему живых организмов. По этой схеме растительные и живые
царства делятся на группы, так называемые типы. Каждый тип, в свою
очередь, делится на классы, отряды, семейства и далее. Группы более
низкого уровня наследуют характеристики групп более высоких уровней.
Так, из утверждения о том, что волк относится к семейству псовых, вытекает сразу несколько положений. Из него следует, что у волков хорошо развиты слух и обоняние, поскольку таковы характеристики псовых.
Так как псовые входят в отряд хищных, это утверждение говорит еще о
том, что волки питаются мясом. Поскольку хищные относятся к млекопитающим, это утверждение говорит и о том, что волки имеют волосяной
покров и регулируемую температуру тела. Наконец, так как млекопитающие являются позвоночными, мы узнаем и то, что у волков есть позвоночник.
Волк -> Псовые -> Хищники -> Млекопитающие -> Позвоночные
Подобные схемы наследования можно проследить в классификации
языков программирования, классификации типов компьютеров и других.
Рассмотрим существующие в объектно-ориентированных языках иерархии
порождаемых объектов.
Вы можете настроить конфигурацию IDE для автоматического вы-
полнения отдельных задач или обработки событий. Диалоговое окно
Options Enviroment позволяет вам настроить конфигурацию редактора, средства просмотра, отладчика, подсистемы управления проектами и других элементов IDE. Заданные параметры сохраняются в файле
BCCONFIG.BCW. Список параметров в окне можно сжимать и расширять
с помощью + и -.
Команда Options Enviroment позволяет также настроить вид
оперативной полосы окон Editor, Browser, Debugger, Project, Message, Desktop и ClassExpert. При выборе одного из этих окон выводится оперативная полоса SpeedBar с комплектом инструментальных
средств. Вы можете ее настроить. Чтобы включить в нее или удалить
командные кнопки, сделайте следующее:
Выберите в основном меню команду Options Enviroment.
Выберите слева тему SpeedBar. В правой части диалогового
окна выводятся общие параметры всех оперативных полос, с
помощью которых ее можно настроить.
Выберите под SpeedBar Customize. В параметрах справа выводится информация о полосах SpeedBar.
Выберите тип оперативной полосы, которую вы хотите изменить
Editor, Browser, Debugger, Project, Message, Desktop или
ClassExpert). В столбце Avaliable Buttons выводятся все
доступные (доступные) командные кнопки, а в столбце Active
Buttons - кнопки выбранной оперативной полосы.
Чтобы добавить командную кнопку, дважды щелкните на ней
"мышью" в столбце Avaliable Buttons, а чтобы удалить, выберите кнопку в Active Buttons и щелкните "мышью" на указывающей влево стрелке.
Для переупорядочения позиций командных кнопок в SpeedBar
используйте стрелки вверх и вниз. Выбранная в Active Buttons кнопка перемещается вверх или вниз по списку.
Кнопка Copy Layout позволяет сделать все оперативные полосы
идентичными.
WinSpector можно настроить таким образом, чтобы она лучше
соответствовала вашим потребностям. Это позволяет управлять выводом информации в файл WINSPCTRL.LOG.
Параметры WinSpector можно устанавливать в диалоговом окне
Preferences или с помощью ввода команд непосредственно в файл
WINSPCTR.INI.
Параметр Directory в диалоговом окне Preferences позволяет
вам решить, куда записывается файл регистрации. Если вы не задаете каталог, то по умолчанию используется каталог Windows.
Для задания каталога сделайте следующее:
Откройте диалоговое окно Preferences.
Введите в поле ввода Directory имя каталога.
Выберите командную кнопку OK.
либо добавьте запись LogDir=[каталог] в файл WINSPCTR.INI.
Параметр Viewer диалогового окна Preferences позволяет задать, какое программное средство нужно использовать для просмотра
файла регистрации. Если вы не задаете каталог, то по умолчанию
используется Windows Notepad.
Если исключительная ситуация возникает в процессе сеансе с
текущим окном Windows, чтобы увидеть файл регистрации, выберите
View Log (Просмотр файла регистрации) диалогового окна Latest UAE
или диалоговое окно Preferences. Команда View Log запускает выбранную программу просмотра и передает файл WINSPCTR.LOG в качестве аргумента командной строки.
Чтобы просмотреть предыдущий файл регистрации, выберите в
системном меню WinSpector команду View Log file.
Чтобы задать средство просмотра, сделайте следующее:
Откройте диалоговое окно Preferences.
Введите средство просмотра в текстовом диалоговом окне Viewer.
Выберите командную кнопку OK.
либо добавьте LogViewer=[имя_файла_программы_просмотра] к файлу
WINSPCTR.INI.
Параметры Append New Reports и Overwrite Previous Reports в
диалоговом окне Preferences позволяет вам либо добавить отчеты к
предыдущему файлу регистрации, либо затереть предыдущий файл регистрации при генерации нового отчета. По умолчанию задается затирание предыдущего файла.
Если вы выбираете перезапись предыдущего файла регистрации,
то при первом возникновении исключительной ситуации предыдущий
Вы можете конфигурировать параметры вывода Turbo Debugger и
программные установки с помощью файлов конфигурации и меню Option
отладчика. Параметры, установленные в файлах конфигурации, начинают действовать после загрузке Turbo Debugger. Чтобы изменить
параметры после загрузки, используйте команды в меню Options.
Одна из наибольших трудностей программирования в Windows
состоит в том, что можно запутаться в управляющих элементах.
Иногда вы посылаете окну сообщение, в другой раз вызываете функцию API. При работе с различными видами элементов внешне похожие
операции часто различаются. ObjectWindows значительно уменьшает
эти трудности, предусматривая объекты, инкапсулирующие интерфейсные элементы. Это избавляет вас от необходимости иметь дело непосредственно с Windows и обеспечивает более единообразный интерфейс для управления интерфейсными элементами.
Интерфейсные объекты предусматривают функции-элементы для
создания, инициализации, уничтожения и управления соответствующим
интерфейсным элементом. Многие детали программирования в Windows
берут на себя функции-элементы.
Интерфейсные объекты инкапсулируют также данные, необходимые
для взаимодействия с интерфейсным элементом. Связь между интерфейсным объектом и интерфейсными элементами аналогична связи между файлом на диске и потоком С++. Объект потока только представляет файл на диске: вы можете манипулировать этим файлом, манипулируя объектом потока.
Borland С++ при компиляции не генерирует на диске никаких
промежуточных структур данных (записывая на диск только файлы
.OBJ). Вместо этого для хранения промежуточных структур данных
между проходами используется оперативная память. Поэтому при недостаточном объеме оперативной памяти вам может выводиться сообщение о нехватке памяти. Чтобы решить эту проблему, уменьшите
размер функций или разбейте файл с крупными функциями на несколько частей.
| WM_NCACTIVATE | WM_NCMBUTTONDOWN |
| WM_NCCREATE | WM_NCMBUTTONUP |
| WM_NCCALCSIZE | WM_NCMOUSEMOVE |
| WM_NCDESTROY | WM_NCMMOUSEMOVE |
| WM_NCHITTEST | WM_NCPAINT |
| WM_NCLBUTTONDBLCLK | WM_NCRBUTTONDBLCLK |
| WM_NCLBUTTONDOWN | WM_NCRBUTTONDOWN |
| WM_NCMBUTTONDBLCLK | WM_NCRBUTTONUP |
Для одного целевого файла можно задать несколько явных правил. Множественные явные правила вы можете использовать для создания с помощью TLIB библиотечного модуля. Например, поскольку
файлы объектных модулей .OBJ могут строиться по-разному (некоторые с помощью компилятора BCC, а другие, например, с помощью
TASM).
Здесь используется тот же формат, что и для обычных явных
правил, но за целевым файлом указывается два двоеточия. Второе
двоеточие сообщает утилите MAKE, что для данного целевого файла
ожидаются дополнительные явные правила.
В следующем примере MYLIB.LIB состоит из четырех объектных
модулей, два из которых являются модулями С++. Первое явное правило компилирует модули С++ и обновляет библиотеку. Второе явное
правило ассемблирует файлы ASM и также обновляет библиотеку.
mylib.lib:: f1.cpp f2.cpp
bcc -c f1.cpp f2.cpp
tlib mylib -+f1.obj -+f2.obj
mylib.lib:: f3.asm f4.asm
tasm /mx f3.asm f4.asm
tlib mylib -+f3.obj -+f4.obj
Важно отметить, что программисты, создавая классы, создают, по
сути, абстрактную основу - шаблоны для создания объектов. Из шаблона,
когда нужно, создается объект, который и используется. Но, прежде чем
вы напишете хотя бы одну строку программы на С++, необходимо хорошо
продумать необходимые вам классы и уровни их использования.
Не существует "идеальной" иерархии классов для каждой конкретной
программы. По мере продвижения разработки может оказаться, что вам
потребуется ввести новые классы, которые коренным образом изменят всю
иерархию классов. Каждая иерархия классов представляет собой сплав
экспериментальных исследований и интуиции, основанной на практике.
Так, потребовались сотни лет для создания классификации животных, и
тем не менее, вокруг нее, до сих пор, ведутся горячие споры и дела-
ются попытки ее изменения.
Умелое использование наследования позволяет с небольшими усилиями модифицировать огромные по объему программы. К тому же необходимо
помнить, что постоянно растущее число поставщиков предоставляют пользователям объектно-ориентированные библиотеки, совместимые с Турбо и
Borland С++. Так что не следует "высасывать их из пальцев".
Поскольку каждая новая версия Borland C++ включает самую
подробную техническую информацию, трудно написать то, чего в ней
нет. Однако, многим программистам вместо чтения толстых толмутов,
для начального программирования необходима информация, изложенная
в кратком виде, доступная по цене и удобная для чтения дома и на
работе. С другой стороны, возникает потребность и в справочной
информации, которая была бы доступна в любой момент времени в виде книги. По замыслу, эта книга предназначена для программистов
уже владеющих профессионально хотя бы одним языком программирования. Первой ознакомительной главы им будет вполне достаточно для
понимания концепции языка С++, а последующие дадут более конкретизированное представление о версии языка Borland C++ 4.0.
В 1 главе книги "Азы C++" Вы бегло ознакомитесь с основными
возможностями языка С++.
Во 2 главе "Наставление пользователю по Borland С++ 4.0" вы
узнаете о порядке инсталяции и работе с интегрированными средствами компилятора Borland.
Глава 3 "Справочная информация по программированию" говорит сама за себя.
"Справочник по программированию для DOS" вы найдете в главе 4.
В главе 5 Вы вкратце ознакомитесь с отладчиком Borland C++
Turbo Debugger 4.0.
Глава 6 включает справочную информацию о функциях в таком
виде:
abort Экстренно завершает программу
DOS UNIX Win16 #include <stdlib.h>
OS/2 Win32 void abort(void);
ANSI C++ ANSI C
и т.д.
Глава 7 расскажет о Objects Windows 2.0.
Жуть сколько много информации, но оригинальная документация
содержит в 3 раза больше. Так что настраивайтесь посерьезней.
Надеюсь книга окажется полезной и нужной Вам, уважаемый Читатель!
М.Вахтеров
Содержание | Вперед
char buff[] = {'a',0xff,3,'b','c'};
main()
{
int c;
decompressor dc;
decompressor_init(&dc, buff, sizeof(buff));
while ((c = decompressor_next(&dc)) != -1) putchar(c);
}
Отметим, что главная программа не знает как работает сам декомпрессор. Она только передает ему аргументы. Декомпрессор, обрабатывая
один символ за раз, может перенаправить его по множеству путей. Так,
он мог бы был выведен непосредственно на экран, как мы это делаем
здесь, передан подпрограмме поиска строки или анализатору ... в соответствии с концепцией.
object module имя_файла is invalid
Сообщение об ошибке утилиты TLIB
(недопустимый объектный модуль)
Библиотекарь не может распознать запись заголовка объектного
модуля, добавляемого к библиотеке, и предполагает, что это недопустимый модуль.
Objects of type тип cannot be initialized with {}
Сообщение об ошибке этапа компиляции:
(объект указанного типа не должен инициализироваться с помощью {})
Обычные структуры Си могут инициализироваться набором значений, заключенных в фигурные скобки. Классы С++ могут инициализироваться с помощью конструкторов (если класс имеет конструкторы,
локальных элементов, функций или базовых классов, которые являются виртуальными.
Only <<KEEP or <<NOKEEP
Сообщение об ошибке утилиты MAKE
(только <<KEEP или <<NOKEEP)
При закрытии временного встроенного файла вы задали что-то
отличное от KEEP или NOKEEP.
Only member functions may be 'const' or 'volatile'
Сообщение об ошибке этапа компиляции
(иметь тип 'const' или 'volatile' могут только функции-элементы)
Как 'const' или 'volatile' описан какой-либо другой объект,
отличный от функции-элемента.
Only one of a set of overloaded functions can be "C"
Сообщение об ошибке этапа компиляции
(только один из наборов переопределенных функций может быть
описана как "C")
Функции С++ по умолчанию являются переопределяемыми, и компилятор присваивает каждой из них новое имя. Если вы хотите переопределить присваивание компилятором нового имени, объявив функцию "C", то можете сделать это только для одного из набора функций с тем же именем (в противном случае компоновщик обнаружит более одной глобальной функции с тем же именем).
Operand of delete must be no-const pointer
Сообщение об ошибке этапа компиляции
(операндом удаления должен быть указатель, отличный от константы)
С помощью операции delete не допускается использовать указатель-константу.
Operator [] missing ]
Сообщение об ошибке этапа компиляции
(в operator[] отсутствует ])
Все интерфейсные объекты ObjectWindows являются производными
от TWindow. Этот класс определяет базовое поведение всех окон,
диалоговых блоков и объектов управляющих элементов. TWindow поддерживает взаимосвязь между интерфейсными объектами и интерфейсными элементами, включая создание и уничтожение объектов и элементов. Он управляет всеми взаимодействиями "предок-потомок" между интерфейсными элементами, а также регистрирует новые оконные
классы Windows.
Эти элементы данных и функции используются для управления
контекстом устройства самого объекта. Они являются защищенными
(protected) и могут использоваться только в производных от TDC
классах.
| ShouldDelete | Указывает, должен ли объект удалять свой
описатель контекста устройства при вызове деструктора. |
| Handle | Содержит фактический описатель контекста
устройства. |
| OrgBrush, OrgPen, OrgFont, OrgPalette | Описатели исходных объектов при создании контекста устройства. В 32-разрядных приложениях присутствует также OrgTextBrush. |
| CheckValid | Генерирует исключительную ситуацию при
недопустимости контекста устройства. |
| Init | Устанавливает OrgBrush, OrgPen, OrgFont,
и OrgPalette при создании объекта. Если вы создаете производный от TDC класс без явного вызова конструктора TDC, то в своем конструкторе вам следует сначала вызвать конструктор TDC::Init. |
| GetHDC | Используя Handle возвращает HDC. |
| GetAttribute | Используя Handle возвращает HDC. Если
создаете объект с несколькими контекстами устройства, то следует переопределить эту функцию для обеспечения нужного возвращаемого значения. Эта функция использует недокументированную функцию API Windows FastWindowFrame или PatBlt. |
Объекты диалоговых блоков - это интерфейсные объекты, которые инкапсулируют поведение диалоговых окон. Инициализацию, создание и выполнение всех типов диалоговых блоков поддерживает класс TDialog. Вы можете создать специализированные диалоговые
блоки, производные от TDialog. ObjectWindows поддерживает также
классы, инкапсулирующие общие диалоговые блоки Windows. Windows
предусматривает общие диалоговые блоки, позволяющие пользователям
выбирать имена файлов, шрифты, цвета и т.д.
ObjectWindows 2.0 предусматривает новый способ манипуляции с
данными - модель Doc/View, которая состоит из трех частей:
Объектов документов, которые могут содержать несколько
различных типов данных и предусматривают методы доступа к
этим данным.
Объекты отображаемых элементов образуют интерфейс между
объектом документа и пользовательским интерфейсом. Они управляют характером вывода данных и тем, как пользователь
взаимодействует с данными.
Администратор документа, работающий в масштабе приложения,
поддерживает координаты объектов документов и соответствующих объектов отображаемых элементов.
Большинство прикладных программ Windows поддерживают меню в
составе своего главного окна. Меню обеспечивает пользователю разнообразные возможности выбора, такие как Save, Open и Help. Иногда в приложениях требуются сложные меню. Объекты меню ObjectWindows (TMenu, TSystemMenu, TMenuDescr и TPopupMenu) дают вам простой способ создания меню и манипулирования ими.
ObjectWindows 2.0 инкапсулирует приложения Windows и DLL-модули с помощью классов TApplication и TModule соответственно.
Объекты TModule инкапсулируют функции инициализации и закрытия DLL Windows. Объект TModule также содержит параметры hInstance и lpCmdLine, эквивалентные параметрам с тем же именем, передаваемых функции WinMain в приложениях, которые строятся без использования
ObjectWindows.
Объект TAplication инкапсулирует инициализацию, управление этапом выполнения и функции закрытия приложения Windows. Объект TApplication содержит также значения параметров hPrevInstance и nCmdShow, которые эквивалентны параметрам с тем же именем, передаваемых функции WinMain в приложениях, которые строятся без использования ObjectWindows. Поскольку TApplication основывается на TModule, этот объект обладает всеми его функциональными возможностями. Кроме того, объект TApplication содержит функции для
простой загрузки и использования библиотеки специализированных
управляющих элементов Borland (Borland Custom Controls Library) и
библиотеку трехмерных управляющих элементов Microsoft (Microsoft 3-D Controls Library).
Явной функции WinMain в приложения ObjectWindows 2.0 не требуется. Вместо нее используется функция OwlMain, которая позволяет вам указывать параметры int argc и char** argv и возвращать int, как и обычная программа Си и С++ с функцией main.
В данном разделе описывается, как использовать объекты TApplication. Если вы не работаете с DLL, самостоятельно создавать объект TModule вам не потребуется.
Чтобы использовать объект TApplication, вы должны включить
нужный файл заголовка, создать объект и найти объект. TApplication определяется в файле заголовка owl\applicat.h. Так как TApplication является производным от TModule, owl\applicat.h включает файл owl\module.h.
Создать объект TApplication можно с помощью одного из двух
конструкторов. Наиболее общим конструктором является конструктор,
воспринимающий строку имени приложения, задавать которую не обязательно. Вторая версия конструктора позволяет задать ряд параметров, соответствующих параметрам, передаваемым обычно функции WinMain.
В данной главе описываются классы ObjectWindows, которые
позволяют вам выполнить следующие задачи печати:
создание объекта принтера;
создание объекта распечатки;
печать содержимого окна;
печать документа;
выбор и настройка конфигурации принтера.
Эти задачи выполняют классы TPrinter и TPrintout.
ObjectWindows предусматривает несколько способов, которые вы
можете использовать для связи объектов проверки допустимости с
редактируемыми управляющими элементами. Объекты проверки допустимости облегчают проверку допустимости данных в существующих приложениях ObjectWindows или для изменения способа проверки данных
в поле. С помощью вызова функции-элемента CanClose объекта вы можете в любое время проверить содержимое любого редактируемого управляющего элемента.
Чтобы связать с управляющим элементом объект, нужно определить указатель на объект управляющего элемента в виде элемента
данных и построить объект управляющего элемента в конструкторе
объекта диалогового блока. Вы можете также определить собственный
класс управляющих элементов, производный от существующего класса
(это позволяет задать специальное поведение). В отличие от задания оконного объекта, это требует двух шагов - построение и создания. Связь интерфейсного объекта с интерфейсным элементом требует только одного шага, так как интерфейсный элемент уже существует (загружается из ресурса). Вы просто сообщаете конструктору,
какой управляющий элемент в ресурсе нужно использовать, указывая
для этого идентификатор ресурса.
Манипулировать управляющими элементами вы не сможете, пока
не будет выполнена функция SetupWindow диалогового блока, поскольку до этого момента связь управляющих элементов с соответствующими объектами отсутствует. После установления связи элемента данных HWindows для управляющих элементов становится допустимым.
Элементы пользовательского интерфейса, которые облегчают передачу ввода пользователя, называются объектами управляющих элементов или объектами управления. Это стандартные элементы интерфейса с пользователем со специализированным поведением. ObjectWindows предусматривает несколько специализированных управляющих
элементов, а также обеспечивает для них интерфейсные объекты, так
что вы можете использовать их в приложения. Интерфейсные объекты
для управляющих элементов называются объектами управляющих элементов.
В некоторых случаях вам может потребоваться переопределить
заданное по умолчание значение типа функции для модели памяти.
Например, вы используете модель памяти large, и в программе имеется рекурсивная функция:
double power(double x,int exp)
{
if (exp <= 0)
return(1);
else
return(x * power(x, exp-1));
}
Каждый раз, когда функция power вызывает сама себя, она
должна выполнить дальний вызов, причем используется дополнительное пространства стека и число тактовых циклов. Объявив power как
near, можно ускорить выполнение ее благодаря тому, что вызовы
этой функции будут ближними:
double __near power(double x,int exp)
Это гарантирует, что функция power может вызываться только
из того кодового сегмента, в котором она компилировалась, и что
все обращения к ней будут ближними.
Это означает, что при использовании большой модели памяти
(medium, large или huge) функцию power можно вызывать только из
того модуля, в котором она определена. Прочие модули имеют свои
собственные кодовые сегменты и не могут вызывать функции near из
других модулей. Более того, ближняя функция до первого к ней обращения должна быть либо определена, либо объявлена, иначе компилятор не знает о необходимости генерировать ближний вызов.
И наоборот, объявление функции как дальней означает генерацию дальнего возврата. В малых моделях кодовой памяти дальняя
функция должна быть объявлена или определена до первого к ней обращения, что обеспечит дальний вызов.
Вернемся к примеру функции power. Хорошо также объявить
power как static, поскольку предусматривается вызывать ее только
из текущего модуля. Если функция будет объявлена как static, то
имя ее не будет доступно ни одной функции вне данного модуля.
Borland С++ позволяет объявлять дальние (far) объекты. Например:
int far x = 5;
int far z;
extern int far y = 4;
static long j;
Компилятор Borland C++ создает для каждого дальнего объекта
отдельный сегмент. Параметры компилятора командной строки -zE,
-zF и -zH (которые могут также задаваться директивой #pragma option) влияют на имя, класс и группу дальнего сегмента, соответственно. Изменяя эти значения при помощи указания #pragma option, вы тем самым распространяете новые установки на все объявления дальних объектов. Таким образом, для создания в конкретном сегменте дальнего объекта, можно использовать следующую последовательность:
#pragma option -zEmysegment -zHmygroup -zFmyclass
int far x;
#pragma option -zE* =zH* -zF*
Тем самым x будет помещен в сегмент MYSEGMENT с классом
'MYCLASS' в группе 'MYGROUP', после чего все дальние объекты будут сброшены в значения, используемые по умолчанию. Отметим, что
при использовании этих параметров можно поместить несколько дальних объектов в один сегмент:
#pragma option -zEcombined -zFmyclass
int far x;
double far y;
#pragma option -zE* -zF*
И x, и y окажутся в сегменте COMBINED 'MYCLASS', без группы.
Только что были рассмотрены случаи, в которых может понадобиться объявить функцию с другой моделью памяти, нежели остальная
часть программы. Зачем то же самое может понадобиться для указателей? По тем же причинам, что и для функций: либо для улучшения
характеристик быстродействия (объявив __near там, где по умолчанию было бы __far), либо для ссылки за пределы сегмента по умолчанию (объявив __far или __huge там, где по умолчанию бывает
__near).
Разумеется, при объявлении функций или указателей с другим
типом, нежели используемый по умолчанию, потенциально появляется
возможность ошибок. Предположим, имеется следующий пример программы с моделью small:
void myputs(s)
char *s;
{
int i;
for (i = 0; s[i] != 0; i++) putc(s[i]);
}
main()
{
char near *mystr;
mystr = "Hello, world\n";
myputs(mystr);
}
Эта программа работает удовлетворительно, хотя объявление
mystr как __near избыточно, поскольку все указатели, как кода,
так и данных, будут ближними (near) по умолчанию.
Однако, что произойдет, если перекомпилировать эту программу
с моделью памяти compact (либо large или huge)? Указатель mystr в
функции main останется ближним (16-битовым). Однако, указатель s
в функции myputs теперь будет дальним (far), поскольку по умолчанию теперь используется far. Это означает, что попытка создания
дальнего указателя приведет к извлечению из стека двух слов, и
полученный таким образом адрес, безусловно, не будет являться адресом функции mystr.
Как избежать этой проблемы? Решение состоит в том, чтобы определить myputs в современном стиле Си:
void myputs(char *s)
{
/* тело myputs */
}
Теперь при компиляции вашей программы Borland C++ знает, что
myputs ожидает указатель на char. Поскольку компиляция выполняется с моделью large, то известно, что указатель должен быть __far.
Вследствие этого Borland C++ поместит в стек регистр сегмента
данных (DS) и 16-битовое значение mystr, образуя тем самым дальний указатель.
Если вы собираетесь явно объявлять указатели как far или near, не забывайте использовать прототипы тех функций, которые могут работать с этими указателями.
Как быть в обратном случае: когда аргументы myputs объявлены
как __far, а компиляция выполняется с моделью памяти small? И в
этом случае без прототипа функции у вас возникнут проблемы, поскольку функция main будет помещать в стек и смещение, и адрес
сегмента, тогда как myputs будет ожидать приема только одного
смещения. При наличии определений функций в прототипах main будет
помещать в стек только смещение.
Фактически, мы уже видели как это делается на примере класса
shape, однако, рассмотрим еще раз этот процесс:
class shape {
public:
double xo, yo;
shape(double x, double y); // Конструктор создания shape (фигуры)
virtual double area(void); // Функция вычисляющая поверхность
virtual draw(void); // Функция рисования shape
}; ^
Ключевое слово virtual
Виртуальные функции объявляются с использованием ключевого слова
virtual. Отметим, что virtual используется только в базовом классе, а
не в классах - потомках.
В этой области выводится в шестнадцатиричном виде содержимое
области памяти. В левой части каждой строки показан адрес (в виде
"сегмент:смещение" или 32-разрядного адреса). Порядок регистров в
области Dump имеет вид: DS, ES, SS, CS. Справа от адреса выводятся значения элементов данных в выбранном формате.
SpeedMenu области Dump содержит команды для перемещения по
области, модификации содержимого, перемещению по указателям, задания формата вывода и работы с блоками памяти.
| Goto | Выводит диалоговое окно Enter Address to Position To, где вы
можете ввести выражение, при вычислении которого получается адрес памяти, доступный программе. | |
| Search | Ищет строку символов или список байт, начиная с адреса, указанного курсором. | |
| Next | Ищет следующий экземпляр элемента, заданного в команде поиска. | |
| Change | Позволяет модифицировать байты по текущему месту расположения курсора. При выводе в формате ASCII или шестнадцатиричном виде запрашивается список байт, в противном случае - элемент текущего формата вывода. | |
| Follow | Открывает меню с командами, позволяющими проверить данные по
адресам указателей near и far. TD32 содержит команды для 32-разрядной адресации.
слово под курсором в области данных, как смещение в текущем сегменте кода (как это задается регистром CS). Область кода становится текущей областью и позиционируется на данный адрес. становится текущей и позиционируется на данный адрес.
Область данных устанавливается в соответствии со смещением, заданным словом в памяти по текущей позиции курсора.
и смещение). Область данных устанавливается в соответствии со смещением, заданным двойным словом в памяти по текущей позиции курсора.
слово под курсором, как адрес сегмента, и позиционирует область данных на начало сегмента. | |
| Previous | Восстанавливает адрес области данных в адрес, который был до
последней команды, явно изменившей значение текущего адреса. Использование клавиш стрелок и клавиш перемещения курсора не приводит к запоминанию позиции. Отладчик поддерживает стек из пяти последних адресов, поэтому вы можете вернуться назад после многократного (< 5) использования команд локального меню Follow, или команды Goto. | |
| Display As | Позволяет выбирать формат вывода в области данных. Вы можете
выбирать один из форматов данных, использующихся в языке Си, Pascal или ассемблер. Эти форматы можно выбрать из меню. Команда Byte устанавливает область данных в режим вывода шестнадцатиричных байтовых данных. Word устанавливает область данных в режим вывода шестнадцатиричных слов. Long задает режим вывода длинных шестнадцатиричных целых чисел. Comp устанавливает режим вывода 8-байтовых целых чисел. Выводится десятичное значение числа. Float устанавливает режим вывода 6-байтовых чисел с плавающей точкой. Выводится значение числа с плавающей точкой в научном представлении. Double выводит 8-байтовые числа с плавающей точкой. Выводится значение числа в научном представлении. Extended устанавливает режим вывода 10-байтовых чисел с плавающей точкой в научном представлении. | |
| Block | Позволяет работать с блоками памяти. Вы можете перемещать,
очищать, присваивать значения блокам памяти, а также записывать и считывать блоки памяти из файлов на диске. По данной команде на экран выводится всплывающее меню. Команда Clear этого меню устанавливает непрерывный блок в памяти в значение 0. Адрес блока и число байт, которые требуется очистить, запрашиваются в выводимой подсказке. Move копирует блок памяти из одного адреса в другой. Адреса исходного и целевого блока, а также число копируемых байт, будут запрашиваться в подсказке. Set присваивает непрерывному блоку в памяти конкретное байтовое значение. Адрес блока, число байт, которым требуется присвоить значение, а также само значение запрашиваются в подсказке. Read считывает все содержимое или часть файла в блок памяти. Вам выводится подсказка для ввода имени считываемого файла, затем адреса, куда требуется считать информацию, и числа считываемых байт. Write записывает блок памяти в файл. Выводится подсказка для ввода имени файла, куда требуется записать данные, затем блока памяти, который нужно записать, и число считываемых байт. |
В этой области выводятся все существующие окна (в виде иерархической схемы) с указанием их родства. Эта область позволяет
вам:
Определить, какие окна активны в оперативной области.
Просмотреть статус окон, включая скрытые окна.
Увидеть, какие окна получают сообщения.
Выбрать окна для трассировки сообщений.
В этой области выводится подробная информация о нити, подсвеченной в области списка нитей. Первая строка показывает статус
подсвеченной нити (приостановлена или выполняется) и ее приоритет. Операционная система устанавливает 5 различных приоритетов
(от -2 до 2). Вторая строка показывает текущую точку выполнения
нити, а третья (если она есть) - как получил управление отладчик.
В области флагов показано значение каждого флага ЦП. Список
различных флагов и то, как они выводятся в области флагов, показан в следующей таблице:
Буква в области Название флага
c Флаг переноса
z Флаг нуля
s Флаг знака
o Флаг переполнения
p Флаг четности
a Флаг дополнитель-
ного переноса
i Флаг разрешения
прерывания
d флаг направления
SpeedMenu этой области содержит содержит команду Toggle, переключающую значение подсвеченного флага между 0 и 1.
Здесь выводятся классы загруженного модуля и их иерархии.
Базовые классы размещаются по левому полю области. Классы, наследующие из нескольких базовых классов, отмечаются звездочками
(**), а все другие классы, являющиеся частью той же группы множественного наследования - одной.
Локальное меню этой области содержит две команды. Команда
Inspect (или клавиша Enter) открывает для подсвеченного класса
окно Class Inspector. При отладке программ С++ с множественным
наследованием здесь доступна также команда Parents, включающая и
выключающая вывод области порождающих классов окна Hierarchy.
Здесь перечисляются классы, найденные ClassExpert в текущем
приложении. Информация в областях событий и редактирования зависит от выбранных здесь классов. Чтобы перейти к конструктору
класса в исходном коде, вы можете дважды щелкнуть на классе
"мышью". При этом выводится область редактирования. Используя
оперативное меню, вы можете добавить классы, связать классы документов с классами отображаемых элементов, получить информацию о
классе, перейти к исходному коду класса или файла заголовка и запустить Resource Workshop.
Эта область выводит в алфавитном порядке список всех классов, используемых в загруженном модуле. Справа представлена детальная информация по подсвеченному здесь классу. Для быстрого
поиска класса используется средство инкрементального поиска. Если
вы начнете набирать здесь имя класса, отладчик подсвечивает имя,
начинающееся с набранных символов.
SpeedMenu этой области содержит две команды. Команда Inspect
(или клавиша Enter) открывает для текущего класса окно Class Inspector. Команда Tree активизирует область иерархии, подсвечивая
текущий класс.
В левой части области кода выводятся адреса дизассемблированных инструкций. Для 16-разрядного кода они имеют вид "сегмент:смещение", а для 32-разрядного это 32-разрядные адреса. Стрелка (>) справа от адреса памяти указывает текущий адрес программы (следующую выполняемую инструкцию). Справа выводится шестнадцатиричный машинный код с соответствующей дизассемблированной
инструкцией. Глобальные идентификаторы выводятся в виде имени,
статические - в виде имени модуля с символов # и именем идентификатора, а номера строк представлены как имя модуля, # и номер
строки. Клавиша F2 позволяет устанавливать/отменять точки останова.
Меню SpeedMenu области кода содержит команды, позволяющие
перемещаться по ней и ассемблировать вводимые инструкции. TDW
имеет дополнительную команду ввода-вывода, а TD32 - команды Threads и OS Exceptions.
| Goto | Вам выводит окно Enter Address to Position To для ввода нового адреса, на который вы хотите перейти. Вы можете ввести адрес, выходящий за пределы программы, что позволяет проверить базовую систему ввода-вывода (BIOS), внутренние области DOS и Windows. | |
| Origin | Позиционирует вас на текущий адрес программы. Используется
для перемещения. | |
| Follow | Позиционирует область кода по целевому адресу текущей подсвеченной инструкции. Используется в сочетании с инструкциями передачи управления (CALL, JMP, INT) и условного перехода (JZ, JNE, LOOP и др.). | |
| Caller | Позиционирует вас на инструкцию, вызвавшую текущее прерывание или подпрограмму. Если текущая подпрограмма прерывания занесла данные в стек, то Turbo Debugger может не иметь возможности
определить, откуда она вызвана. | |
| Previous | Восстанавливает позицию области кода в соответствии с адресом, который был текущим перед последней командой, явно изменившей его значение. Использование клавиш перемещения на команду не влияет. | |
| Search | Позволяет вам вводить инструкцию или список байт, которые вы
хотите найти. Будьте внимательны при поиске инструкций. Следует выполнять поиск только тех инструкций, которые не изменяют байт, в которые они ассемблируются, в зависимости от того, где в памяти они ассемблируются. Например, поиск следующих инструкций проблемы не представляет: PUSH DX POP [DI+4] ADD AX,100 |
| View Source | Для вывода исходного кода, соответствующего текущей дизассемблированной инструкции открывает окно Module. Если соответствующего исходного кода нет (например, вы находитесь в коде Windows, или отсутствует отладочная информация), вы просто остаетесь в области кода. | |
| Mixed | Позволяет выбрать один из трех способов вывода на экран дизассемблированных инструкций и исходного кода: | |
| No (Нет) | Исходный код не выводится, выводятся только дизассемблрованные инструкции. | |
| Yes (Да) | Перед первой дизассемблированной инструкцией, со ответствующей данной строке, выводится строка исходного кода. Область устанавливается в данный режим, если исходный модуль написан на языке высокого уровня. | |
| Both (Оба) | Для тех строк, которым соответствует исходный код, дизассемблированные строки заменяются строками исходного текста. В противном случае выводятся дизассемблированные инструкции. Используйте этот режим, когда вы отлаживаете модуль на ассемблере и хотите видеть строку исходного текста, а не соответствующую дизассемблированную инструкцию. Область устанавливается в данный режим вывода, если текущим модулем является исходный модуль ассемблера. | |
| Thread | Позволяет выбрать нить, выполнение которой вы хотите отладить. Открывает диалоговое окно Pick a Thread, из которого вы можете выбрать конкретную нить программы. | |
| OS Exceptions | Позволяет выбрать исключительные ситуации операционной системы, которые вы хотите обрабатывать. Подробнее об этом рассказывается ниже. | |
| New EIP | Изменяет текущий адрес программы, подсвеченный в области кода (в TDW команда называется New CS:IP). При возобновлении выполнения программы оно начинается по этому адресу. Эта команда полезна, когда нужно пропустить некоторые машинные инструкции, но использовать ее нужно аккуратно, так как она может вызвать нестабильность системы. | |
| Assemble | ||
| I/O | Эта команда TDW считывает или записывает значения в пространство адресов ввода-вывода ЦП и позволяет вам проверить содержимое регистров ввода-вывода и записать в них значения. При этом выводится меню, показанное ниже: | |
| In byte | Ввести байт из порта | |
| Out byte | Вывести байт в порт | |
| Read byte | Прочитать байт из порта | |
| Write byte | Записать байт в порт Учтите, что эти команды могут нарушить нормальную работу устройств. | |
В этой области перечисляются все активные нити программы,
идентифицируемые по номеру нити (назначаемому Windows NT) и имени. Turbo Debugger генерирует имя нити, когда ваша программа создает нить. Первая создаваемая нить называется Thread 1, затем Thread 2 и т.д. Это имя можно изменить.
Окно Thread содержит единое SpeedMenu, которое активизируется из всех областей и содержит перечисленные ниже команды.
| Options | Открывает диалоговое окно Thread Options, позволяющее задать
параметры отдельных нитей. Кнопка Freeze этого окна позволяет "замораживать" и "размораживать" индивидуальные нити. Включение этой кнопки означает, что нить выполняться не будет. Для выполнения программы необходима хотя бы одна активная нить. Кнопка Notify or Tremination позволяет задать, должен ли отладчик уведомлять вас о завершении текущей (подсвеченной) нити (он генерирует сообщение и активизирует окно Module и CPU с текущим адресом программы). Чтобы задать уведомление для всех нитей, используйте команду меню All Threads. Поле ввода Thread Name позволяет изменить имя текущей нити. | |
| Make Current | Команда Make Current позволяет сменить нить, обрабатываемую
отладчиком. Подсветите в области Threads List нить, которую вы хотите проверить, и нажмите Ctrl+M (или выберите Make Current). | |
| Inspect | Открывает окно Module или CPU, которое показывает для подсвеченной нити текущую точку выполнения. Этой команде эквивалентна
клавиша Enter. | |
| All Threads | Открывает меню, команды которого относятся ко всем нитям
программы. Это команды Thaw, Freeze, Enable Exit Notification и Disable Exit Notification. | |
| Step | Позволяет переключаться между All и Single. При выборе All
клавиши F7 и F8 приводят к выполнению всех нитей программы, а Single позволяет выполнять только одну нить. |
Это окно выводит наследование классов С++ и, в зависимости
от использования в программе множественного наследования, состоит
из трех областей.
Эта область выводится только для программ с множественным
наследованием и при ее разрешении. Для классов, полученных путем
множественного наследования, она выводит все производные классы.
SpeedMenu этой области содержит единственную команду Inspect. При
ее выборе (или нажатии Enter) для подсвеченного класса выводится
окно Class Inspector.
Это редактор, в котором выводится исходный код элементов,
выбранных в области классов и области событий. Это окно имеет те
же функциональные возможности, что и окно редактирования IDE.
В области регистров (верхняя область справа от области кода)
выводится содержимое регистров процессора. Вид этой области зависит от отладчика (TD32 или TDW). По умолчанию TDW выводит 13
16-разрядных регистров, а TD32 - всегда выводит 15 регистров процессора 80386 и старше.
С помощью команд SpeedMenu области регистров вы можете модифицировать или сбрасывать содержимое регистров. Команда Increment
добавляет 1 к текущему подсвеченному регистру, Decrement вычитает
1 из содержимого текущего подсвеченного регистр, а Change позволяет изменить содержимое регистра, выводя диалоговое окно Enter
New Value для ввода нового значения. Последняя команда вызывается
автоматически, если вы начинаете набор в области регистров.
Команда Registers 32-bit, доступная только в TDW, переключает вывод регистров с 16-битовых на 32-битовые (сегментные регистры остаются 16-битовыми).
В этой области (только для TDW) выводится список селекторов
защищенного режима и указывается некоторая информация для каждого
из них. Селектор может быть допустимым или нет. Допустимый селектор указывает на ячейку таблицы дескрипторов защищенного режима,
соответствующего адресу памяти. Если селектор недопустим, то он
не используется. Для допустимого селектора в области выводится
следующее:
являются ли содержимым данные или код;
загружена ли область памяти, на которую ссылается селектор
(присутствует в памяти) или разгружена (выведена на диск);
длина сегмента памяти, на которую ссылается селектор (в
байтах).
Если селектор ссылается на сегмент данных, то имеется дополнительная информация по полномочиям доступа (Read/Write - Чтение/
Запись или Read only - только чтение) и направление расширения
сегмента в памяти (Up - вверх или Down - вниз).
Локальное меню области можно использовать для перехода к новому селектору или просмотра содержимого подсвеченного. В зависимости от характера данных, содержимое выводится в области кода или области дампа.
Команда Selector выводит подсказку для ввода селектора, который нужно вывести в области. Для ввода селектора вы можете использовать полный синтаксис выражений. Если вы вводите числовое значение, то TDW подразумевает, что оно десятичное (если вы не
используете синтаксис текущего языка для указания того, что значение является шестнадцатиричным).
Другим методом ввода значения селектора является вывод окна
CPU и проверка содержимого сегментных регистров. Если регистр содержит интересующий вас селектор, то вы можете ввести имя регистра с предшествующим символом подчеркивания (_). Например, вы можете задать имя сегментного регистра данных, как _DS.
Команда Examine выводит содержимое области памяти, на которую ссылается текущий селектор, и переключается в область, где
выводится содержимое. Если селектор указывает на сегмент кода, то
содержимое выводится в области кода. Если содержимое представляет
собой данные, то оно выводится в области данных.
В области событий (Events) перечисляются события и виртуальные функции базового класса в классе, выбранном в области классов
(Classes). Информация в области событий зависит от типа базового
класса. Используя оперативное меню этой области, вы можете добавить или удалить обработчики сообщений и экземпляры переменных.
Иногда вместо выбора для трассировки конкретных окон может
потребоваться просматривать сообщения для всего класса окон. Это
можно сделать с помощью области списка классов.
Эта область показывает шестнадцатиричное содержимое программного стека. Текущий указатель стека отмечается указателем >.
SpeedMenu этой области содержит команды Goto, Origin, Follow,
Previous и Change, аналогичные описанным выше командам.
Утилита DFA обрабатывает информацию Турбо отладчика,
собранную WinSpector во время возникновения исключительной ситуации. Если во время исключительной ситуации информация отчета установлена в PostMortem Dump, то WinSpector записывает файл
WINSPCTR.BIN. После этого для трансляции файла WINSPCTR.BIN в полезный формат можно использовать утилиту DFA.
Ниже приведены функции обработки ошибок в графическом режиме:
| grapherrormsg | Возвращает строку с сообщением об ошибке
для заданного кода ошибки. |
| graphresult | Возвращает код ошибки для последней графической операции, в которой встретилась
ошибка. |
Если ошибка произошла при вызове графической библиотечной
функции (например, не найден шрифт, запрошенный функцией settextstyle), устанавливается внутренний код ошибки. Доступ к коду
ошибки для последней графической операции, сообщившей об ошибке,
выполняется при помощи функции graphresult. Вызов grapherrormsg(graphresult()) возвращает строку сообщения об ошибке из
приведенной выше таблицы.
Код возврата ошибки накапливается, изменяясь только когда
графическая функция сообщает об ошибке. Код возврата ошибки сбрасывается в 0 только при успешном выполнении initgraph, либо при
вызове функции graphresult. Таким образом, если вы хотите знать,
какая графическая функция возвратила ошибку, нужно хранить значение graphresult во временной переменной и затем проверять ее.
| 0 | grOk | No error (нет ошибки) |
| -1 | grNoInitGraph | (BGI) graphics not installed
(use initgraph) (графика не инсталлирована используйте функцию initgraph) |
| -2 | grNotDetected | Graphics hardware not detecte
(графическое аппаратное обеспечение не обнаружено) |
| -3 | grFileNotFound | Device driver file not found
(не найден файл драйвера устройства) |
| -4 | grInvalidDriver | Invalid device driver file
(неверный файл драйвера устройства) |
| -5 | grNoLoadMem | Not enough memory to load driver
(не хватает памяти для загрузки драйвера) |
| -6 | grNoScanMem | Out of memory in scan fill
(кончилась память при сканирующем заполнении) |
| -7 | grNofloodMem | Out of memory in flood fill
(кончилась память при лавинном заполнении) |
| -8 | grFontNotFound | Font file not found (файл шрифта не найден) |
| -9 | grNoFontMem | Not enough memory to load font
(не хватает памяти для загрузки шрифта) |
| -10 | grInvalidMode | Invalid graphics mode for
selеcted driver (недопустимый графический режим для выбранного драйвера) |
| -11 | grError | Graphics error (графическая ошибка) |
| -12 | grIOerror | Graphics I/O error
(графическая ошибка ввода-вывода) |
| -13 | grInvalidFont | Invalid font file
(неверный файл шрифта) |
| -14 | grInvalidFontNum | Invalid font number (неверный номер шрифта) |
| -15 | grInvalidDeviceNum | Invalid device number (неверный номер устройства) |
| -18 | grInvalidVersion | Invalid version of file (неправильная версия файла) |
В данной главе описывается, как использовать таблицы реакции
ObjectWindows 2.0. Таблицы реакции - это методы, используемые для
обработки событий в приложении ObjectWindows. Для использования
таблицы реакции ObjectWindows нужно выполнить следующие шаги:
Описать таблицу реакции.
Определить таблицу реакции.
Определить записи таблицы реакции.
Описывать и определить функции-элементы реакции.
Для использования описываемых в данном разделе макрокоманд
вы должны включить файл заголовка owl\eventhan.h. Этот файл уже
включается файлами owl\module.h и owl\window.h, поэтому явно данный файл обычно включать не требуется.
Таблицы реакции ObjectWindows 2.0 - это значительное усовершенствование по сравнению с методами обработки событий Windows и
сообщениями, включая оператор switch (как в стандартных программах Си для Windows) и схемы, используемые в других прикладных
средах. Таблицы реакции ObjectWindows 2.0 предусматривают:
Автоматическую обработку сообщений для предопределенных
командных сообщений, что устраняет необходимость вручную
обрабатывать значения WPARAM и LPARAM.
Проверку ошибок и типов на этапе компиляции, при которой
проверяются типы параметров и типы результата функции обработки событий.
Возможность обрабатывать в одной функции несколько сообщений.
Поддержку множественного наследования и возможность для
каждого производного класса построения таблиц реакции на
основе базового класса или классов.
Переносимость на разные продукты без специальных расширений компилятора.
Простую обработку команд, регистрации, уведомления дочернего объекта и специальных сообщений с помощью стандартных
макрокоманд таблицы реакции.
Обычно события Doc/View обрабатываются через объект приложения и интерфейсный элемент вашего отображаемого элемента. Вы можете управлять выводом на экран отображаемого элемента через указатель или смешивать функциональные возможности интерфейсного
объекта с классом отображаемого элемента.
Если при построении объекта TDocManager вы задаете параметр
mdMenu, администратор документа обрабатывает определенные события
от имени документов. Это делается путем обработки стандартных команд меню с помощью таблицы реакции. Команды меню администратора
документа доступны даже при отсутствии открытого документа и независимо от явного добавления в приложение ресурсов. Администратор документов может обрабатывать следующие события:
| CM_FILECLOSE | Закрытие файла. |
| CM_FILENEW | Создание нового файла. |
| CM_FILEOPEN | Открытие файла. |
| CM_FILEREVERT | Отмена изменений файла. |
| CM_FILESAVE | Сохранение файла. |
| CM_FILESAVEAS | Сохранение файла под новым именем. |
| CM_VIEWCREATE | Создание отображаемого элемента. |
В некоторых экземплярах вы можете обрабатывать эти события
самостоятельно. Так как поиск в таблице событий администратора
документа выполняется в последнюю очередь, вы можете обрабатывать
эти события на уровне отображаемого элемента, рамки или приложения. Можно также построить администратор документа без параметра
dmMenu и предусмотреть функции для обработки этих событий (обычно
через объект приложения или другой интерфейсный объект).
Файл заголовка docview.h предусматривает ряд макрокоманд для
таблицы реакции, а также функции обработки и проверки типов. С
помощью NOTIFY_SIG и VN_DEFINE вы можете также определить собственные функции и события.
Имеется ряд предопределенных событий Doc/View. Каждое такое
событие имеет соответствующую макрокоманду таблицы реакции и сигнатуру функции-обработчика. Модель Dec/View не предусматривает
версий этих функций. Вы должны определить эти функции в своем
производном классе и задать соответствующие действия.
| EV_VN_VIEWOPENED | Построение нового отображаемого элемента. |
| EV_VN_VIEWCLOSED | Уничтожение нового отображаемого элемента. |
| EV_VN_DOCOPENED | Открытие нового документа. |
| EV_VN_DOCCLOSED | Закрытие нового документа. |
| EV_VN_COMMIT | Изменения, внесенные в данные в отображаемом элементе должны быть зафиксированы в документе. |
| EV_VN_REVERT | Изменения, внесенные в данные в отображаемом элементе должны быть отменены. |
| EV_VN_ISDIRTY | Если изменения еще не зафиксированы в документе, следует возвратить True, иначе False. |
| EV_VN_ISWINDOWS | Если параметр HWND совпадает с HWND окна отображаемого элемента, следует возвратить True. |
Для генерации собственных событий отображаемых элементов и
определения соответствующих макрокоманд и функций обработки событий таблицы реакции вы можете использовать макрокоманды VN_DEFINE
и NOTIFY_SIG.
Во-первых, нужно определить имя события, которое вы хотите
обрабатывать. По соглашению оно должно начинаться с vn. Для задания сигнатуры функции обработки события используйте макрокоманду
NOTIFY_SIG, а для определения самой макрокоманды - VN_DEFINE. Эта
макрокоманда имеет три параметра: имя события, имя функции обработки события и размер параметра для функции обработки события.
Объект приложения управляет обычно только несколькими событиями, указывающими на создание или уничтожение документа или
отображаемого элемента. Событие dnCreate генерируется при создании отображаемого элемента или документа, а dnClose - при их закрытии. Чтобы задать для этих событий таблицу реакции, добавьте в
нее макрокоманды EV_OWLDOCUMENT и EV_OWLVIEW.
После инициализации приложения начинает выполняться цикл опроса сообщений объекта - MessageLoop. MessageLoop отвечает за обработку поступающих от Windows сообщений. Изменить обработку сообщений в ObjectWindows можно двумя способами: задать дополнительную обработку сообщений, переопределив функции обработки, и
выполняя обработку во время простоя.
TApplication имеет функции-элементы MessageLoop, IdleAction,
PreProcessMenu и ProcessAppMsg, обеспечивающие для любых приложений ObjectWindows функциональные возможности обработки сообщений.
Обработка во время простоя реализуется с помощью переопределения IdleAction. Такая обработка выполняется, когда пользователь
не выполняет никаких действий. Такая обработка должна быть краткосрочной. Длительные операции следует разбивать на несколько процессов.
Параметр функции IdleAction idleCount задает, сколько раз
между сообщениями должна вызываться IdleAction. idleCount можно
использовать для выбора между низкоприоритетной и высокоприоритетной обработкой во время простоя. Если idleCount достигает высокого значения, то ввода от пользователя не было уже длительный период, и надежнее выполнить низкоприоритетную обработку.
В дополнение к своей собственной обработке всегда следует
вызывать функцию IdleAction базового класса. Если вы пишете приложения для Windows NT, то можете для фоновой обработки использовать несколько нитей.
Обрабатывать сообщения управляющих элементов VBX нужно через
родительский объект управляющего элемента. Чтобы родительский
объект мог обрабатывать эти сообщения, он должен быть производным
от класса TVbxEventHandler. Для этого вы можете смешать класс интерфейсного объекта, который хотите использовать для включения
VBX (например, TDialog, TFrameWindow или классы, производные от
интерфейсных классов ObjectWindows) с классом TVbxEventHandler.
Каждую выполненную инструкцию Turbo Debugger регистрирует в
протоколе выполнения (при трассировки программы). С помощью окна
протокола выполнения Execution History вы можете просмотреть выполненные инструкции и вернуться в нужную точку программы. Команда обратного выполнения Reverse Execute выполняется по клавишам
Alt+F4. Turbo Debugger может регистрировать около 400 инструкций.
Здесь действуют следующие правила:
Регистрируются только те инструкции, которые выполнены с
помощью команды Trace Into (F7) или Instruction Trace
(Alt+F7). Однако, если не выполняются отдельные инструкции
(перечисленные ниже), то регистрируются также команды Step
Over.
Инструкция INT приводит к стиранию протокола выполнения.
Если вы не трассируете прерывание с помощью Alt+F7, то об ратное выполнение этой инструкции невозможно.
После выполнения команды Run или выполнения после прерыва ния протокол удаляется. (Регистрация начинается после во зобновления трассировки.)
При выполнении вызова функции без ее трассировки обратное
выполнение за инструкцию после возврата невозможно.
Обратное выполнение инструкций работы с портами невозможно
(отменить чтение и запись нельзя).
Невозможно также обратное выполнение вызываемого програм мой кода Windows (если только вы не находитесь в окне CPU
и не отлаживаете DLL).
В окне CPU обратное выполнение доступно всегда, а для обратного выполнения исходного кода нужно установить Full History в On
(в меню Execution History). Меню Execution History содержит также
команды Inspect и Reverse Execute. Команда Inspect переводит вас
к команде, подсвеченной в области Instruction. Если это строка
исходного кода, она выводится в окне Module. При отсутствии исходного кода открывается окно CPU и подсвечивается инструкция в
области Code. Действие инструкций IN, INSB, INSW, OUT, OUTSB,
OUTSW отменить невозможно, поэтому их обратное выполнение может
давать побочные эффекты.
TD.EXE имеет в окне Execution History дополнительную область, позволяющую вам вернуться в нужную точку программы при
случайной потере протокола. Область Keystroke Recording в нижней
части этого окна активизируется при разрешении регистрации нажатий клавиш (это можно сделать с помощью TDINST или параметра -k
командной строки).
Область Keystroke Recording показывает причину передачи управления отладчику (например, точка останова) и текущий адрес
программы с соответствующей строкой исходного кода или машинной
инструкцией. Turbo Debugger регистрирует все нажимаемые вами клавиши и записывает их в файл XXXX.TDK, где XXXX - это имя отлаживаемой программы. Локальное меню этой области содержит команды
Inspect и Keystroke Restore. По команде Inspect отладчик активизирует окно Model или CPU, в котором курсор позиционирован на ту
строку, где нажата клавиша. Команда Keystroke Restore перезагружает программу и выполняет ее до строки, подсвеченной в области
Keystroke Recording.
В данном разделе описываются некоторые наиболее общие ошибки
и предупреждения, обнаруживаемые компилятором.
Call to function имя_функции with no prototype
(Вызов функции без прототипа)
Данное предупреждение означает, что функция используется перед ее прототипизацией или описанием. Это предупреждение может
выводиться также, когда функция, не воспринимающая аргументов, не
описана прототипом с void.
Conversion may lose signifigant digits
(Преобразование может привести к потере значимых цифр)
Это предупреждение является результатом преобразования компилятором значения, например, LONG в int. Оно сообщает, что вы
можете потерять информацию. Если вы уверены, что таких проблем не
возникает, то с помощью соответствующего явного приведения типа к
меньшему размеру это предупреждение можно подавить.
Function should return a value
(Функция должна возвращать значение)
Функция, описанная как возвращающая значение, значения не
возвращает. В старом коде Си, отличном от стандарта ANSI, такое
предупреждение является общим для функций, не возвращающих значения и не имеющих типа возврата:
foo(i)
int i;
{
...
}
Описанные таким образом функции интерпретируются компилятором, как возвращающие int. Если функция ничего не возвращает, ее
следует описать так:
void foo(int i)
{
...
}
Lvalue required
(Требуется именующее значение)
Type mismatch in parameter
(Несовпадение типа в параметре)
Эти ошибки указывают, что вы пытаетесь передать тип, отличный от указателя, там, где требуется указатель. При определении
STRICT описателей, а также LRESULT, WPARAM и LPARAM внутренним
образом описываются как указатели, поэтому попытка передачи в качестве указателя int, WORD или LONG дает в результате подобные
ошибки.
Эти ошибки следует исправлять путем описания отличных от
указателя значения, используемых при передаче параметров или
присваивании. В случае специальных констант, таких как (HWND)1,
вам следует пользоваться новыми макрокомандами (такими как
HWND_BOTTOM). Ошибки несоответствия типов следует подавлять в
Библиотека классов container, поставляемая в пакете Турбо и
Borland C++, содержит классы для часто используемых структур данных
(списки, стеки, очереди и т.д.). Классы организованы в соответствии с
иерархией классов, что позволяет иметь высокую степень модульности
благодаря свойствам наследования и полиморфизма. Вы можете использовать эти классы в том виде, как они есть, либо расширять и дополнять
их, получая объектно-ориентированные программные продукты, подходящие
для ваших задач.
В вершине иерархии классов conteiner находится абстрактный класс
Object. Он почти не содержит данных-элементов, а его функции элементы
являются "чистыми" виртуальными функциями (pure virtual - т.е. функциями, никогда не вызываемыми непосредственно, и служащими для задания местоположения функций с тем же именем, определяемых в производных классах). Неабстрактные классы, предназначенные для реализации
объектов, называются реализуемыми классами (абстрактные классы заключены в кавычки.)
Чтобы лучше освоить понятие классов, посмотрите их исходные
тексты в каталоге CLASSLIB дистрибутивной поставки компилятора.
"Object" Error
"Sortable" String
"BaseDate" Date
"BaseDate" Time
Association
"Container" "Collection" "AbstractArray" Array
SortedArray
HashTable Bad Set Dictionary
List
DoubleList
Stack
Queue
Deque
"ContainerIterator" HashTableIterator
ListIterator
DoubleListIterator
ArrayIterator
DoubleListElement
ListElement
Рис. Иерархия классов в CLASSLIB
Эти окна позволяют вам вывести детальную информацию по классам С++. Чтобы открыть это окно, выведите окно Hierarchy, подсветите класс и нажмите Enter.
[Ч] Class LinearGauge 4 [^][v]
int Range::Low ^
int Range::High
int Screen::MaxX v
< >
class Range *Range::ctr()
int Range::GetValue()
int Range::GetLow()
int Range::GetHigh()
Данное окно содержит две области. В верхней области выводится информация о элементах данных и их типах, в нижней - о функциях-элементах и возвращаемых типах. Однако это окно не отражает данных конкретного экземпляра. Если вы хотите проверить аргументы
функцию-элемента, подсветите ее и нажмите Enter. Откроется окно
Function Inspector.
Если подсвеченный элемент данных представляет собой указатель на класс, то нажатие Enter открывает другое окно Class Inspector. Таким образом вы можете проверять сложные вложенные классы. Как и в случае других окон Inspector клавиша Esc закрывает
текущее окно Inspector, а Alt+F3 закрывает их все.
SpeedMenu каждой области данного окна содержит три команды,
которые в каждой области ведут себя несколько по разному.
| Inspect | В области элементов данных открывает для подсвеченного элемента данных окно Inspector. В области функций-элементов команда
открывает для подсвеченной функции окно Function Inspector. Для вывода исходного кода функции позиционируйте курсор на адрес функции-элемента и нажмите Enter. Откроется окно Module. | |
| Hierarchy | Во всех областях открывает окно Hierarchy для текущего подсвеченного класса. | |
| Show Inherited | В каждой области переключается между Yes (по умолчанию) и
No. При установке в Yes Turbo Debugger показывает для подсвеченного класса все функции-элементы или элементы данных, включая наследуемые. В противном случае выводятся только элементы данного класса. |
Выводят текущее содержимое выбранной переменной. Его можно
открыть с помощью команды Data Inspect или Inspect меню SpeedMenu. Закрывается оно обычно по Esc или щелчком "мышью" на блоке
закрытия. При последовательном открытии нескольких окон Inspector
нажатием Alt+F3 или командой Window Close вы можете закрыть сразу
все эти окна. Окна Inspector выводят простые скалярные величины,
указатели, массивы, объединения, структуры, классы и объекты. Выбором команды Inspect в этом окне вы можете создать дополнительные окна Inspector.
Эти окна предоставляют наилучший способ просмотра элементов
данных, так как они автоматически форматируются в соответствии с
типом данных. Их особенно полезно использовать при проверке сложных объектов данных (массивов или связанных списков). Чтобы просмотреть данные в шестнадцатиричном виде, в активном окне Inpsector используйте команду View Dump. Окна Inspector открываются из
команды Data Inspector или SpeedMenu окон Wathes, Variables или
Inspector.
При открытии окна Inspector выводится диалоговое окно Enter
Variable с подсказкой на ввод выражений. Введите имя переменной
или выражение. Если в момент команды Inspect курсор находится на
идентификаторе, или вы выделили выражение, то они автоматически
помещаются в поле ввода. Заголовок окна Inspector содержит проверяемое выражение.
Скалярное окно Inspector показывает значения простых элементов данных, таких как char, int или long. Оно содержит две строки: в первой указан адрес переменной, а вторая показывает ее тип и значение (в десятичном/шестнадцатиричном виде).
[*] Inspecting wordcount 3 [^][v]
05A51:AA00
unsigned int 2 (0x02)
< >
Окно Inspector для указателей выводит значения переменных,
указывающих на другие элементы данных. В верхней строке указывается адрес переменной, а далее следует детальная информация об
указываемых данных. В нижней области показывается тип этих данных.
[*] Inspecting bufp 3 [^][v]
register ds:0874 [TCDEMO buffer] ^
[0] 'n' 110 (Ox88)
[1] '0' 111 (Ox6F)
[2] 'w' 119 (Ox77)
< >
char *
Если указатель ссылается на сложный объект данных, значения
заключаются в фигурные скобки (выводится столько данных, сколько
можно показать). При ссылке на строку символов выводится каждый
элемент символьного массива с указанием индексов и значений. Команда Range позволяет выводить несколько строк информации.
Окна Inspector для структур и объединений показывают значения элементов в сложных объектах данных. Такое окно имеет две области. В верхней области выводится адрес объекта данных с перечислением имен и значений элементов данных объекта. Нижняя область содержит одну строку. Если вы в верхней области подсветите
Окна многодокументального интерфейса или окна MDI являются
частью интерфейса MDI, используемого для управления несколькими
окнами или отображаемыми элементами, связанными с одним приложением. Документ обычно предусматривает работу с файлами, например
редактирование файла или работу с файлом электронной таблицы.
Меню View является точкой входа в большинство окон Turbo Debugger. Перечислим их кратко. С помощью команды View Another вы
можете дублировать на экране окна Dump, File и Module.
Это окно используется для просмотра структуры и значений
конкретного экземпляра класса. Чтобы открыть данное окно, поместите курсор на конкретный экземпляр класса (в окне Module) и нажмите Ctrl+I.
[*] Inspecting tw 3 [^][v]
@75C6:01E8 ^
Screen::MaxX 500 (Ox1F4)
Screen::MaxY 512 (Ox200) v
< >
Screen::Convert @0000:0000
Screen::VertVtoA @0000:0000
Screen::VertAtoV @0000:0000
class TextWindow
Данное окно содержит три области. Область элементов данных
(верхняя) показывает текущие значения элементов данных объектов.
Окно функций-элементов (среднее) выводит текущие значения и адреса функций-элементов объекта. Область типов показывает тип подсвеченного элемента данных или функции-элемента.
SpeedMenu верхних двух областей содержат идентичные команды,
только область элементов данных содержит дополнительную команду
Change.
| Range | Позволяет вам задать диапазон выводимых элементов массива.
Если подсвеченный элемент не является массивом или указателем, то команда недоступна. | |
| Change | Позволяет изменить значение подсвеченного элемента данных. | |
| Methods | Переключается между Yes (по умолчанию) и No. В состоянии Yes
отладчик выводит среднюю область окна Object Inspector с перечислением функций-элементов. No отменяет вывод средней области. | |
| Show Inherited | Также переключается между Yes и No. В состоянии Yes показываются все функции-элементы, определенные в классе и наследуемые.
No позволяет вывести только функции-элементы, определенные в классе. | |
| Inspect | Открывает для текущего подсвеченного элемента окно Inspector. Проверка функции-элемента открывает окно Module, где курсор
позиционируется на определяющий эту функцию код. | |
| Descend | Работает аналогично команде Inspect SpeedMenu, но заменяет
текущее окно Inspector. Это уменьшает число открытых на экране окон inspector. | |
| New Expression | Используется для проверки различных выражений. Данные в текущем окне Inspector заменяются данными нового вводимого выражения. | |
| Type Cast | Позволяет задавать для текущего подсвеченного элемента данные различного типа. Эта команда полезна, если идентификатор не
имеет информации о типе и для явного задания типа указателей. | |
| Hierarchy | Открывает окно Hierarchy с наследованием текущего класса. |
Окна-рамки (объекты класса TFrameWindow) - это специализированные окна, поддерживающие клиентное окно. Они составляют основу
окон-рамок MDI и SDI, дочерних окон MDI и (вместе с TLayoutWindow) декорированных окон-рамок. Окна-рамки играют в ObjectWindows
важную роль и используются для управления такими элементами как
меню и полосы прокрутки. Их клиентные окна могут специализироваться для выполнения конкретных задач. Вносимые в окно-рамку изменения (например, добавление строки состояния) на клиентное окно
не влияет.
Окна реквизитов основываются на производном от TWindow классе TGadgetWindow. Они предназначены для размещения в них реквизитов, задания схемы их расположения и вывода их в другом окне. Окна реквизитов обеспечивают функциональные возможности для включенных в них реквизитов. Так как реквизиты не являются окнами,
они не могут выставлять или принимать события, непосредственно
взаимодействовать с окнами или вызывать для себя функции Windows.
Все, что требуется делать реквизиту, должно выполняться через окно реквизитов.
Реквизит практически не может управлять своим расположением
в окне реквизитов. Окно реквизитов отвечает за размещение и расположение всех реквизитов, который оно содержит. Обычно реквизиты
располагаются в одну линию (вертикально или горизонтально).
Реквизиты обычно включаются в другое окно. Родительским окном окна реквизитов является как правило декорированное окно-рамка, такое как TDecoratedFrame или TDecoratedMDIFrame, хотя класс
TToolBox использует обычно TFloatingFrame.
В конструкторе TGadgetWindow задается указатель на объект
родительского окна, направление (горизонтальное и вертикальное),
указатель на объект шрифта TFont и параметр TModule базового
конструктора (по умолчанию 0). Функция ~TGadgetWindow удаляет
каждый из реквизитов окна реквизитов, а затем удаляет объект
шрифта.
TGadgetWindow переопределяет заданную по умолчанию функцию-элемент Create. Версия TGadgetWindow этой функции выбирает
начальный размер на основе следующих критериев:
Установлена ли для реквизитов в окне автоматическая настройка размера.
Размера реквизитов, содержащихся в окне.
Направления расположения реквизитов в окне.
Имеет ли окно реквизитов рамку, и размера этой рамки.
Функция Create определяет на основе этих факторов подходящий
размер окна, устанавливает размеры атрибутов окна, а затем для
создания интерфейсного элемента окна вызывает базовую функцию
TWindow::Create.
Чтобы окно реквизитов выполняло полезные функции, оно должно
содержать некоторые реквизиты. Чтобы поместить реквизит в окно,
Окна схемы (разметки) инкапсулируют класс TLayoutWindow, инкапсулирующий производный от TWindow класс TLayoutWindow. Как и
TFrameWindow, TLayoutWindow создает основу для декорированных
окон-рамок и возможности упорядочения элементов в области рамки.
Окна схемы (или разметочные окна) называются так потому, что
могут упорядочивать дочерние окна в своей клиентной области. Расположение дочерних окон определяется относительно окна схемы или
другого дочернего окна ("братского" окна - окна равного уровня).
Расположение дочернего окна зависит от параметров схемы, которые
включат в себя ряд правил, описывающих координаты X и Y окон, их
высоту и ширину. Эти правила обычно основываются на координатах
братского окна и, в итоге, на размере и организации окна схемы.
Параметры схемы для дочерних окон содержатся в классе TLayoutMetrics. Объекты параметров схемы состоят из ряда ограничений
схемы. Каждое ограничение описывает правило определения конкретного изменения окна, например X-координаты или ширины окна. Эти
ограничения хранятся в структуре TLayoutConstraints, но обычно
используются производные от нее классы, такие как TEdgeConstraint.
Ограничения схемы определяют соотношение между краем или
размером одного окна и краем или размером братского или родительского окна схемы. Это соотношение может быть достаточно гибким.
Например, можно задать ширину окна как процент от ширины родительского окна. Ограничения задаются обычно с помощью функции
Set, которая определяется в классе TEdgeConstraint и в результате
наследуется из TEdgeOrWidthConstraint и TEdgeOrHeightConstraint.
Параметр edge функции Set определяет, какую часть окна вы
ограничиваете. Для этого используется enum TEdge с 5 возможными
значениями:
lmLeft определяет левый край окна.
lmTop определяет верхний край окна.
lmRight определяет правый край окна.
lmBottom определяет нижний край окна.
lmCenter определяет центрирование окна (горизонтальное или
вертикальное).
С помощью enum TWidthHeight можно задать ограничение высоты
Для вывода информации об отлаживаемой программе в Turbo Debugger используется набор окон. Для облегчения отладки служат команды управления окнами, которые находятся в меню Window и System. Каждое открываемое окно имеет номер, указанный в его правом
верхнем углу. Нажатием клавиши Alt в сочетании с номером окна вы
можете активизировать любое из первых 9 окон. Список открытых
окон содержится в нижней половине меню Window. Чтобы открыть
конкретное окно, нажмите в меню Window цифру номера окна. Если
окон больше 9, в этом меню выводится команда Window Pick, выводящая меню окон.
Клавиша F6 (или команда Window Next) позволяет циклически
перемещаться по открытым на экране окнам. Окно может иметь несколько областей. Для перемещения между областями используйте клавиши Tab или Shift+Tab, либо Window Next. Курсор в областях перемещается с помощью стандартных клавиш перемещения курсора.
При открытии нового окна оно выводится в месте текущего расположения курсора. Переместить его в другое место можно с помощью
команды Window Size/Move и клавиш стрелок, либо сразу нажмите
Shift и сдвигайте окно стрелками. Для быстрого увеличения или
уменьшения окна выберите Window Zoom (F5) или щелкните "мышью" на
кнопке минимизации/максимизации в верхнем правом углу окна.
Если вы по ошибке закрыли окно, вернуться в последнее окно
можно с помощью команды Window Undo Close (Alt+F6). Когда программа затирает своим выводом экран операционной среды (при выключенном переключении экрана), вы можете очистить его с помощью
System Repaint Desktop. Для возврата к используемой по умолчанию
схемы окон Turbo Debugger выберите System Restore Standard.
Каждое окно Turbo Debugger имеет специальное оперативное меню SpeedMenu, содержащее команды, относящиеся к данному окну. Области окон также могут иметь свои меню. Для доступа к SpeedMenu
активного окна или области вы можете нажать в окне правую кнопку
"мыши", либо нажать клавиши Alt+F10, либо нажать Ctrl и подсвеченную букву команды SpeedMenu (для этого должно быть разрешено
действие команд-сокращений).
Используется для установки, модификации или удаления точек
останова. Точка останова определяет то место в программе, где отладчик приостанавливает выполнение программы. Это окно имеет две
области. Справа перечислены условия и действия точек останова,
слева - все точки останова.
Создать окно точек останова Breakpoints можно с помощью команды View Breakpoints основного меню. Это дает вам способ выбора
и установки условий, при которых срабатывает точка останова. Это
окно можно использовать для добавления новых точек останова, отмены (удаления) точек останова и изменения существующих точек останова.
[*] Breakpoints 3 [^][v]
TCDEMO.220 Breakpoint
TCDEMO.225 Always
TCDEMO.226 Enabled
< >
В левой области этого окна показан список всех адресов, где
установлены точки останова. В правой области показаны подробные
данные по текущим (подсвеченным в левой области) точкам останова.
Локальное меню SpeedMenu окна Breakpoints можно получить по
нажатию клавиш Alt+F10. Команды данного меню позволяют вам добавлять новые точки останова, отменять существующие или изменять характер поведения имеющихся точек останова.
Буфер Clipboard отладчика используется для для вырезания и
вставки элементов из одного окна отладчика в другое. Оно показывает вырезанные элементы и их типы. Скопированные в буфер элементы динамически обновляются.
Выводит текущее состояние процессора. Окно имеет 6 областей,
где выводятся дизассемблированные инструкции, селекторы Windows
(только в TDW), шестнадцатиричные данные, стек в шестнадцатиричном виде, регистры ЦП и флаги процессора. Это окно полезно использовать при отладке программ на ассемблере или просмотре точно последовательности инструкций.
Это окно открывается командой View CPU строки меню и использует различные области для описания состояния вашей программы на
нижнем уровне. Его можно использовать для
просмотра машинного кода и дизассемблированных инструкций
программы;
проверки и модификации байт структур данных программы;
тестирования исправления ошибок с помощью встроенного ассемблера в области кода.
область регистров
область кода область стека
[*] CPU 80486 3 [^][ ]
TCDEMO.120: Inc(NumLines); ^ ax 0004 c=0
cs:04C4:4F36063000 inc word ptr [TPDEMO bx 3EEE z=0
TCDEMO.121 i := 1; cx 0000 s=0
cs:04C8 C:43FE0100 word ptr [bp+02].000 dx 5920 o=0
TCDEMO.122: while i <= Length(S) do si 3CEC p=0
cs:04C0 C47ED4 les di,[bp+04] bp 3EF4 a=0
cs:0400 288A05 mov al,es:[di] sp 3EF4 i=1
cs:0403 3D84 xor ah,ah ds 5920 d=0
cs:0405 3B48FE cmp ax,[bp+02] es 5920
cs:0408 7D03 jnl TPDEMO.125 (04DD) ss 595A
cs:040A 898A00 jmp TPDEMO.148 cs 548A
TCDEMO.125 while (i <= Length(S)) and notv ip 04C8
< >
ds:0008 5A 5D 5A 5D 5A 5D 00 00 Э^$< < ss:3EF2 548A
ds:0010 00 00 00 00 00 00 5A 5D 6D vЖ ss:3EF0>04C1
ds:0018 00 00 5A 5D 00 00 00 90 7 ss:3EEE 0246
область дампа область стека
Область кода показывает машинный код и дизассемблированные
машинные инструкции вашей программы. Здесь могут также выводиться
строки исходного кода. В области регистров выводится содержимое
регистров ЦП. В области флагов показывается состояние 8 флагов
процессора. В области дампа выводится шестнадцатиричный дамп любой области памяти, доступной для программы. Область стека показывает шестнадцатиричное содержимое стека программы. Область селекторов доступна только для TDW и показывает все селекторы Windows.
Для адресных ссылок вне текущего сегмента в окне CPU выводятся знаки вопроса. Клавиша Ctrl в сочетании со стрелками позволяет сдвигать вывод на 1 байт. При выполнении кода Windows, модуля без отладочной информации, остановке программы на инструкции
внутри строки исходного кода или при трассировке инструкций с помощью Alt+F7 окно CPU выводится автоматически.
Выводит в шестнадцатиричном виде содержимое любой области
памяти (аналогично области окна CPU). Команды SpeeMenu этого окна
позволяют вам модифицировать данные и работать с блоками памяти.
В этом окне выводится в непосредственном виде дамп любой области памяти. Оно работает так же, как область данных окна CPU.
[*] Dump 3 [^][v]
ds:0000 CD 20 00 A0 00 9A F0 FE = & U** ^
ds:0008 1B 02 B2 01 22 31 7C 01 <.^% .`
ds:0010 22 31 88 02 52 2B E2 1D * X 4-#
ds:0018 01 01 01 00 03 FF FF FF v
< >
С помощью команды View Another Dump вы можете одновременно
открыть несколько окон Dump.
Выводит последние выполненные машинные инструкции или исходные строки программы, номер строки исходного кода и следующую выполняемую инструкцию или строку кода. Используется для обратного
выполнения.
Выводит содержимое любого файла на диске. В нем можно просматривать шестнадцатиричные байты или текст ASCII и искать нужные
байтовые последовательности.
Выводит на экран дерево иерархии всех используемых текущим
модулем классов. Имеет область списка классов и дерева иерархии.
Это окно показывает взаимосвязь используемых в модуле классов.
Окно Hierarchy (открываемое командой View Hierarchy) служит
для проверки иерархии объектов или классов, которая выводится в
графическом виде.
Область классов Область иерархии
[*] Class Hierarchy 3 [^][v]
Devi e Point
GlowGauge Rectangle
HorzArrow Device
HorzBar TextWindow
LinearGauge Range
Point Device
Range GlowGauge
Rectangle
Screen Parents of Device
TextWindow Range
VertArrow Rectangle
VertBar Point
Screen
< >
Выводит содержимое журнала сообщений с прокручиваемым списком сообщений и информацией, сгенерированной при работе с отладчиком. Это окно можно также использовать для получения информации
об использовании памяти, модулях и оконных сообщения приложения
Windows.
Это окно отслеживает события, происходящие во время сеанса
отладки. Открывается оно по команде View Log и по умолчанию содержит до 50 строк текста (вы можете изменить это с помощью программы инсталляции).
[*] Log 3 [^][v]
At MCINPUT.124 ^
Breakpoint at TCDEMO.220
Breakpoint at TCDEMO.220
Breakpoint at TCDEMO.220
We are now entering procedure Params...
Breakpoint at TCDEMO.180 v
< >
В это окно записываются:
адрес программы при ее приостановке;
комментарий (при использовании команды Add Comment данного
окна);
значение выражения, определенного для активизированной
точки останова;
содержимое области или окна при выборе команды Edit Dump
to Log.
информация о локальной и глобальной динамической распределяемой памяти или список программных модулей (при выборе
команды Display Windows Info локального меню данного окна);
при установке в Yes параметра Send to Log Window окна Windows Messages в окно Log передаются все посылаемые данному
окну сообщения.
Команды SpeedMenu окна Log позволяют вам записывать журнал в
файл на диске, останавливать и начинать регистрацию, комментировать журнал, очищать его и записывать в него информацию о программе Windows.
| Open Log File | Эта команда записывает на дик все записи, регистрируемые в
окне Log. Вам выводится подсказка для ввода имени файла на диске. По умолчанию он имеет расширение .LOG, а его имя соответствует имени программы. При открытии файла в него записываются все уже зарегистрированные записи. Если это нежелательно, выберите сначала команду Erase Log. | |
| Close Log File | Закрывает файл, открытый с помощью команды Open Log File. | |
| Logging | Разрешает/запрещает запись событий в окно Log. Используется
для управления регистрацией событий. | |
| Add Comment | Позволяет включить в окно Log комментарии. Открывает диалоговое окно с подсказкой для ввода комментария. | |
| Erase Log | Очищает окно Log. Файл журнала на диске не изменяется. | |
| Display Windows Info | Доступна только для TDW и выводит на экран окно Windows Information. Позволяет вывести информацию о динамически распределяемой памяти и список модуля приложения. |
Одно из важнейших окон Turbo Debugger, показывающее исходный
код отлаживаемого программного модуля (включая DLL). Модуль должен компилироваться с отладочной информацией.
Показывает текущее состояние сопроцессора и имеет три области: содержимого регистров с плавающей точкой, значений флагов
состояния и значений управляющего флага. Это позволяет вам диагностировать проблемы в использующих сопроцессор подпрограммах.
См. файл TD_ASM.TXT.
Показывает содержимое регистров (в области регистров) и флагов ЦП (в области флагов). С помощью команд SpeedMenu вы можете
изменить их значения.
В окне Registers выводится содержимое регистров и флагов
центрального процессора. оно работает, как сочетание областей регистров и флагов в окне CPU и имеет те же команды.
Назад | Содержание | Вперед
При компиляции программ в окне сообщений выводятся ошибки и
предупреждения. С помощью команды Preferences в диалоговом окне
Enviroment Options вы можете настроить некоторые функциональные
возможности окон сообщений Message.
При выборе сообщения в окне Message редактор помещает курсор
в ту точку исходного кода, где произошла ошибка или предупреждение. Если файл с ошибкой не загружен в окне редактора, для его
загрузки нажмите пробел (можно воспользоваться и SpeedMenu). Окно
сообщений остается выбранным, так что вы можете перемещаться от
сообщения к сообщению. С помощью команды Remove all messages оперативного меню вы можете очистить окно сообщения. Клавиши Alt+F7
выводят следующее сообщение об ошибке, а Alt+F8 - предыдущее.
Показывает текущее состояние программного стека. Первая вызванная функция показывается в нижней части окна, а выше ее - каждая последующая. Подсвечивая эти функции и нажимая Ctrl+I вы можете проверять исходный код. Кроме того, можно открыть окно Variables и вывести все локальные переменные и аргументы функции (Ctrl+L).
Это окно позволяет проанализировать стек вызова и вывести в
удобном для чтения формате все активные функции и значения аргументов. Окно Stack вы можете создать с помощью команды View Stack. В окне стека выводится список всех активных процедур и
функций. Первой в списке указывается последняя вызванная процедуры, за которой следует вызвавшая ее процедура и предыдущая процедура, и так до самой первой функции программы (функция main в
Си). Это окно выводит также имена функций-элементов, перед которой указывается имя класса. При рекурсивном вызове окно Stack содержит несколько экземпляров функции.
[*] Stack 3 [^][v]
TCDEMO.PROCESSLINE.ISLETTER('A')
TCDEMO.PROCESSLINE('ABCDEF')
< >
SpeedMenu окна Stack содержит две команды: Ispect и Locals.
Команда Inspect открывает окно Module и позиционирует курсор на
активную строку подсвеченной функции. Если подсвеченная функция
находится в вершине стека вызова (последняя вызванная функция),
то в окне Module показывается положение счетчика команд. В противном случае курсор позиционируется на строку после вызова соответствующей функции. Вызвать эту команду можно также нажатием Enter после подстветки нужной функции. Команда Locals открывает окно Variables с идентификаторами, локальными для текущего модуля и
подсвеченной функции.
Выводит все переменные в данном контексте программы. В верхней области окна перечисляются глобальные переменные, а в нижней
- локальные. Это полезно использовать для поиска функции или
идентификатора, имени которых вы точно не помните.
В этом окне, которое открывается по команде View Variable,
показаны все локальные и глобальные переменные (с именами и значениями), доступные из текущего места программы. Его можно использовать, чтобы найти переменные, написание имен которых вы не помните. Для дальнейшего анализа или изменения их значений можно
использовать команды локальных меню. Это окно можно также использовать для проверки переменных, локальных по отношению к любой вызванной функции.
[*] Variables 3 [^][v]
TCDEMO.SHORESULTS @7129:01fA
TCDEMO.INIT @7129:0402
TCDEMO.PROCESSLINE @7129:04B5
TCDEMO.PARMSONHEAP @7129:0651
TCDEMO.NUMLINES 1 ($1)
TCDEMO.NUMWORDS 0 ($0)
< >
CH 'A'
ISLETTER True
S 'ABC DEF'
I 1 ($1)
WORDLEN 28969
Окно имеет две области. Область глобальных переменных (вверху), показывает все глобальные идентификаторы программы. Область
статических/локальных переменных (внизу) показывает все статические переменные (идентификаторы) текущего модуля. В обеих областях
выводится имя переменной (слева) и ее значение (справа). Если отладчик не может найти информации о типе данных идентификаторов,
то он выводит четыре вопросительных знака (????).
Меню окна Variables
Каждая область окна Variables имеет собственное SpeemMenu.
Оба меню содержат команды Inspect, Change и Wathes, а команда
Show имеется только в области локальных идентификаторов.
| Inspect | Открывает окно Inspector, где выводится содержимое подсвеченного идентификатора. В отличие от обычных окон Inspector, если
вы проверяете глобальную переменную, имя которой совпадает с именем локальной переменной, то Turbo Debugger выводит значение глобальной переменной. При проверке имени функции активизируется окно Module, а курсор перемещается на имя этой функции в исходном коде (при его отсутствии выводится окно CPU). | |
| Change | Открывает диалоговое окно Change, в котором можно изменит
значение подсвеченного идентификатора. | |
| Watch | Открывает окно Watches и добавляет в него подсвеченный идентификатор. При этом не отслеживается, глобальная это переменная
или локальная. В блоке локальной переменной локальная переменная имеет старшинство. | |
| Show | Выводит диалоговое окно Local Display. Кнопки с зависимой
фиксацией этого окна позволяют разрешить или изменить область действия переменной в области локальных переменных. | |
| Show | Показывать только статические переменные. | |
| Auto | Только переменные, локальные для текущего блока. | |
| Both | И статические, и локальные (по умолчанию). | |
| Module | Смена текущего модуля. Выводит диалоговое окно со
списком модулей программы. |
Показывает значения переменных и выражений. Введя в это окно
выражения, вы можете отслеживать их значения при выполнении программы. Окно добавляется с помощью клавиш Ctrl+W при установке курсора на переменной в окне Module.
Это окно обеспечивает самый простой способ отслеживания элементов данных программы. В нем вы можете просматривать переменные
и выражения, значения которых нужно отслеживать.
[*] Watches 2 [^][v]
wordcount unsigned int 8 (Ox8) ^
wordcounts unsigned int [10] {1,2,4,6,1,1,2,0,0,0}
lettersinfo struct linfo [26] {(4,2),(1,1),(0,0),(1,1),(7,0),(.
nlines*nwords unsigned int 24 (Ox22)
totalcharacters unsigned long 88L (Ox42) v
< >
Это окно допускает просмотр значений как простых переменных,
так и составных объектов данных (например, массивов). Элементы
составных объектов выводятся в фигурных скобках ({}). Можно также
отслеживать выражения, не ссылающиеся непосредственно на память.
Отслеживаемые выражения перечисляются в левой части окна, соответствующие типы данных и значения - справа.
Чтобы задать отслеживаемые данные, выберите команду Data Add
Watch, либо команду Watch локального меню окна Module, Variable
или Watches. Turbo Debugger открывает диалоговое окно Enter Expression to Watch. Введите в нем имя переменной или выражение.
Если в окне Module курсор находится на переменной, то она
автоматические добавляется в окно Watch при выборе окна Wathes в
SpeedMenu. Это же относится к выражениям, выделенными с помощью
клавиш Ins и стрелок.
Если не переопределяется область действия, отладчик вычисляет выражения относительно текущего указателя команд. Если выражение содержит символ, недоступный в активной области действия, то выводятся символы ????. При вводе выражений вы можете использовать имена еще не определенных переменных, поэтому имена следует
вводить аккуратно (Turbo Debugger не распознает ошибок).
При трассировке внутри функции-элемента можно использовать
указатель this, который можно сопровождать спецификаторами формата и квантификаторами.
Показывает список оконных сообщений программы Windows. Области этого окна показывают задание режима отслеживания сообщений, тип перехватываемых сообщений и перехваченные сообщения.
Оконные объекты - это интерфейсные объекты высокого уровня,
облегчающие работу с окнами, дочерними окнами и управляющими элементами. ObjectWindows предусматривает несколько различных типов
оконных объектов:
Окна схемы.
Окна-рамки.
Декорированные окна-рамки.
Окна MDI.
Еще один класс оконных объектов, окна реквизитов, описывается в другом разделе.
В дополнение к операциям переназначения <, > и >>, утилита
MAKE добавляет операции << и &&. Эти операции для создания подаваемых на вход команды данных создают в оперативном порядке файл.
Операция << создает временный файл и переназначает поток стандартного ввода команды таким образом, что он поступает из созданного файла. Если у вас имеется программа, которая допускает ввод
данных из потока stdin, то команда:
MYPROG <<!
Это лишь тест
!
будет создавать временный файл, содержащий строку "Это лишь тест
\n", переопределяя ее как единственный поток входной информации
для программы myрrog. Восклицательный знак (!) представляет собой
в данном примере разделитель; в качестве разделителя для этого
файла можно использовать любой символ за исключением символов #
или \. Первая строка, начальным символом которой является символ
разделителя, завершает файл. Остальная часть строки, следующая за
символом разделителя (в данном примере, восклицательным знаком)
считается часть предшествующей команды.
Операция && аналогична операции <<. Он создает временный
файл, но вместо того, чтобы сделать этот файл стандартным потоком
ввода для указанной команды, операция && заменяется именем временного файла. Это оказывается полезным в том случае, если вы хотите, чтобы утилита MAKE создала файл, который должен быть использован в качестве источника входных данных команды. В
приведенном ниже примере показывается, как создать "файл подсказки" для утилиты TLINK.
MYPROG.EXE: $(MYOBJS)
tlink /c @&&!
COS $(MYOBJS)
$*
$*
$(MYLIBS) EMU.LIB MATHS.LIB CS.LIB
Заметьте, что макрокоманда (которая обозначается с помощью
знака $) расширяется при создании файла. $* заменяется именем
создаваемого файла без расширения, а $(MYOBJS) и $(MYLIBS) заме-
няются значениями макрокоманд MYOBJS и MYLIBS. Таким образом, для
TLINK файл будет выглядеть следующим образом:
COS a.obj b.obj c.obj d.obj
MYPROG
MYPROG
w.lib x.lib y.lib z.lib EMU.LIB MATHS.LIB CS.LIB
Если не используется параметр командной строки -K, то все
временные файлы удаляются. Параметром -K следует пользоваться для
"отладки" временных файлов, если возникает впечатление, что эти
файлы работают неверно.
Ввод вывод с плавающей точкой требует компоновки с подпрограммами преобразования, используемыми функциями printf и scanf.
Чтобы уменьшить размер выполняемого файла, форматы с плавающей
точкой автоматически не компонуются. Однако такая компоновка автоматически выполняется при использовании в программе математической подпрограммы или получении адреса некоторого числа с плавающей точкой. Если не выполняется ни одно из этих действий не
выполняется, то отсутствие форматов с плавающей точкой может дать
в результате ошибку ввода-вывода. Правильно оформить программу
можно, например, следующим образом:
/* Подготовка к выводу чисел с плавающей точкой */
#include <stdio.h>
#pragma extref _floatconvert
void main() {
printf(*d = %f\n", 1.3);
}
В отладчик встроен контекстно-зависимый оперативный справочник. Он доступен как при работе в системе меню, так и при выводе
сообщения об ошибке или подсказки. Для вывода справочного экрана
с информацией, относящийся к текущему контексту (окну или меню)
нажмите клавишу F1. При наличие "мыши" вы можете вывести справочный экран, выбрав F1 в строке состояния. Некоторые справочные экраны содержат подсвеченные слова, которые позволяют вам получить
дополнительную информацию по данной теме. Для перемещения к нужным ключевым словам используйте клавиши Tab или Shift+Tab и нажмите клавишу Enter. Для перемещения к первому или последнему слову на экране используйте клавиши Home и End. Доступ к оперативным
справочным средствам можно получить также с помощью команды Help
из строки меню (оперативные клавиши Alt+H).
Если вы хотите вернуться к предыдущему справочному экрану,
нажмите клавиши Alt+F1 или выберите команду Previous из меню
Help. В справочной системе для просмотра последних 20 экранов
можно пользоваться клавишей PgUp (клавиша PgDn работает, когда вы
находитесь в группе связанных экранов). Для доступа к индексному
указателю справочной системы нажмите Shift+F1 (или F1 в справочной системе) или выберите команду Index в меню Help. Для получения информации о самой справочной системе выберите в меню Help
команду Help Help. Для выхода из справочной системы нажмите клавишу Esc.
При работе в отладчике в нижней части экрана выводится краткая справочная строка. В этой строке состояния кратко описаны
клавиши или команды меню для текущего контекста.
Оператор CODE определяет стандартные атрибуты сегментов кода. Сегменты кода могут иметь любое имя, но должны принадлежать
классам сегментов, имена которых оканчиваются на CODE. Например,
корректными именами классов сегментов являются CODE и MYCODE.
Оператор имеет следующий синтаксис:
Для TLINK:
CODE [FIXED MOVEABLE]
[DISCARDABLE NONDISCARDABLE]
[PRELOAD LOADONCALL]
Для TLINK32:
[PRELOAD LOADONCALL]
[EXECUTEONLY EXECUDEREAD]
FIXED означает, что сегмент занимает фиксированное положение
в памяти; MOVEABLE означает, что сегмент может перемещаться.
DISCARDABLE означает, что сегмент может отбрасываться, если
он больше не нужен. DISCARDABLE подразумевает MOVEABLE.
NONDISCARDABLE означает, что сегмент не может отбрасываться.
PRELOAD означает, что сегмент загружается при первой загрузке модуля; LOADONCALL означает, что сегмент загружается, когда
вызывается код, находящийся в этом сегменте. Компилятор ресурсов
и загрузчик Windows устанавливают сегмент кода, содержащий начальную точку входа в программу, в значение PRELOAD независимо от
содержания файла определения модуля.
EXECUTEONLY означает, что сегмент кода может быть только выполняемым. EXECUTEREAD означает, что сегмент кода может считываться и выполняться.
Оператор DATA определяет стандартные атрибуты сегментов данных и имеет синтаксис:
DATA [NONE SINGLE MULTIPLE]
[READONLY LOADCALL]
[PRELOAD LOADONCALL]
[SHARED NONSHARED]
NONE означает отсутствие сегмента данных. Если задается
NONE, то другие параметры использовать нельзя. Этот параметр
используется только для библиотек.
READONLY означает, что сегмент данных может только считыватьcя. READWRITE означает чтение и запись в сегмент данных.
PRELOAD означает, что сегмент данных загружается при первой
загрузке модуля. LOADONCALL (по умолчанию) означает, что сегмент
данных загружается при первом обращении (для 32-разрядных приложений это игнорируется).
SHARED (по умолчанию для 16-разрядных приложений) означает,
что одна копия сегмента данных совместно используется всеми процессами. NONSHARED (по умолчанию для программ и 32-разрядных DLL)
означает, что копия сегмента данных загружается для каждого процесса, которому требуется использовать сегмент данных.
DESCRIPTION вставляет текст в модуль прикладной программы.
Оператор DESCRIPTION обычно используется для вставки автора, даты
или информации о копировании. Оно является необязательным параметром. Оператор имеет синтаксис:
DESCRIPTION 'текст'
где "текст" является строкой ASCII, разделенной одинарными кавычками.
EXETYPE задает стандартный тип заголовка (Windows или OS/2)
выполняемого файла (.EXE) для 16-разрядных приложений. В 32-разрядных приложениях для обратной совместимости этот оператор можно
сохранить. В данной версии Borland C++ можно задавать только значение WINDOWS. Оператор имеет синтаксис:
EXETYPE WINDOWS