Написание переносимого кода Windows
В данном разделе обсуждаются конструкции (введенные в
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 | Описатель задачи. |
Определить, какой программный код вы хотите согласовать
со STRICT.
Включить наивысший уровень вывода ошибок/предупреждений.
В IDE используйте команду
Options Compiler Messages Display All. В BCC32 укажите
параметр -w.
Перед включением windows.h и компиляцией определить
STRICT с помощью #define или использовать в командной
строке параметр -DSTRICT.
Перечислим некоторые рекомендации, которые могут оказаться
полезными при преобразовании вашего программного кода в соответствии со STRICT:
Измените HANDLE на соответствующий тип описателя, например, HMODULE, HINSTANCE и др.
Измените WORD на UINT (за исключением тех мест, где вы
хотите получить 16-битовое значение на 32-разрядной платформе).
Измените WORD на WPARAM.
Измените LONG на LPARAM или LRESULT.
Измените FARPROC на WNDPROC, DLGPROC или HOOKPROC.
В 16-разрядной Windows всегда описывайте указатели функций
с помощью подходящего типа функции, а не с помощью
FARPROC. При использовании MakeProcInstance,
FreeProcInstance и других функций, воспринимающих или
возвращающих FARPROC, вам нужно приводить типы указателей
функции, например:
BOOL CALLBACK DlgProc(HWND hwnd, UINT msg,
WPARAM wParam,
LPARAM lParam);
DLGPROC lpfnDlg;
lpfnDlg=(DLGPROC)MakeProcInstance(DlgProc, hinst);
...
FreeProcInstance((FARPROC)lpfnDlg);
Особое внимание обратите на HMODULE и HINSTANCE. Функции
ядра, осуществляющие управление модулями, обычно используют HINSTANCE, но некоторые API возвращают или воспринимают
только HMODULE.
Если вы копируете какие-то описания функций API из
WINDOWS.H, они могут быть изменены, и ваши описания могут
оказаться устаревшими. Удалите локальные описания.
Приведите тип результата LocalLock и GlobalLock к соответствующему виду указателя данных. Параметры этих и других функций управления памятью должны при необходимости
приводиться к LOCALHANDLE или GLOBALHADLE.
Приведите результат GetWindowWord и GetWindowLong и параметры к SetWindowWord и SetWindowsLong.
При приведении типа SendMessage, DefWinmdowProc и
SendDlgItemMsg или любых других функций, которые возвращают LRESULT или LONG к какому-либо описателю вы должны сначала привести результат к UINT:
HBRUSH hbr;
hbr = (HBRUSH)(UINR)
SendMessage(hwnd WM_CTLCOLOR, ..., ...);
Параметр CreateWindow и CreateWindowEx функции hmenu иногда используются для передачи целочисленного управляющего
идентификатора. В этом случае вы должны привести тип к
HMENU:
HWND hwmd;
int id;
hwnd = CreateWindow("Button", "Ok", BS_PUSBUTTON,
x, y, cx, cy, hwndParent,
(HMENU)id, // здесь требуется приведение типа
hinst, NULL);
Полиморфические типы данных (WPARAM, LPARAM, LRESULT, void
FAR*) следует возможно скорее присваивать переменным. Избегайте использовать их в своих программах, когда тип значения известен. Это минимизирует число потенциально небезопасных и непереносимых в 32-разрядный режим преобразований типов. Макрокоманды API и механизмы обработки сообщений, предусмотренные в windowsx.h, будут выполнять практически всю упаковку и распаковку этих типов данных способом, обеспечивающим переносимость в 32-разрядный режим.
Ознакомьтесь с наиболее общими предупреждениями и ошибками
компилятора, которые вы можете обнаружить при переходе к
STRICT.
Наш декомпрессор в стиле фильтра
Декомпрессор, работающий в посимвольном режиме будет выглядеть
так:
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;
}
Наследование
Наследование - это способность брать существующий - базовый
класс и порождать из него новый класс - потомок, с наследованием всех
его атрибутов и поведения. Это пожалуй самая впечатляющая возможность
объектно-ориентированного программирования и, возможно, единственное
коренное отличие С++ от Си.
Рассмотрим отвлеченный пример из реальной жизни - классификационную схему живых организмов. По этой схеме растительные и живые
царства делятся на группы, так называемые типы. Каждый тип, в свою
очередь, делится на классы, отряды, семейства и далее. Группы более
низкого уровня наследуют характеристики групп более высоких уровней.
Так, из утверждения о том, что волк относится к семейству псовых, вытекает сразу несколько положений. Из него следует, что у волков хорошо развиты слух и обоняние, поскольку таковы характеристики псовых.
Так как псовые входят в отряд хищных, это утверждение говорит еще о
том, что волки питаются мясом. Поскольку хищные относятся к млекопитающим, это утверждение говорит и о том, что волки имеют волосяной
покров и регулируемую температуру тела. Наконец, так как млекопитающие являются позвоночными, мы узнаем и то, что у волков есть позвоночник.
Волк -> Псовые -> Хищники -> Млекопитающие -> Позвоночные
Подобные схемы наследования можно проследить в классификации
языков программирования, классификации типов компьютеров и других.
Рассмотрим существующие в объектно-ориентированных языках иерархии
порождаемых объектов.
и Windows NT. ObjectWindows позволяет
ObjectWindows 2.0 - это прикладная среда Borland С++ для
Windows 3.1, Win32S и Windows NT. ObjectWindows позволяет быстро
и легко строить полнофункциональные приложения Windows и обеспечивает следующие возможности:
Легкую переносимость между 16- и 32-разрядными платформами.
Автоматизированную обработку сообщений.
Надежную обработку особых ситуаций и ошибок.
Позволяет легко переносить программы в другие среды и компиляторы.
Инкапсулирует объекты GDI Windows.
Имеет классы Doc/View для простой абстракции и вывода данных.
Содержит классы для работы с принтером и предварительного
просмотра печатаемой информации на экране.
Поддерживает управляющие элементы VisualBasic.
Имеет средства проверки допустимости ввода.
Настройка конфигурации IDE
Вы можете настроить конфигурацию 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
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 позволяет вам либо добавить отчеты к
предыдущему файлу регистрации, либо затереть предыдущий файл регистрации при генерации нового отчета. По умолчанию задается затирание предыдущего файла.
Если вы выбираете перезапись предыдущего файла регистрации,
то при первом возникновении исключительной ситуации предыдущий
файл регистрации затирается. Последующие исключительные ситуации,
возникающие в процессе текущего сеанса работы с Windows, будут
добавлять информацию к этому файлу.
Чтобы добавлять отчеты к предыдущему файлу регистрации, сделайте следующее:
Откройте диалоговое окно Preferences.
Установите Log File в Append New Reports.
Выберите командную кнопку OK.
либо нужно добавить Add CreateNewLog=0 в файл WINSPCTR.INI.
Чтобы затирать предыдущие файлы регистрации, сделайте следующее:
Откройте диалоговое окно Preferences.
Установите Log File в Overwrite Previous Reports.
Выберите командную кнопку OK.
либо добавьте Add CreateNewLog=1 в файл WINSPCTR.INI.
Параметр System Information в диалоговом окне Preferences
позволят вам добавить в файл регистрации список задач Task List,
список модулей Module List, и информацию о динамически распределяемой области памяти пользователя (USER) и GDI. По умолчанию в
отчет включается системная информация.
Чтобы включить системную информацию в файл регистрации, сделайте следующее:
Откройте диалоговое окно Preferences
В Report Information выберите System Info.
Выберите командную кнопку OK.
либо нужно добавить Add ShowSystemInfo=1 в файл WINSPCTR.INI.
Чтобы системная информация не включалась в файл регистрации,
сделайте следующее:
Откройте диалоговое окно Preferences
В Report Information отмените System Info.
Выберите командную кнопку OK.
либо нужно добавить Add ShowSystemInfo=0 в файл WINSPCTR.INI.
Параметр AUX Summary в диалоговом окне Preferences указывает
WinSpector, что на устройство AUX нужно выводить сокращенную форму отчета. Чтобы использовать данный параметр, нужно подключить к
AUX терминал или драйвер устройства, который перенаправляет AUX
на второй монитор. По умолчанию информация на AUX не выводится.
Для передачи итогового отчета на устройство AUX сделайте
следующее:
Откройте диалоговое окно Preferences.
В Report Information, выберите Summary To AUX.
Выберите командную кнопку OK.
либо добавьте LogToStdAux=1 в файл WINSPCTR.INI.
Чтобы итоговый отчет не передавался на устройство AUX сделайте следующее:
Откройте диалоговое окно Preferences.
Under Report Information, отмените Summary To AUX.
Choose OK.
либо добавьте LogToStdAux=0 в файл WINSPCTR.INI.
Параметр Stack Frame Data в диалоговом окне Preferences позволяет вам выполнить подробную трассировку стека в файл регистрации. Для кадра стека не превышающего 256 байт выполняется шестнадцатиричный дамп, начиная с SS:BP для кадра стека. Если между двумя последовательными кадрами стека больше 256 байт, то показ
памяти для этого кадра опускается. Эти данные можно использовать
для получения значений или параметров, которые передавались функции. По умолчанию подробная трассировка стека не выполняется.
Обычно для выявления значений параметров существенно проще
использовать утилиту DFA. Однако в тех случаях, когда вам недоступна информация отладчика, может оказаться полезной подробная
трассировка стека. Чтобы добавить данные трассировки стека в файл
регистрации, сделайте следующее:
Откройте диалоговое окно Preferences.
В Report Information, выберите Stack Frame Data.
Выберите командную кнопку OK.
либо добавьте ShowStackInfo=1 в файл WINSPCTR.INI.
Чтобы не включать данные кадра стека в файл регистрации,
сделайте следующее:
Откройте диалоговое окно Preferences.
В Report Information, отмените Stack Frame Data.
Выберите командную кнопку OK.
либо добавьте ShowStackInfo=0 в файл WINSPCTR.INI.
Параметр PostMortem Dump в диалоговом окне Preferences генерирует файл WINSPCTR.BIN.
Утилита DFA воспринимает файл WINSPCTR.BIN и информацию Турбо отладчика (файлы .TDS) и транслирует непосредственные двоичные
данные в полезную форму. Она генерирует файл, содержащий трассировку стека аналогичную той, что выводится в файл регистрации, но
с именами функций и номерами строк, а также локальными и глобальными переменными.
Генерация файла WINSPCTR.BIN:
Откройте диалоговое окно Preferences.
В Report Information выберите PostMortem Dump.
Выберите командную кнопку OK.
либо добавьте PostMortemDump=1 в файл WINSPCTR.INI.
Чтобы не генерировать файл WINSPCTR.BIN, сделайте следующее:
Откройте диалоговое окно Preferences.
В Report Information, отмените PostMortem Dump
Выберите командную кнопку OK.
либо добавьте PostMortemDump=0 в файл WINSPCTR.INI.
Параметр User Comments в диалоговом окне Preferences позволяет вам ввести информацию о том, что происходило во время возникновения исключительной ситуации. Диалоговое окно выводится
немедленно после записи файла регистрации, и в это время можно
ввести комментарии о том, что произошло. Ваши комментарии будут
добавляться к файлу регистрации.
Чтобы добавить комментарии пользователя в файл регистрации,
сделайте следующее:
Откройте диалоговое окно Preferences.
В Report Information, выберите User Comments.
Выберите командную кнопку OK.
либо добавьте ShowUserInfo=1 в файл WINSPCTR.INI.
Чтобы не включать комментарии пользователя в файл регистрации, сделайте следующее:
Откройте диалоговое окно Preferences.
В Report Information, отмените User Comments.
Выберите командную кнопку OK.
либо добавьте ShowUserInfo=0 в файл WINSPCTR.INI.
Настройка Turbo Debugger
Вы можете конфигурировать параметры вывода 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);
}
Отметим, что главная программа не знает как работает сам декомпрессор. Она только передает ему аргументы. Декомпрессор, обрабатывая
один символ за раз, может перенаправить его по множеству путей. Так,
он мог бы был выведен непосредственно на экран, как мы это делаем
здесь, передан подпрограмме поиска строки или анализатору ... в соответствии с концепцией.
- O -
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[] отсутствует ])
В С++ operator[] была объявлена как operator[. Вы должны добавить недостающую квадратную скобку или еще как-либо исправить
объявление.
operator -> must return a pointer or a class
Сообщение об ошибке этапа компиляции
(operator -> должна возвращать указатель или класс)
Функция С++ операция operator-> должна быть объявлена как
возвращающая класс или указатель на класс (или структуру либо
объединение). В любом случае это должно быть нечто такое, к чему
применима операция ->.
Operator delete must return void
Сообщение об ошибке этапа компиляции
(Операция delete должна возвращать void)
Переопределенная операция С++ operator delete была объявлена
иначе.
Operator delete[] must return void
Сообщение об ошибке этапа компиляции
(Операция delete должна возвращать void)
Переопределенная операция С++ operator delete была объявлена
иначе. Опишите delete с одним параметром void*, а другим - типа
size_t.
Operator must be declared as function
Сообщение об ошибке этапа компиляции
(операция должна описываться как функция)
Переопределяемая операция была описана с типом, отличным от
типа функции.
Operator new[] must have an initial parameter of type size_t
Сообщение об ошибке этапа компиляции
(операция new[] должна иметь параметр инициализации типа size_t)
Операция new может объявляться с произвольным числом параметров, но обязательно должна иметь хотя бы один параметр, в котором будет находиться размер распределяемой памяти.
Operator new must return an object of type void*
Сообщение об ошибке этапа компиляции
(операция new должна возвращать объект типа void*)
Переопределенная операция С++ operator new была объявлена
иначе.
Operator new[] must return an object of type void*
Сообщение об ошибке этапа компиляции
(операция new[] должна возвращать объект типа void*)
Переопределенная операция С++ operator new была объявлена
иначе.
Out of memory
Фатальная ошибка этапа компиляции
(недостаточно памяти)
Исчерпана общая рабочая память. Повторите компиляцию этого
файла на машине с большей доступной памятью. Если у вас и так
имеется 640К, следует упростить исходный файл.
Out of memory
Сообщение об ошибке утилиты TLIB
(недостаточно памяти)
По каким-то причинам утилита TLIB или Borland C++ исчерпали
при построении библиотеки доступную память. Во всех конкретных
случаях выводятся также детальное сообщение, а "Out of memory" -
это общая ситуация нехватки памяти в разных ситуациях. При работе
в Windows, чтобы освободить память, закройте одну или более прикладных программ.
Если данное сообщение возникает, когда слишком большой становится таблицы идентификаторов, вы должны освободить память. Для
командной строки это предполагает удаление резидентных программ
или драйверов устройств, использующих память реального режима. В
интегрированной среде дополнительную память можно получить, закрыв редакторы. При работе в Windows, чтобы освободить память,
закройте одну или более прикладных программ.
Out of memory
Сообщение об ошибке утилиты TLINK
(недостаточно памяти)
TLINK исчерпал динамически распределяемую память, необходимую для процесса компоновки. Эта общая ошибка возникает во многих
ситуациях, когда утилите TLINK не хватает памяти. Обычно это означает, что в компонуемых объектных файлах определено слишком
много модулей, внешних идентификаторов, групп или сегментов. Вы
можете попробовать уменьшить объем виртуальных дисков и/или активных дисковых буферов. При работе под Windows, чтобы освободить
память, закройте одну или более прикладных программ.
out of memory creating extended dictionary
Сообщение об ошибке утилиты TLIB
(не хватает памяти при создании расширенного словаря)
Библиотекарь исчерпал память при создании расширенного словаря библиотеки. Библиотека будет создана, но не будет иметь расширенного словаря.
out of memory reading LE/LIDATA record from object module
Сообщение об ошибке утилиты TLIB
(не хватает памяти при чтении записи LE/LIDATA из объектного
файла)
Библиотекарь пытается прочитать запись данных из объектного
модуля, но не может получить достаточно большой блок памяти. Если
добавляемый блок содержит большой сегмент или сегменты данных, то
возможно добавление этого модуля перед другими модулями позволит
решить проблему. Добавив модуль первым, вы получите дополнительную память для записи общедоступных переменных и списка модулей,
добавляемых далее.
Out of space allocating per module debug struct
Сообщение об ошибке утилиты TLIB
(нет памяти при выделении структуры для модулей)
Библиотекарь исчерпал память выделяя пространство для отладочной информации, связанной с конкретным объектным модулем. Устранение отладочной информации из некоторых добавляемых в библиотеку модулей может устранить проблему.
Output device is full
Сообщение об ошибке утилиты TLIB
(устройство вывода переполнено)
Устройство вывода переполнено (обычно нет места на диске).
Overlays generated and overlay manager included
Предупреждение утилиты TLINK
(сгенерированы оверлеи и включен оверлейный менеджер)
Это предупреждение выводится, если оверлеи создаются, но
идентификатор __OVRTRAP__ не определен ни в одном из объектных
модулей или компонуемых библиотек. Этот идентификатор определяется стандартной оверлейной библиотекой OVERLAY.LIB.
Overlays only supported in medium, large and huge memory models
Сообщение об ошибке этапа компиляции
(оверлеи допустимы только для моделей памяти medium, large и
huge)
Оверлеи допустимы только в программах с моделями памяти medium, large и huge).
Overloadable operator expected
Сообщение об ошибке этапа компиляции
(ожидается переопределяемая операция)
Почти все операции С++ могут быть переопределены. Единственными исключениями являются операции выбора поля (.), точка со
звездочкой (.*), двойное двоеточие (::) и условное выражение
(?:). Операции препроцессора # и ## не являются операциями языка
С или С++ и потому переопределяться не могут. Прочие знаки пунктуации, не входящие в число операций, например, точка с запятой,
разумеется, также не могут быть переопределены.
Overloaded имя_функции ambiguous in this context
Сообщение об ошибке этапа компиляции
(имя переопределяемой функции в данном контексте неоднозначно)
Единственный случай, когда имя переопределенной функции может использоваться без фактического вызова, это инициализация или
присваивание переменной или параметра соответствующего типа. В
данном случае переопределяемое имя функции используется в каком-то другом контексте.
Overloaded prefix 'operator операция' used as a postfix operator
Предупреждение этапа компиляции
(переопределенный префикс 'operator операция' используется
как постфиксная операция)
В последней спецификации С++ теперь можно переопределить
префиксную и постфиксную версию операций ++ и --. Чтобы можно было компилировать старый код, когда переопределенной является
только префиксная операция, но она используется в постфиксном
контексте, Borland C++ использует префиксную операцию и выводит
данное предупреждение.
Назад | Содержание | Вперед
Объект TWindow
Все интерфейсные объекты 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
предусматривает общие диалоговые блоки, позволяющие пользователям
выбирать имена файлов, шрифты, цвета и т.д.
Объекты Doc/View
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.
TApplication содержит обычно несколько функций-элементов и
элементов данных, которые может потребоваться вызывать вне объектов приложений. Чтобы вы могли к ним обращаться, класс TWindow имеет функцию-элемент GetApplication, возвращающую указатель на объект приложения. Затем вы можете использовать этот указатель для вызова функций-элементов TApplication и доступа к элементам
данных этого класса.
Минимальное приложение ObjectWindows имеет следующий вид:
#include <owl\applicat.h>
int
OwlMain(int argc, char* argv[])
{
return TApplication("ObjectWindows!").Run();
}
Оно создает приложение Windows, основное окно которого будет
иметь заголовок "ObjectWindows!". Вы можете изменять размеры этого окна или закрыть его. В реальном приложении создается новый
производный класс приложения с большими функциональными возможностями.
Объекты принтера
В данной главе описываются классы 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 или huge
Только что были рассмотрены случаи, в которых может понадобиться объявить функцию с другой моделью памяти, нежели остальная
часть программы. Зачем то же самое может понадобиться для указателей? По тем же причинам, что и для функций: либо для улучшения
характеристик быстродействия (объявив __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, аналогичные описанным выше командам.
Обработка данных WinSpector
Утилита 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
Обычно события Doc/View обрабатываются через объект приложения и интерфейсный элемент вашего отображаемого элемента. Вы можете управлять выводом на экран отображаемого элемента через указатель или смешивать функциональные возможности интерфейсного
объекта с классом отображаемого элемента.
Обработка событий TDocManager
Если при построении объекта 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
Обрабатывать сообщения управляющих элементов 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). Ошибки несоответствия типов следует подавлять в
исключительных случаях ( так как часто это может дать в результате
некорректный код).
Non-portable conversion
(Не переносимое преобразование)
Вы приводите указатель или описатель ближнего типа к 32-битовому значению, такому как LRESULT, LPARAM, LONG или DWORD. Это
предупреждение практически всегда указывает на ошибку, так как
старшие 16 бит значения будут содержать ненулевое значение. Помещая в старшие 16 бит значение текущего сегмента данных, компилятор сначала конвертирует 16-битовый ближний указатель к 32-битовому дальнему указателю.
Чтобы избежать этого предупреждения и обеспечить размещение
в старших 16 битах 0, нужно привести тип описателя к UINT:
HWND hwnd;
LRESULT result = (LRESULT)(UINT)hwnd;
В тех случаях, когда вы хотите, чтобы 32-битовое значение
содержало указатель FAR, можно избежать предупреждения путем явного приведения типа к дальнему указателю:
char near* pch;
LPARAM lparam = (LPARAM)(LPSTR)pch;
Not an allowed type
(Не является допустимым типом)
Это сообщение об ошибке обычно выводится в результате попытки разыменования указателя void. Обычно это бывает при непосредственном использовании значения-указателя, возвращаемого GlobalLock или LocalLock. Чтобы решить данную проблему, перед использованием указателя присвойте возвращаемое значение переменной соответствующего типа (используя при необходимости приведение типа).
Size of the type is unknown or zero
(Размер типа неизвестен или равен нулю)
Вы пытаетесь с помощью + или += изменить значение пустого
указателя. Это ошибка обычно появляется в результате того, что
отдельные функции Windows (например, GlobalLock или LocalLock)
возвращающие указатели произвольных типов, определены для возврата void FAR* вместо LPSTR. Чтобы решить эту проблему, присвойте
значение void* описанной соответствующим образом переменной (приведя при необходимости тип):
BYTE FAR* lpb = (BYTE FAR*)GlobalLock(h);
lpb += sizeof(DWORD);
Type mismatch in redeclaration of имя_параметра
(Несовпадение типа при повторном описании параметра)
В вашей программе имеется несогласованное описание переменной, параметра или функции. Используя API Win32, вы можете внести
в свой исходный код изменения, которые сделают программу более
переносимой.
Обзор и важные концепции
Библиотека классов 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
Окна Class Inspector
Эти окна позволяют вам вывести детальную информацию по классам С++. Чтобы открыть это окно, выведите окно 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 показывает для подсвеченного класса все функции-элементы или элементы данных, включая наследуемые. В противном случае выводятся только элементы данного класса. |
Окна Inspector
Выводят текущее содержимое выбранной переменной. Его можно
открыть с помощью команды Data Inspect или Inspect меню SpeedMenu. Закрывается оно обычно по Esc или щелчком "мышью" на блоке
закрытия. При последовательном открытии нескольких окон Inspector
нажатием Alt+F3 или командой Window Close вы можете закрыть сразу
все эти окна. Окна Inspector выводят простые скалярные величины,
указатели, массивы, объединения, структуры, классы и объекты. Выбором команды Inspect в этом окне вы можете создать дополнительные окна Inspector.
Окна 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 для структур и объединений показывают значения элементов в сложных объектах данных. Такое окно имеет две области. В верхней области выводится адрес объекта данных с перечислением имен и значений элементов данных объекта. Нижняя область содержит одну строку. Если вы в верхней области подсветите
адрес объекта данных, в нижне выводится тип объекта и его имя. В
противном случае там показывается тип элемента данных, подсвеченного в верхней области.
[*] Inspecting letterinfo[n] 3 [^][v]
$7937:0852 ^
count 2 (Ox2)
firstletter 2 (Ox2)
< >v
struct linfo
Область Inspector для массива показывает значения элементов
массива (каждому элементу соответствует строка). Слева выводится
индекс, справа - значение. Если значением является составной объект, Turbo Debugger выводит максимум данных объекта.
[*] Inspecting letterinfo 3 [^][v]
$7682:0852 ^
[0] {2,2}
[1] {2,0}
[2] {2,0}
[3] {1,1}
[4] {1,0}
< >
struct linfo [26]
Окно Inspector для функции показывает адрес функции, ее аргументы, а также возвращаемый функцией тип (в нижней области) и
соглашения по вызову.
[*] Inspecting analyzewords 3 [^][v]
071E9:02DD
char *bufp
< >
long ()
Окна MDI
Окна многодокументального интерфейса или окна MDI являются
частью интерфейса MDI, используемого для управления несколькими
окнами или отображаемыми элементами, связанными с одним приложением. Документ обычно предусматривает работу с файлами, например
редактирование файла или работу с файлом электронной таблицы.
Окна меню View
Меню View является точкой входа в большинство окон Turbo Debugger. Перечислим их кратко. С помощью команды View Another вы
можете дублировать на экране окна Dump, File и Module.
Окна Object Inspector
Это окно используется для просмотра структуры и значений
конкретного экземпляра класса. Чтобы открыть данное окно, поместите курсор на конкретный экземпляр класса (в окне 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.
Чтобы окно реквизитов выполняло полезные функции, оно должно
содержать некоторые реквизиты. Чтобы поместить реквизит в окно,
используйте функцию Insert, в параметрах которой задаются ссылка
на включаемый в окно реквизит, расположение реквизита относительно соседних реквизитов и указатель на братский реквизит.
Если окно реквизитов уже создано, вам нужно после вызова Insert вызвать LayoutSession. Реквизит появится в окне после задания его схемы (LayoutSession).
Чтобы удалить из окна реквизит, используйте функцию Remove.
Сам объект реквизита она не удаляет. Чтобы реквизит исчез из окна, нужно вызвать LayoutSession.
Изменить поля и схемы окна можно перед его выводом или после. Для этого используйте функции SetMargins и SetDirection. Обе
эти функции устанавливают соответствующие элементы данных, а затем вызывают функцию LayoutSession. Направление вывода реквизитов
определяется с помощью функции GetDirection.
По умолчанию функция LayoutSession проверяет создание интерфейсного элемента. Если нет, то функция не выполняет никаких
действий. Если элемент окна уже создан, то LayoutSession выводит
реквизиты без перекрытия и запрещает модифицированной область.
Сеанс задания схемы обычно начинается изменением полей, вставкой
или удалением реквизитов или изменением окна реквизитов.
TileGadget определяет необходимое каждому реквизиту пространство и поочередно их размещает. TileGadget вызывает функцию
PositionGadget. Это позволяет производным классам настраивать интервалы между реквизитами, что помогает реализовать специальную
схему расположения.
Если реквизит изменяет размер, он должен вызывать для окна
реквизитов функцию GedgetChangedSize со ссылкой на реквизит с измененным размером. Заданная по умолчанию версия этой функции
просто инициализирует сеанс задания схемы.
С помощью функции SetShrinkWrap вы можете задать автоматическую настройку размера окна реквизитов. Автоматическую настройку горизонтального и вертикального размера определяют параметры shrinkWrapWidth и shrinkWrapHeight.
Определить текущий шрифт и его размер можно с помощью функций GetFont и GetFontHeight.
При нажатии в ограничивающем прямоугольнике левой кнопки
"мыши" реквизит всегда получает уведомление. После нажатия кнопки, если вы хотите посылать уведомления о перемещении "мыши", вам
нужно перехватить нажатие кнопки. Это можно сделать с помощью
функций GedgetSetCapture и GadgetReleaseCapture. Эти функции
обычно вызываются реквизитом через указатель на окно реквизитов.
Режим подсказки реквизита указывает, будет ли выводиться в
родительском окне окна реквизитов информация о реквизите. Этот
режим устанавливается с помощью функции SetHintMode, параметр которой может иметь значения NoHints (подсказка не выводится),
PressHints (подсказка выводится при нажатии реквизита) и EnterHints (подсказка выводится при перемещении "мыши" на реквизит).
Определить текущий режим можно с помощью функции GetHintMode.
Вывод подсказки определяет функция SetHintCommand. Обычно
она вызывается реквизитом через указатель на окно реквизитов.
Чтобы эта функция правильно работала со стандартными классами ObjectWindows, нужно чтобы:
декорированное окно-рамка (родительское окно окна реквизитов) имело строку сообщений или строку состояния;
в окне-рамке должна быть разрешена подсказка;
должен существовать строковый ресурс с тем же идентификатором, что и реквизит.
Для поиска содержащихся в окне реквизитов вы можете использовать функции FirstGadget, NextGadget, GadgetFromPoint, GadgetWidthId.
Окна схемы
Окна схемы (разметки) инкапсулируют класс 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 можно задать ограничение высоты
или ширины окна:
lmWidth задает, что ограничением должна быть ширина окна.
lmHeight задает, что ограничением должна быть высота окна.
rel задает соотношение между краями окна (lmAsis, lmPersentOf, lmAbove, lmLeftOf, lmBelow, lmRightOf, lmSameAs, lmAbsolute).
otherWin задает окно, содержащее ваше дочернее окно. Для
спецификации родительского окна используется lmParent.
otherEdge задает конкретный край otherWin, с помощью которого вы ограничиваете свое дочернее окно (допускаются те же значение, что и для edge).
value имеет разный смысл в зависимости от значения rel и
Units.
TEdgeConstraint содержит также ряд функций, которые вы можете использовать для задания предопределенных соотношений, тесно
связанных с теми, которые задаются в Set.
Для задания схемы окна недостаточно одного ограничения расположения. Например, указание того, что окно должно находиться на
10 элементов изображения ниже другого окна ничего не говорит о
высоте и ширине окна, расположении его левого или правого края
или нижней границы. Комбинация ограничений схемы расположения может полностью определить расположение окна. TLayoutMetrics использует 4 ограничения расположения: два объекта TEdgeConstraint
(X и Y), TEdgeOrWidthConstraint (Width) и TEdgeOrHeightConstraint
(Height).
TLayoutMetrics - достаточно простой класс. Его конструктор
не имеет параметров и только устанавливает элемент каждого ограничения. Для каждого ограничения схемы ограничивающее окно обнуляется, соотношение устанавливается в lmAsIs, единицы устанавливаются в lmLayoutUnits, а значение - в 0.
После построения объекта TLayoutMetrics вам нужно задать ограничения схемы нужного окна. Для установки каждого ограничения
можно использовать соответствующую функцию.
Чтобы лучше понять, как совместно работают ограничения, выполните пример приложения LAYOUT из каталога примеров программ.
Его диалоговое окно позволяет изменить ограничения каждого из
окон и увидеть результаты. Однако ограничения нужно описывать
полностью. Неполное описание может приводить к аварийному завершению.
Окна Turbo Debugger
Для вывода информации об отлаживаемой программе в 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
Используется для установки, модификации или удаления точек
останова. Точка останова определяет то место в программе, где отладчик приостанавливает выполнение программы. Это окно имеет две
области. Справа перечислены условия и действия точек останова,
слева - все точки останова.
Окно Breakpoints
Создать окно точек останова Breakpoints можно с помощью команды View Breakpoints основного меню. Это дает вам способ выбора
и установки условий, при которых срабатывает точка останова. Это
окно можно использовать для добавления новых точек останова, отмены (удаления) точек останова и изменения существующих точек останова.
[*] Breakpoints 3 [^][v]
TCDEMO.220 Breakpoint
TCDEMO.225 Always
TCDEMO.226 Enabled
< >
В левой области этого окна показан список всех адресов, где
установлены точки останова. В правой области показаны подробные
данные по текущим (подсвеченным в левой области) точкам останова.
Локальное меню SpeedMenu окна Breakpoints можно получить по
нажатию клавиш Alt+F10. Команды данного меню позволяют вам добавлять новые точки останова, отменять существующие или изменять характер поведения имеющихся точек останова.
Окно Clipboard
Буфер Clipboard отладчика используется для для вырезания и
вставки элементов из одного окна отладчика в другое. Оно показывает вырезанные элементы и их типы. Скопированные в буфер элементы динамически обновляются.
Окно CPU
Выводит текущее состояние процессора. Окно имеет 6 областей,
где выводятся дизассемблированные инструкции, селекторы Windows
(только в TDW), шестнадцатиричные данные, стек в шестнадцатиричном виде, регистры ЦП и флаги процессора. Это окно полезно использовать при отладке программ на ассемблере или просмотре точно последовательности инструкций.
Окно CPU
Это окно открывается командой 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 выводится автоматически.
Окно Dump
Выводит в шестнадцатиричном виде содержимое любой области
памяти (аналогично области окна CPU). Команды SpeeMenu этого окна
позволяют вам модифицировать данные и работать с блоками памяти.
Окно Dump
В этом окне выводится в непосредственном виде дамп любой области памяти. Оно работает так же, как область данных окна 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.
Окно Execution History
Выводит последние выполненные машинные инструкции или исходные строки программы, номер строки исходного кода и следующую выполняемую инструкцию или строку кода. Используется для обратного
выполнения.
Окно File
Выводит содержимое любого файла на диске. В нем можно просматривать шестнадцатиричные байты или текст ASCII и искать нужные
байтовые последовательности.
Окно Hierarchy
Выводит на экран дерево иерархии всех используемых текущим
модулем классов. Имеет область списка классов и дерева иерархии.
Это окно показывает взаимосвязь используемых в модуле классов.
Окно Hierarchy
Окно 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
< >
Окно Log
Выводит содержимое журнала сообщений с прокручиваемым списком сообщений и информацией, сгенерированной при работе с отладчиком. Это окно можно также использовать для получения информации
об использовании памяти, модулях и оконных сообщения приложения
Windows.
Окно Log
Это окно отслеживает события, происходящие во время сеанса
отладки. Открывается оно по команде 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. Позволяет вывести информацию о динамически распределяемой памяти и список модуля приложения. |
Окно Module
Одно из важнейших окон Turbo Debugger, показывающее исходный
код отлаживаемого программного модуля (включая DLL). Модуль должен компилироваться с отладочной информацией.
Окно Numeric Processor
Показывает текущее состояние сопроцессора и имеет три области: содержимого регистров с плавающей точкой, значений флагов
состояния и значений управляющего флага. Это позволяет вам диагностировать проблемы в использующих сопроцессор подпрограммах.
См. файл TD_ASM.TXT.
Окно Registers
Показывает содержимое регистров (в области регистров) и флагов ЦП (в области флагов). С помощью команд SpeedMenu вы можете
изменить их значения.
Окно Registers
В окне Registers выводится содержимое регистров и флагов
центрального процессора. оно работает, как сочетание областей регистров и флагов в окне CPU и имеет те же команды.
Назад | Содержание | Вперед
Окно сообщений
При компиляции программ в окне сообщений выводятся ошибки и
предупреждения. С помощью команды Preferences в диалоговом окне
Enviroment Options вы можете настроить некоторые функциональные
возможности окон сообщений Message.
При выборе сообщения в окне Message редактор помещает курсор
в ту точку исходного кода, где произошла ошибка или предупреждение. Если файл с ошибкой не загружен в окне редактора, для его
загрузки нажмите пробел (можно воспользоваться и SpeedMenu). Окно
сообщений остается выбранным, так что вы можете перемещаться от
сообщения к сообщению. С помощью команды Remove all messages оперативного меню вы можете очистить окно сообщения. Клавиши Alt+F7
выводят следующее сообщение об ошибке, а Alt+F8 - предыдущее.
Окно Stack
Показывает текущее состояние программного стека. Первая вызванная функция показывается в нижней части окна, а выше ее - каждая последующая. Подсвечивая эти функции и нажимая Ctrl+I вы можете проверять исходный код. Кроме того, можно открыть окно Variables и вывести все локальные переменные и аргументы функции (Ctrl+L).
Окно Stack
Это окно позволяет проанализировать стек вызова и вывести в
удобном для чтения формате все активные функции и значения аргументов. Окно 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 с идентификаторами, локальными для текущего модуля и
подсвеченной функции.
Окно Variables
Выводит все переменные в данном контексте программы. В верхней области окна перечисляются глобальные переменные, а в нижней
- локальные. Это полезно использовать для поиска функции или
идентификатора, имени которых вы точно не помните.
Окно 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 | Смена текущего модуля. Выводит диалоговое окно со
списком модулей программы. |
Окно Watches
Показывает значения переменных и выражений. Введя в это окно
выражения, вы можете отслеживать их значения при выполнении программы. Окно добавляется с помощью клавиш Ctrl+W при установке курсора на переменной в окне Module.
Окно Watches
Это окно обеспечивает самый простой способ отслеживания элементов данных программы. В нем вы можете просматривать переменные
и выражения, значения которых нужно отслеживать.
[*] 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 Messages
Показывает список оконных сообщений программы 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. Например,
корректными именами классов сегментов являются 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 определяет стандартные атрибуты сегментов данных и имеет синтаксис:
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 обычно используется для вставки автора, даты
или информации о копировании. Оно является необязательным параметром. Оператор имеет синтаксис:
DESCRIPTION 'текст'
где "текст" является строкой ASCII, разделенной одинарными кавычками.
Оператор EXETYPE
EXETYPE задает стандартный тип заголовка (Windows или OS/2)
выполняемого файла (.EXE) для 16-разрядных приложений. В 32-разрядных приложениях для обратной совместимости этот оператор можно
сохранить. В данной версии Borland C++ можно задавать только значение WINDOWS. Оператор имеет синтаксис:
EXETYPE WINDOWS