Учебник по Delphi 4

         

ProcessMessages



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

    while not Application.Terminated do

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

    while not Application.Terminated do


    Application.ProcessMessages;


 

Совет: Программисты часто предпочитают использовать для длительных вычислений отдельную подзадачу, реализуемую классом TThread.


 



Просмотр значений переменных



    При пошаговом прохождении программы в отладчике вы, несомненно, захотите узнать, что содержится в различных переменных. Для этого можете использовать окно просмотра переменных Watch List, которое предоставляет возможность пассивно просматривать содержимое одной или нескольких переменных, или диалоговое окно Evaluate/Modify, позволяющее работать только с одной переменной (в нем можно не только просмотреть, но и изменить ее содержимое).


    Для просмотра значения переменной используйте команду Run/AddWatch или установите указатель мыши на переменную в окне редактирования, щелкните правой кнопкой мыши и выберите из контекстного меню команду Add Watch at Cursor. После этого появится диалоговое окно Watch Properties, показанное на рис. 2.12. Введите имя переменной в поле Expression (если оно не появилось там автоматически). Обратите внимание на то, что вы можете просматривать значения не только переменных, но и выражений типа х*(y+z). Единственное ограничение— выражение не может содержать вызовов функций, поскольку это может вызвать побочный эффект, связанный с незапланированным вызовом функции, описанный выше, в подразделе ''Использование директивы Assert". Допускается также просмотр значений записей, массивов и других структурированных элементов.


    Поле Repeat Count используется в том случае, если у вас есть большой массив, и вы хотите просмотреть его часть. Предположим, что вам надо знать значения элементов 826-833 следующего массива

    var


        BigArray: array[1..1000] of Integer;

    Вы не можете просмотреть массив BigArray, так как 1 000 элементов просто не поместятся в окне (да и пролистать ненужные вам 825 элементов — работенка немалая!) Вместо этого вы просите показать вам значение BigArray [826] и устанавливаете параметр Repeat Count равным 8. При этом вам будут показаны значения восьми элементов массива— от 826 по 833.


    Использование поля Digits позволяет определить количество значащих цифр при выводе числа с плавающей точкой.



    Отключенная опция Enabled предотвращает вывод значения переменной, однако,



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

    В диалоговом окне имеется также набор переключателей для выбора способа представления переменной. Значение Default позволяет среде разобраться с типом переменной самостоятельно. Как правило, такое решение оптимально, однако в любой момент вы можете представить переменную как переменную того типа, который вас интересует. Опция Memory dump представляет информацию как набор байтов, что бывает полезно, когда необходимо увидеть внутреннее представление информации в переменной.

На рис 2.13 отображены значения нескольких переменных в окне Watch List. Кроме того, в некоторых случаях отладчик выводит информацию о причинах, по которым содержимое переменной недоступно.

 

 


Рис. 2.12. Использование диалогового окна Watch Properties для добавления или изменения набора переменных в окне просмотра.



Рис. 2.13. Просмотр переменных.

    Смысл приведенных сообщений поясняется ниже

Variable 'X' inaccessible here due to optimization(Переменная 'X' недоступна из-за оптимизации). В этой точке значение переменной просмотреть невозможно (иногда это можно сделать в другом месте программы), так как для нее не выделена память из-за оптимизации программы компилятором.

Symbol was eliminated by linker (Переменная удалена компоновщиком). Переменная удалена из кода программы компоновщиком, так как на нее нет ни одной ссылки в тексте программы.

    Отладчик также выводит сообщение об ошибке, если имя переменной написано неправильно, например вы запросили значение Foo [5], в то время как переменная Foo массивом не является.

Совет: Когда вы пытаетесь просмотреть свойства объекта, выводимые значения могут оказаться бессмысленными. Многие свойства объектов, выглядящие как переменные, на самом деле являются вызовами функций. Отладчик не вызывает функции для определения значений, а потому корректные значения при таком просмотре вы получить не можете. Выход — в объявлении новых переменных, присвоении им значений свойств и просмотре не свойств, а новых переменных. Неприятности могут начаться из-за слишком умного оптимизатора, который сообразит, что, раз в программе значение переменной больше не используется, ее можно выбросить без ущерба для программы (увы, но не для отладки программы!) Если это происходит, используйте глобальные переменные, т.е. переменные, объявленные вне функции или процедуры. Отладчик всегда корректно отобразит значения глобальных переменных.


Qualifying_types


Указательные типы

    Переменная указательного типа содержит значение, указывающее на переменную обычного типа — адрес этой переменной (табл. 1.8).

    pointer   // Указатель без типа.
    ^typel    // Указатель с типом.

    Если исходный тип (тип переменной, на которую должен ссылаться указатель) еще не объявлен, его надо объявить в том же разделе объявления типов, что и тип указателя.
    Только исходный тип указателей может совпадать с собственно типом.

Таблица 1.8. Средства работы с указателями

Средство Описание
New  Распределяет новый участок динамической памяти и записывает его адрес в переменную указательного типа
Оператор @  Направляет переменную-указатель на область памяти, содержащую любую существующую переменную, процедуру или функцию, включая переменные, имеющие идентификаторы
GetMem Создает новую динамическую переменную заданного объема и записывает ее адрес в переменную указательного типа

  Указатели и адресные функции


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

Функция Описание
Addr  Возвращает адрес указанного объекта
Assigned Проверяет, равно ли значение процедурной функции Nil
Ptr Преобразует адрес в указатель

    Зарезервированное слово Nil указывает значение указателя, который ни на что не указывает. Такие указатели называют неопределенными. В Object Pascal только при определении указателей можно нарушать правило, по которому все указываемые идентификаторы, в том числе идентификаторы типов, должны быть объявлены выше. Здесь можно указать идентификатор еще необъявленного типа, как в следующем примере:

    type
        PointerType = ^NotYetDefinedType;

    Однако необъявленный тип необходимо объявить ниже в том же блоке объявления типов.
    Определенный в Object Pascal тип Pointer— это указатель без типа. Обратиться к переменной через такой указатель невозможно (к переменной типа Pointer нельзя дописывать символ "^"). Однако можно задать ей другой указательный тип.
    По значениям переменных тип Pointer совместим с остальными указательными типами.


Совет: Во многих языках указательные типы как таковые отсутствуют. Однако в С и C++ они есть и определяются звездочкой перед типом объявляемой переменной. Указатели в C/C++ трактуются наподобие целых переменных. программисты Delphi избегают подобного манипулирования указателями.



Разделяемое хранилище



    Вам может не понравиться то, что ваши шаблоны содержатся в хранилище Delphi. Предположим, что вы де инсталлируете Delphi (при этом, чтобы сохранить свои шаблоны, вы будете вынуждены вручную сохранять их в другом месте, а потом вновь добавлять их в очередное хранилище). Или, например, вы работаете в сетевом окружении и хотите поделиться своими формами с другими программистами. Обе эти проблемы позволяет решить концепция разделяемого хранилища.
    Разделяемое хранилище (shared repository) представляет собой папку с двумя файлами, используемыми для хранения информации о расположении шаблонов. Вы можете определить расположение разделяемого хранилища, выполнив следующие действия.
 

Выберите команду Tools/Options, и на экран будет выведено диалоговое окно Environment Options, показанное на рис. 1.8.

Щелкните на вкладке Preferences вверху диалогового окна.

В поле ввода Directory введите путь к папке, которую вы хотите использовать в качестве разделяемого хранилища.

Щелкните на ОК. Теперь при выводе диалогового окна New Items Delphi будет просматривать эту папку в поисках шаблонов.

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



Разделяемые обработчики событий



Как вы уже знаете, каждый класс способен генерировать свои собственные события. Каждое из них имеет определенный тип, как, например, TNotifyEvent у OnClick и TCloseEvent у OnClose. Delphi позволяет написать один обработчик события и назначить его нескольким событиям одновременно.


    Представьте себе объект TEdit, генерирующий события OnKeyDown и OnKeyUp. Поскольку оба события — одного типа, можете написать одну процедуру и назначить ее обоим событиям. Процедура будет вызываться дважды при каждом нажатии клавиши (при нажатии и отпускании). Или, например, вы можете создать один обработчик для событий OnCreate и OnClick.


    Еще одно общее назначение разделяемых обработчиков — обработка событий от двух различных управляющих элементов, которые могут и не быть экземплярами одного класса.


    Вот как создать разделяемый между классами TButton и TEdit обработчик OnClick.

Выберите из меню File/New Application для создания приложения.

Поместите TButton в форму и введите в обработчик OnClick следующий код.

        procedure TFormI.ButtonlClick (Sender: TObject);
        begin
            Editl.SetFocus;
            Editl.SelectAll;
        end;

Поместите TEdit в форму. В Object Inspector выберите в списке для события OnClick обработчик ButtonClick.

    Теперь после щелчка на кнопке и на объекте TEdit будут выполняться одни и те же действия,

фокус ввода будет передаваться управляющему элементу TEdit,

и весь текст в нем будет выделяться.



Размещение компонентов



Размещать компоненты на форме очень просто. Требуется только щелкнуть на нужной вкладке палитры компонентов, затем на кнопке с пиктограммой соответствующего компонента и после этого щелкнуть в окне формы. Все! Или, если вам так больше нравится, можно щелкнуть на компоненте, а затем нарисовать прямоугольник с помощью мыши на форме — компонент появится внутри этого прямоугольника. Если размеры компонента поддаются изменению, при появлении на форме он заполнит собой прямоугольник.
    Если вы забыли, на какой странице расположен конкретный компонент, выберите пункт Component List (Компоненты) из меню View (Вид), и на экране появится список компонентов в алфавитном порядке.
Если щелкнуть на компоненте в палитре компонентов, его кнопка окажется нажатой. Если щелкнуть на другом компоненте, первая кнопка вернется в исходное состояние — только один компонент может быть выбран в один момент времени. Для того чтобы все кнопки оказались в исходном состоянии и было восстановлено нормальное использование мыши, следует щелкнуть на кнопке со стрелкой выбора, которая появляется с левой стороны каждой страницы палитры (рис. 4.1).  

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

 

Выберите страницу Standard палитры компонентов.

Поместите указатель мыши на компонент с изображением кнопки ОК. После того как мышь побудет в недвижимом состоянии секунду или две, появится поле помощи, идентифицирующее этот компонент как Button (см. рис. 4.1).

Щелкните на кнопке, затем щелкните на вашей форме. Появится кнопка среднего размера, озаглавленная Button 1.

 Щелкните на компоненте Button опять, но на этот раз, удерживая ле-вую кнопку мыши, нарисуйте прямоугольник большого размера прямо на форме. Текст Button2 заполнит прямоугольник. Обратите внимание, что кнопка имеет небольшие квадратные маркеры (угловые и боковые), позволяющие изменять размер. Используйте их, чтобы с помощью мыши изменить размер кнопки.


Теперь щелкните на кнопке Button 1 и перетащите ее в новое место.

    Вы заметите, что при перемещении и изменении размера компоненты выравниваются по точкам координатной сетки формы. Как правило, это хорошо — такая возможность помогает поддерживать порядок в формах. Если вы захотите отменить эту возможность или изменить плотность точек координатной сетки, выберите пункт Options из меню Tools. Первая страница параметров предназначена для настройки пользователем параметров среды. На этой странице имеется группа Form designer (Конструктор форм), флажки опций Display grid (Отображение сетки) и Snap to grid (Привязка к сетке) которой определяют, видна ли координатная сетка и активна ли она. Можно также изменить значения параметров Grid Size X (Шаг по оси X) и Grid Size Y (Шаг по оси Y), что приведет к изменению шага координатной сетки по горизонтали и вертикали, соответственно.

Совет: Для лучшего управления размещением и размерами своих компонентов попробуйте следующее. Установите значение шага координатной сетки равным 4 вместо 8, отключите изображение координатной сетки, но оставьте включенным параметр Snap To grid.


Редактор библиотек типов



Редактор библиотек типов Delphi используется для просмотра и редактирования библиотек типов. Основой интерфейса редактора является панель Object List (рис. 3.1), с помощью которой пользователь может изменять, добавлять и удалять элементы библиотеки типов. Элементами библиотек типов являются составные классы, свойства и методы интерфейсов и перечисления. Панель Object List представляет элементы в виде дерева объектов. В зависимости от типа элемента, выбранного в панели Object List, в правой части редактора библиотек типов появляются различные вкладки. Возможно, это будут вкладки Attributes, Members и Uses.
    Для редактирования библиотеки типов текущего проекта выполните команду View/Type Library. Чтобы просмотреть библиотеку типов, не являющуюся частью проекта, выберите пункт меню File/Open. После этого в списка File of type выберите строку Type Library (*.tlb;*.dll;*.ocx;*.exe;*.olb), чтобы вывести все файлы, которые могут содержать информацию о типах.
    Теперь более детально рассмотрим каждый элемент библиотеки типов. Начнем с информации о библиотеке.



Regestry_ActiveX


Регистрация и установка элемента управления ActiveX

    Для регистрации элемента управления ActiveX нужно просто воспользоваться какой-либо утилитой или приложением, которое вызывает экспортируемую элементом ActiveX функцию DllRegiaterServer. Эта функция знает, как внести в реестр Windows записи об элементах ActiveX, данные о фабриках объектов которых зарегистрированы в глобальном объекте сервера СОМ среды программирования Delphi. Нами рассмотрена только одна фабрика объектов (TActiveXControlFactory), но для каждой страницы свойств существует своя фабрика объектов.
    Чтобы зарегистрировать элемент управления ActiveX, воспользуйтесь командой Run/Register ActiveX Server. 

Чтобы проверить созданный элемент ActiveX в действии, установите его в среде Delphi. Для этого выберите команду Component/lnstall ActiveX control, и на экране появится диалоговое окно Import ActiveX  (рис. 3.10).
    Если в списке зарегистрированных элементов управления нет библиотеки PieXControlLib, то следует щелкнуть на кнопке New и добавить в список файл PieXControl.dll. После щелчка на кнопке OK Delphi автоматически вызовет функцию DllRegisterServer, и элемент управления появится в списке зарегистрированных элементов управления. Выберите созданный элемент в списке и щелкните на кнопке Add to package. Здесь есть две возможности: создать новый модуль-оболочку для элемента ActiveX и вставить созданный элемент в уже существующий модуль. Я бы посоветовал вставить созданный элемент в модуль PieLib. dpk, после чего нужно только перекомпилировать модуль, так как он уже установлен.  

Рис. 3.10. Диалоговое окно Import ActiveX

 После выполнения описанных выше действии на вкладке ActiveX в палитре компонентов Delphi появится элемент управления PieX. Вот и все о создании, регистрации и установке элементов управления ActiveX в среде программирования Delphi 4. В других средах программирования регистрация и установка элементов ActiveX реализованы иначе, поэтому обратитесь к руководству по продукту для получения подробных инструкции.



Шаблоны форм



Шаблоны форм (Form Templates) предоставляют основу для новой формы. По одной заготовке можно создать несколько форм. В Delphi есть хранилище объектов (Object Repository), в котором содержится множество различных шаблонов форм, диалогов и проектов.



ShowMessage



    Кроме вывода информации в форму, можно воспользоваться модальным диалоговым окном. Принципиальное отличие этого метода, в первую очередь, состоит в том, что модальное диалоговое окно останавливает выполнение программы, пока вы его не закроете. Таким образом, у вас имеется достаточно времени, чтобы прочесть и осмыслить полученную информацию.


    Процедура ShowMessage (из модуля Dialogs) идеально подходит для этой цели Она позволяет вывести строку любой длины в простом модальном диалоговом окне. Вам только следует создать строку для вывода и передать ее процедуре (можно также использовать MessageDIg, но в нем слишком много шашечек и бантиков, которые требуют немалых усилий для достижения того же эффекта).


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


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


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

    procedure TFormI.ButtonlClick(Sender: TObject);


    var MemStat: TMemoryStatus;


    begin


        MemStat.dwLength:= SizeOf(TMemoryStatus);


        GlobalMemoryStatus(MemStat);


        with MemStat do ShowMessage(Format('Memory load: %d%%'#13 +


            'Total physical: %d'#13+'Available physical: %d'#13 +


            'Total page file: %d'#13 + 'Available page file: %d'ftl3 +


            'Total virtual: %d'#13 + 'Available virtual: %d',



            [dwMemoryLoad, dwTotalPhys, dwAvailPhys, dwTotalPageFile,

            dwAvailPageFile, dwTotalVirtual, dwAvailVirtual]));

    end;

    Заметьте, что я внес в строку несколько символов #13 (ASCII-символ возврата каретки). Это позволяет разбить строку при выводе на несколько строк, что существенно облегчает чтение информации. На рис 2.23 показано, что получится после запуска программы и щелчка на кнопке.

    Судя по результатам Memory load и Available physical, представленным на рисунке, мне стоит всерьез подумать о наращивании памяти своего компьютера.

 



Рис 2.23 Использование функции ShowMessage для вывода отладочной информации.


Символьные типы



Смысл символьных данных очевиден, когда они выводятся на экран или принтер. Тем не менее, определение символьного типа может зависеть от того, что подразумевать под словом символ. Обычно символьные типы данных задают схему взаимодействия между участками памяти разного объема и некоторым стандартным методом кодирования/декодирования для обмена символьной информацией. В классическом языке Pascal не задано никакой схемы, и в конкретных реализациях применялось то, что на том же компьютере мог использовать каждый.
    В реализациях языка Pascal для первых микропроцессоров была применена 7-битовая схема, названная ASCII (American Standard Code for Information Interchange — Американский стандартный код для обмена информацией). Эта схема и поныне широко распространена, но информация хранится, как правило, в 8-битовых участках памяти. Дополнительный бит удваивает число возможных представлений символов, но реализации расширенного набора символов ASCII часто бывают далеки от стандарта. В данной версии Delphi определен набор 8-битовых символов, известный как расширенный (extended) ANSI (American National Standards Institute — Американский национальный институт стандартов). Как бы то ни было, символьную схему приходится воспринимать так, как ее воспринимает операционная система. Для оконных операционных систем фирмы Microsoft это схема ANSI, включающая ограниченное число предназначенных для вывода международных знаков. В стремлении же применить более обширный набор международных знаков весь компьютерный мир переходит к 16-битовой схеме, именуемой UNICODE, в которой первые 256 знаков совпадают с символами, определенными в схеме ANSI.
    Для совместимости со всеми этими представлениями в Object Pascal определены два физических символьных типа и один логический.
Физические типы перечислены ниже.
  

AnsiChar Однобайтовые символы, упорядоченные в соответствии с расширенным набором символов ANSI
WideChar Символы объемом в слово, упорядоченные в соответствии с международным набором символов UNICODE. Первые 256 символов совпадают с символами ANSI
<
     Символьные типы объемом в двойное слово (32 бит) отсутствуют.
    Логический символьный тип именуется char. В классическом языке Pascal char— единственный символьный тип. В Delphi char всегда соответствует физическому типу данных AnsiChar. У американских программистов ассоциация символа с однобайтовой ячейкой памяти укоренилась за долгие годы настолько, что им зачастую просто не приходит в голову, что можно использовать другие схемы кодирования. Однако дискуссии по интернационализации программ в Internet и World Wide Web могут существенно изменить их отношение к проблеме объема символьных данных. Применяя логический тип char, следует делать реализации для других микропроцессоров и операционных систем, в которых char может определяться как WideChar. При написании программ, которые могут обрабатывать строки любого размера, для указания этого размера рекомендуется применять функцию SizeOf, не задавая ее жестко постоянной. Функция Ord (С), где С — любая переменная символьного типа, возвращает целое значение, которым символ С представлен в памяти.
  
Chr (X) Преобразует целую переменную в переменную типа char с тем же порядковым номером. В Delphi это эквивалентно заданию типа Char (X)
UpCase Преобразует строчную букву в прописную
Совет: Процессор не различает типы char, определенные в C/C++ и Delphi. Однако функционально каждый из этих языков трактует данный тип совершенно по-разному. В C/C++ это целый тип, переменной которого можно присваивать целые значения. Переменной int можно присвоить символьное значение, а переменной char — целое. В Delphi символьные типы жестко отделены от численных. Для присвоения численному значению символьного здесь необходимо воспользоваться функцией Ord. В языке Basic один символ представляется так же, как и строка символов. Функция Chr из Delphi эквивалентна функции CHR$ из Basic. Функция Ord из Delphi, возвращающая код ANSI символьной переменной, подобна функции A3 С из Basic, аргумент которой представляет односимвольную строку.


События TForm



Класс ТForm добавляет несколько событий к родительскому классу TWinControl. Эти события позволяют изменять поведение формы путем выполнения загрузки и сохранения информации о состоянии формы или распределения и освобождения дополнительных ресурсов.


    Когда форма создается и отображается, происходит пять следующих событий.

        1. OnCreate запускается при создании формы и позволяет распределять ресурсы и инициализировать форму.


        2. OnShow происходит непосредственно перед выводом формы на экран. К этому времени все элементы управления и компоненты созданы и инициализированы.

Совет: Хотя к тому моменту, когда происходит событие OnShow, форма еще не видна, свойство Visible установлено равным True.

        3. OnResize генерируется при изменении размера формы во время выполнения приложения. Обычно здесь помещается код для изменения размера и положения на экране элементов управления, не поддерживающих свойство Align. Событие OnResize также однократно генерируется при создании формы, когда Delphi устанавливает начальные размеры формы.

Совет: OnResize вызывается неоднократно в процессе изменения размеров формы.

        4. OnActivate происходит при получении формой фокуса ввода. OnActivate вызывается только при переходе фокуса ввода от одной формы к другой в пределах одного приложения. При переключении между приложениями Delphi генерирует событие OnActivate глобального объекта Application.
        5. OnPaint запускается, когда необходимо перерисовать форму. Это может происходить, когда форма только что стала видимой, при частичном удалении перекрывающих ее элементов или увеличении размеров. Событие полезно, если вы перерисовываете какую-то часть формы самостоятельно.

Совет: Событие OnCreate происходит один раз за все время существования формы, прочие же события могут вызываться неоднократно.



 

     При закрытии и уничтожении формы также генерируется пять следующих событии.
       
1. OnCloseQuery генерируется в ответ на действия, закрывающие форму. Обработчик получает логическую переменную CanClose, определяющую, может ли форма быть закрыта. По умолчанию она имеет значение True, но если вы в обработчике установите False, форма останется открытой. Обычно это используется для сохранения не сохраненных файлов или для подтверждения закрытия формы. Вот пример такого кода.
    procedure TFormI.FormCloseQuery(Sender: TObject;

        var CanClose: Boolean);

    begin

        CanClose:= MessageDIg('Close form?', mtConfirmation,

                            [mbYes,mbNo], 0) = mrYes;

    end;
        2. OnClose генерируется непосредственно перед закрытием формы. Обычно оно используется для изменения стандартного поведения формы при закрытии. Для этого Delphi передает в обработчик события переменную Action, которая может принимать одно из четырех значений: caHide, caMinimize, caNone или caFree. По умолчанию для не MDI-форм используется caHide, скрывающее форму. Для дочерних MDI-форм значение по умолчанию, сворачивающее форму, равно caMinimize. Если Action установлено равным caNone, закрытия не происходит. caFree заставляет Delphi закрыть форму и освободить всю связанную с ней память. Если после этого сослаться на объект формы, произойдет исключительная ситуация.
Совет: OnClose вызывается только при закрытии формы с помощью щелчка на кнопке закрытия или вызова функции Close. Если вы закрываете главную форму приложения, все другие открытые формы закрываются без вызова события OnClose. Событие OnCloseQuery вызывается всегда, независимо от способа закрытия формы.

        3. OnDeActivate происходит при потере формой фокуса ввода. Запуск происходит по тем же правилам, что и запуск события OnActivate.

        4. OnHide запускается непосредственно перед тем, как форма станет невидимой.
Совет: Хотя при вызове OnHide форма еще видна, ее свойство Visible установлено равным False.

        5. OnDestroy генерируется непосредственно перед уничтожением формы. Обычно оно используется для освобождения ресурсов, выделенных в OnCreate.
Совет: Событие OnDestroy вызывается только один раз за все время существования формы, прочие события могут вызываться неоднократно.

События TScreen



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



Составные классы (CoClass) в библиотеках типов



    Составной класс в библиотеке типов (CoClass) представляет весь элемент управления ActiveX, объект автоматизации или специальный объект СОМ. Составной класс включает интерфейсы и диспинтерфейсы, которые предоставляются клиентскому приложению. В следующих двух разделах рассматривается назначение вкладок Attributes и Members редактора библиотек типов в описаниях классов составных объектов.
 



Создание форм



В MDI-приложении, как правило, требуется выводить несколько экземпляров классов формы. Поскольку каждая форма представляет собой объект, она должна быть создана перед использованием и освобождена, когда в ней больше не нуждаются. Delphi может делать это автоматически, а может предоставить эту работу вам


.



Создание интерфейса



    Интерфейс MDI-приложения очень похож на интерфейс разработанного ранее SDI-приложения, но каждое изображение выводится в отдельной, а не в главной форме. Выполните следующие действия для создания родительской формы.

        1. Выберите команду File/New Application, и появится пустое приложение.


        2. Установите следующие свойства.


            Свойство                                           Значение


            Caption                                              Image Viewer
            FormStyle                                          fsMDIForm
            Name                                                frmMDIParent            ShowHint                                            True


        3. Поместите компонент TPanel в форму. Установите следующие его свойства.

            Свойство                                          Значение

            Align                                                    alTop

            Caption                                                -

4. Поместите три компонента TSpeedButton в TPanel и назовите их spbtnLoad, spbtnStretch и spbtnCenter. Установите следующие их свойства.

            Свойство                                          Значение

            spbtnLoad.Hint                                    Load
            spbtnLoad.Left                                    8
            spbtnLoad.Top                                    8
            spbtnStretch.AllowAlIUp                     True
            spbtnStretch.Grouplndex                      1
            spbtnStretch.Hint                                  Stretch
            spbtnStretch.Left                                  48
            spbtnStretch.Top                                  8
            spbtnCenter.AllowAlIUp                      True
            spbtnCenter.Grouplndex                       2
            spbtnCenter.Hint                                   Center




            spbtnCenter.Left                                   80

            spbtnCenter.Top                                   8

    Свойства Glyph установите те же, что и для SDI-приложения.

    5. Добавьте в форму компонент TOpenDialog и установите следующие его свойства.

            Свойство                                            Значение

            Filter                                                     Bitmaps (*.bmp)]*.bmp
            Name                                                    opndlgLoad
            Options                                                 [ofPathMustExist,ofFileMustExist]



Теперь создадим дочернюю форму.

       1. Выберите из меню File/New Form, и появится пустая форма.

       2. Установите следующие ее свойства.

              Свойство                                          Значение

              FormStyle                                            fsMDIChild
              Name                                                  frmMDIChild
              Position                                               poDefaultPosOnly

        3. Поместите компонент TImage во вновь созданную форму и установите его следующие свойства.

               Свойство                                         Значение




                Align                                                  alClient
                Name                                                 imgMain

    Удалите дочернюю форму из списка автоматически создаваемых форм следующим образом.

 

        1. Выберите команду Project/ Options, и появится диалоговое окно Project Options, показанное на рис. 1.14.

        2. Выберите frmMDIChild в списке Auto-create forms.

        3. Щелкните на кнопке. Форма frmMDIChild при этом будет перенесена в список Available forms.
        4. Щелкните на кнопке ОК.

    Теперь самое время сохранить проект, выбрав команду File/Save Project As. Сохраните Unit1 как MDIParent, а проект — как EgMDIApp.


Создание надежного приложения



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

Ваше приложение должно быть хорошо организовано. Разделите программу на модули, каждый из которых выполняет определенные задачи. Например, если код, создающий отчет, разнесен по десяти модулям, время отладки такого кода увеличится даже более чем в десять раз (хотя бы за счет поиска нужной строки в десяти модулях). Конечно же, вы можете вызывать подпрограммы из других модулей, но они должны быть созданы для выполнения четко поставленной задачи. Глупо размещать одну половину выполняемой операции в процедуре в одном модуле, а вторую половину— в другой процедуре (тем более— в другом модуле). Пусть это примитивный совет, но он является одним из самых действенных! Порядок — прежде всего! Порядок в мыслях и в программе!

Защититесь от дурака. Если ваша процедура не может переварить некорректные данные и вызвать тем самым крах всей системы, проверьте целостность входных данных, прежде чем работать с ними. Однако помните: если системой сможет воспользоваться любой дурак, значит, только дурак и будет ею пользоваться. Не увлекайтесь чрезмерной защитой, которая неумолимо будет отбирать время и ресурсы, необходимые для выполнения более важных задач.

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



Создание одноэкземплярного приложения



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



Stack Overflow



Переполнение стека (stack overflow) — ошибка, появляющаяся в 32-битовом приложении гораздо реже, чем в 16 битовом, так как размер стека в этом случае существенно больше. Практически есть только один путь получить эту ошибку в Delphi 4 — попасть в бесконечную рекурсию. Например, приведенная ниже функция неминуемо должна вызвать переполнение стека.

    function BlowTheStack(I: Integer); Integer;


    var J: Integer;


    begin


        J:= 2;


        Result:= BlowTheStack(I*J);


    end;

    Каждый раз при рекурсивном вызове в стеке резервируется место для локальной переменной J и адреса возврата. Поскольку условия возврата из рекурсии нет, переполнение стека неминуемо.


    Конечно же, бесконечная рекурсия — не единственная причина возникновения ошибки такого рода, но это первое,  что стоит отследить при переполнении стека.



Страницы свойств в среде DAX



    Другой частью среды DAX являются страницы свойств, которые используются в различных средах программирования для изменения значений свойств элементов управления на этапе разработки. Страницы свойств часто оказываются устаревшими, так как среды программирования обладают различными реализациями инспекторов свойств объектов, которые позволяют оперировать свойствами объектов во время разработки приложения. Но несмотря на это в создаваемые элементы управления ActiveX нужно всегда включать страницы свойств. Даже если эти страницы не будут использоваться ни для чего больше, то они хотя бы предоставят разработчику способ построения специальных окон редактирования более сложных свойств элемента управления. Как будет показано ниже, в Delphi можно довольно просто создавать страницы свойств. Ниже показана иерархия классов, которая поддерживает создание страниц свойств в Delphi.

    TCustomForm
        TPropertyPage
            TActiveXProperty Page
        [TMyPropertyPage]

    При создании новая страница свойств будет наследована от класса TPropertyPage.



String_type_of_data


Строковые типы

    В выражениях Delphi поддерживает три физических строковых формата: короткий (ShortString), длинный (LongString) и широкий (WideString). Их можно комбинировать в операторах присваивания и выражениях (все необходимые преобразования Delphi выполняет автоматически).


    Переменные типов AnsiString и WideString — это динамически распределяемые массивы символов, максимальная длина которых ограничивается только наличием памяти. Разница между ними состоит в том, что в AnsiString знаки записываются в формате char, а в WideString— в формате WideChar. Обычно вполне достаточно одного типа AnsiString, однако при работе с международными наборами символов, такими как UNICODE, удобнее использовать WideString.


    Тип ShortString—это, по существу, массив Array [0..255] of char. Первый его элемент задает динамическую длину строки, которая может принимать значения от 0 до 255 символов. Символы, составляющие строку, занимают места от 1 до 255. Тип ShortString предназначен, в основном, для обеспечения совместимости с ранними версиями Delphi и Borland Pascal.


    Логический строковый тип именуется просто String. Отнесение его к типу AnsiString или ShortString задается командой $Н. По умолчанию задается { $Н+}, и String совпадает с AnsiString. Если задать команду {$Н- }, то String будет совпадать с ShortString и иметь максимальную длину, равную 255 символам.


    Для совместимости с другими языками программирования в Delphi поддерживается класс строк с конечным нулем. Зарезервированных слов или идентификаторов для этого класса не существует.


    Строки с конечным нулем состоят из ненулевых символов и оканчиваются символом с порядковым номером 0 (#0). В отличие от типов AnsiString, ShortString и WideString, строки с нулевым окончанием не имеют указателя длины. Конец в этих стооках обозначается нулем.


    Физически строки с нуль-окончанием подобны массивам символов с нумерацией элементов от нуля, наподобие array [ 0 . . X] of char, где Х — некоторое положительное целое, большее нуля, хотя никаких объявлении подобного рода не происходит. Вместо этого определяется переменная-указатель PChar и распределяется необходимый объем памяти. При необходимости строке AnsiString можно присвоить тип PChar.



В табл. 1.7 перечислены некоторые процедуры и функции обработки данных строковых типов.

Совет: Программисты, работающие на С, привыкли записывать все строки в массивы с нуль-окончанием. Фактически они применяют в выражениях не строковые переменные, а указатели на них. Программисты, работающие на Basic, привыкли использовать строку как одно целое. Для типа AnsiString из Delphi годятся оба подхода.

 

Таблица 1.7.

Строковые функции

Функция  Описание
Concat(sl, s2, s3) Возвращает последовательное соединение строк. Эквивалентна оператору sl+s2+s3
Copy(s, pos, len) Возвращает подстроку длиной максимум len символов, начинающуюся в позиции pos строки s
Delete(s, pos, len) Удаляет максимум len символов из строки s, начиная с позиции pos
 Insert(sourse, tar-get, pos) Вставляет строку source в строковую переменную target, начиная с позиции pos
Length (s) Возвращает динамическую длину строки. Подобна функциям LEN в Basic и strlen — в C/C++
Pos(substring, s) Возвращает место первого вхождения подстроки substring в строку s. Подобна функциям SUBSTR в Basic и strstr () — в C/C++
SetLength(s, newlen) Задает новую динамическую длину newlen строковой переменной s
SetString Задает содержимое и длину строки
Str(x, s) Преобразует численное значение х в строковую переменную s
StringOfChars  Возвращает строку с конкретным числом символов
UniqueString Делает данную строку уникальной со счетом обращений 1
Val (s, v, code) Преобразует строку s в соответствующее численное представление v
 


Свойства TApplication



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



Свойства TForm



Класс TForm предоставляет возможность изменять его поведение и внешний вид формы с помощью ряда свойств.



Terminate



Этот метод— предпочтительный способ закрытия приложения. Terminate не закрывает приложение немедленно, а дожидается обработчика события и завершения всех других процессов. Обычно оно используется в меню File/Exit.

    procedure TFormI.mnuFileExitClick(Sender: TObject);


    begin


        Application.Terminate;


    end;


 



TileMode



Это — свойство перечислимого типа, определяющее, как родительская форма размещает дочерние при вызове метода Tile. Используются значения tbHorizontal (по умолчанию) и tbVertical для размещения форм по горизонтали и вертикали.



Тип Variant



Тип Variant предназначен для представления значений, которые могут динамически изменять свой тип. Если любой другой тип переменной зафиксирован, то в переменные типа Variant можно вносить переменные разных типов. Шире всего тип Variant применяется в случаях, когда фактический тип данных изменяется или неизвестен в момент компиляции.



Title



    Определяет заголовок приложения в панели задач.



Трассировка исходного кода VCL



    Если вы используете соответствующую версию поставки Delphi 4, значит, в нее входят исходные тексты VCL (Visi Component Library). В поставку VCL входят скомпилированными без отладочной информации, что означает, что при отладке вы не сможете пройти код пошагово. Нет особой необходимости трассировать код VCL, но если вы хотите убедиться, что ошибка не в VCL, или посмотреть, как работает функция, придется перекомпилировать модули, которые нужно трассировать, с отладочной информацией.

Совет:  Некоторые стандартные модули VCL требуют компиляции с отключенной опцией Overflow Checking для корректной работы. Поэтому при перекомпиляции убедитесь, что эта опция компилятора отключена.

 
 
 
 
 
 
 
 
 
 
 
 
 



Управление хранилищем объектов



   После добавления шаблона в хранилище вы вдруг обнаруживаете, что совсем забыли внести в него последние исправления. Вы можете сделать это, используя диалоговое окно Object Repository, показанное на рис. 1.9. Для его вызова воспользуйтесь командой Tools/Repository.
    В списке Pages, расположенном слева в диалоговом окне, перечислены страницы, выводимые в диалоговом окне New Items. Управлять этим набором можно с помощью кнопок Add Page, Delete Page и Rename Page.

Рис. 1.8. Опция Shared Repository позволяет определить разделяемое хранилище шаблонов

 

Рис. 1.9. Использование диалогового окна Object Repository для работы с шаблонами

    Выбор страницы из списка приводит к заполнению списка Objects объектами, содержащимися на этой странице. Если вы выберете элемент [Object Repository], будут показаны все объекты в хранилище. Вы можете перемещать объекты путем их перетаскивания из списка Objects на нужную страницу в списке Pages.


Кнопка Edit Object позволяет вывести диалоговое окно Edit Object Info, показанное на рис. 1.10. С его помощью можно редактировать свойства объекта в любой момент.


    Кнопка Delete Object удаляет объект из хранилища, но не удаляет его файлы с диска.


    Переключатели, расположенные внизу диалогового окна, выполняют две задачи. Первый переключатель. New Form, позволяет определить шаблон, используемый при создании новой формы. Второй, Main Form, определяет шаблон, используемый для построения главной формы при создании нового приложения. Для назначения соответствующих шаблонов просто выберите объект из списка Objects и отметьте нужную опцию.


 

Рис. 1.10. Редактировать свойства объекта можно в хранилище с помощью диалогового окна Edit Object Info

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


 



Установка точек останова



    Точка останова (breakpoint) — своеобразный знак STOP для отладчика (на полосе слева в окне редактора она и выглядит как маленький красный значок). Когда ваше приложение запущено под отладчиком и доходит до строки, в которой находится точка останова, оно прекращает работу и ждет ваших дальнейших распоряжений. Такие точки могут быть условными и безусловными. Отладчик всегда останавливается на точке безусловного останова и может останавливаться в точке условного останова, когда выполнено условие. Интегрированный отладчик Delphi поддерживает два типа условий — логическое и по количеству проходов. Ниже рассмотрены оба типа.


    Установить точки останова можно следующими способами:

Поместите курсор редактирования на выбранную строку программы и нажмите клавишу команды Toggle Breakpoint (по умолчанию это клавиша <F5>) для установки или удаления точки останова в этой строке. То же самое можно выполнить и с помощью контекстного меню.

Выберите команду Run/Add Breakpoint, и откроется диалоговое окно Edit breakpoint (рис 2.15). Для установки простейшей точки останова просто щелкните на кнопке New. Вы также можете использовать поля Filename и Line Number для установки точек останова в другом файле или строке за пределами текущей позиции курсора. Поля Condition и Pass count используются для установки точки условного останова.

    После установки одной или нескольких точек останова можете использовать окно Breakpoint List для управления ими. Для вызова окна Breakpoint List выберите команду View/Breakpoints (рис. 2.16). В этом окне можете щелкнуть на строке конкретной точки правой кнопкой мыши и в контекстном меню отключить точку останова с помощью команды Disable (вновь включить точку останова можно с помощью команды Enable) или удалить ее с помощью команды Delete. Команды View Source и Edit Source активизируют окно с текущим файлом исходного текста, при этом команда Edit Source устанавливает курсор в строку с точкой останова. Команда Properties выводит диалоговое окно Edit breakpoint, показанное на рис. 2.15, позволяя тем самым изменять параметры точки останова.


 


Рис. 2.15. Использование диалогового окна Edit breakpoint для установки новой точки останова.



Рис. 2.16. Использование окна Breakpoint list для управления точками останова.

    После щелчка правой кнопкой мыши в окне при невыбранной точке останова выводится контекстное меню, в котором команда Add служит для добавления новой точки, Delete All удаляет все точки останова, а команды Disable All и Enable All отключают или включают все точки останова в списке.

    Для превращения безусловной точки останова в условную, необходимо вызвать диалоговое окно Edit breakpoint (см. рис. 2.15) и ввести условное выражение или количество проходов в соответствующие поля.

    Условное выражение, введенное в поле Condition, может быть любым логическим выражением. По достижении точки останова отладчик вычисляет значение выражения и, если результат ложен, продолжает выполнение программы. Если выражение истинно, выполнение программы приостанавливается. Как обычно, выражение не должно использовать вызов функции. Такие точки останова полезны, если вы можете попасть в интересующий вас фрагмент кода различными путями, но вы хотите остановить выполнение программы только при достижении каких-либо конкретных условий.

    Ненулевое значение, введенное в поле Pass count, дает отладчику задание продолжать выполнение программы при прохождении через точку останова, пока через нее не будет выполнено соответствующее количество проходов. При каждом проходе через точку останова отладчик уменьшает значение счетчика на единицу и по достижении нулевого значения программа приостанавливается. Такой метод полезен при работе с циклами, особенно если вы знаете, что ошибка происходит после определенного количества циклов.

    Сейчас, когда вы изучили основы технологии отладки, вероятно, у вас возникло желание поставить точку останова у себя в голове и поработать с точками останова в программах. Кстати, один из отличных методов понять,  как работает та или иная программа, — проследить за ее пошаговым выполнением, а поскольку ни установка точек останова, ни просмотр или изменение переменных не изменяют текста программы, вы можете работать смело, не опасаясь каким-либо образом "поломать" используемое в учебных целях приложение.


Вариантные записи



Вариантная часть типа record дает возможность по-разному трактовать область памяти, совместно занимаемую вариантами поля:

    record
        case optional tagfield: required ordinal type of
        1: variantnamel: varianttype3;
        2, 3: variantname2: varianttype4;
    end;

Совет: Термин вариантный в отношении записей не имеет ничего общего с типом Variant, который мы рассмотрим в следующем разделе данной главы. Вариантные поля, несмотря на свое название, никогда не имеют тип Variant. Объявление этого типа в любом месте вариантной части записи запрещено.

    Все варианты занимают в памяти одно место. Каждый вариант обозначается некоторой постоянной. При желании можно получать доступ ко всем полям всех вариантов одновременно, однако это может иметь смысл только в наиболее простых случаях, когда точно известно, как именно информация каждого варианта записывается в память.
    Каждый вариант обозначается минимум одной константой. Все константы должны быть порядковыми и совместимыми по типу с меткой поля.
    Необязательное поле — это идентификатор дополнительного поля в фиксированной части записи, общий для всех вариантов. Обычно с его помощью определяют, когда к какому варианту обращаться.
Необязательное поле можно не указывать, однако порядковый тип необходим. При отсутствии необязательного поля программе придется выбирать подходящий вариант каким-то иным образом.
Данные некоторых типов бессмысленно интерпретировать различным образом, и в Object Pascal на некоторые критические типы наложено соответствующее ограничение. Как следствие, в вариантную часть записи нельзя включать длинные строки и переменные типа Variant, а также структурные переменные, содержащие эти типы.

Совет: В С и C++ эквивалентом вариантному типу записи из Delphi является тип union.



Вариантные значения



    При рассмотрении типа Record мы ознакомились с вариантной частью записи, где в одном фрагменте памяти можно хранить информацию нескольких типов. Такой метод недостаточно нагляден. Много ли пользы от того, чтобы найти в памяти действительное значение с фиксированной запятой и интерпретировать его, как целое! Тип Variant (не имеющий ничего общего с вариантной частью записи) более "проворен" и полезен в управлении данными разных типов. Переменным типа Variant можно присваивать любые значения любых целых, действительных, строковых и булевых типов. Для совместимости с другими языками программирования предусмотрена также возможность присвоения этим переменным значений даты/времени и объектов OLE Automation. Кроме того, вариантные переменные могут содержать массивы переменной длины и размерности с элементами указанных типов.
    Все целые, действительные, строковые, символьные и булевы типы совместимы с типом Variant в отношении операции присваивания. Вариантные переменные можно сочетать в выражениях с целыми, действительными, строковыми, символьными и булевыми; при этом все необходимые преобразования Delphi выполняет автоматически. Можно произвольно задавать для выражении тип Variant в форме Variant (X).
    В Object Pascal определены два особых значения Variant. Значение Unassigned применяется для указания, что вариантной переменной пока не присвоено значение какого бы то ни было типа. Значение Null указывает на наличие в переменной данных неизвестного типа или потерю данных. Разницу между этими двумя значениями трудно уловить. Значение Unassigned присваивается вариантным переменным автоматически при их создании, независимо от того, локальная это переменная или глобальная, и является ли она частью другой, структурной, переменной, такой как запись или массив. Unassigned означает, что к данной вариантной переменной еще не обращались. Null же означает, что к вариантной переменной обращались, но не ввели в нее никакой информации. Таким образом, Null указывает, что значение вариантной переменной недействительно или отсутствует.
    Вариантные переменные предоставляют широкие возможности формирования выражений с переменными разных типов. Однако за это приходится платить большим, по сравнению с жестко задаваемыми типами, расходом памяти. К тому же на выполнение операций с вариантными переменными требуется больше времени.
    Интересна проблема использования вариантной переменной как массива. Элементы этого массива должны быть одного типа. На первый взгляд, это вполне естественное условие. Однако элементам массива можно присвоить и тип Variant! Тогда каждый элемент сможет содержать информацию разных типов, в том числе массив Variant. Как правило, вариантные массивы создаются с помощью процедуры VarArrayCreate.
    Для передачи двоичной информации между контроллерами автоматизации OLE и серверами обычно применяются вариантные массивы с элементами varByte. Вариантные массивы типа varByte не могут подвергаться никаким преобразованиям. Нельзя также переформатировать содержащуюся в них двоичную информацию. Эффективный доступ к ним осуществляется с помощью процедур VarArrayLock и VarArrayUnlock.
    Элементы вариантного массива не могут иметь тип varString. Для создания вариантных массивов со строковыми элементами следует выбрать тип varOleStr.



VersionInfo



    Вкладка Versionlnfo дает возможность добавить к выполняемому модулю или DLL информацию о версии— Major Version, Minor Version и File Description.


    Действительно полезную возможность предоставляет Auto-increment build number, заставляя Delphi всякий раз увеличивать номер выпуска при компиляции программы.


    Раздел Module Attributes позволяет включать флаги, такие как Debug Build, в приложение. Выбор опций не влияет на процесс компиляции — они используются только в информативных целях.



Вкладка Attributes в описании библиотеки типов



Во вкладке Attributes (атрибуты) содержится общая информация и характеристики библиотеки типов. Показанные ниже атрибуты и флаги появляются в этой вкладке, когда в панели Object List выбран элемент библиотеки типов (см. рис. 3.1). В табл. 3.1 перечислены все атрибуты, а в табл. 3.2 — все флаги библиотеки типов.

Рис. 3.1. Редактирование данных о библиотеке типов

Таблица 3.1. Атрибуты библиотеки типов

  

Атрибут  Описание
Name  Имя библиотеки типов
GUID Глобально уникальный 128-разрядный идентификатор библиотеки типов
Version Версия библиотеки типов, записанная в формате п.т, где п — старший и т — младший номера версии. В качестве номера версии может использоваться и единичное целое число. В качестве старшего и младшего номеров версий можно использовать числа от 0 до 65 535
LCID Идентификатор места действия (locale), описывающий один национальный язык, который используется для всех текстовых строк в библиотеке типов и ее элементах
Help String Краткое описание библиотеки. Настоятельно рекомендуется указывать эту строку во всех созда-ваемых библиотеках
Help File Имя файла справки, связанной с библиотекой типов
 Help Context  Идентификатор контекста справки библиотеки типов

  
 
  Таблица 3.2. Флаги библиотеки типов

  

Флаг Описание
None  Флаги не установлены
Restricted Запрещает использовать библиотеку типов в средах программирования макросов, таких как Visual Basic
Control Указывает, что библиотека содержит элемент управления, который будет использован на стороне сервера для порождения новых библиотек типов и классов составных объектов (CoClass)
Hidden Указывает, что библиотека существует, но не должна быть показана в пользовательских броузерах

  



Вкладка Attributes в описании интерфейса



На рис. 3.4 показан интерфейс, выбранный в окне редактора библиотек типов, с вкладкой Attributes в правой части окна редактора. В табл. 3.4 перечислены все возможные атрибуты, которые можно использовать в описании интерфейса, а в табл. 3.5 — все флаги, используемые в описании интерфейса.
  Таблица 3.4. Атрибуты интерфейсов в библиотеках типов

  

Атрибут Описание
Name Имя перечисления
GUID 128-разрядный идентификатор GUID-перечисления
Help String Краткое описание перечисления. Настоятельно рекомендуется указывать эту строку во всех создаваемых библиотеках
Help Context Идентификатор контекста справки по перечислению
Version Версия библиотеки типов, записанная в формате п.т, где п — старший и т — младший номера версии. В качестве номера версии может использоваться и единичное целое число. В качестве старшего и младшего номеров версий можно использовать числа от 0 до 65 535
Parent Interface Имя интерфейса, являющегося базовым классом для выбранного интерфейса. Этот атрибут не применяется для интерфейсов Displnterface

    

Рис. 3.4. Редактирование атрибутов интерфейсов в библиотеке типов

Таблица 3.5. Флаги интерфейсов в библиотеках типов 

Флаг Описание
Displnterface Элемент описывает методы и свойства объекта, доступ к которому можно получить только через метод Invoke интерфейса Idispatch
Hidden Указывает, что интерфейс существует, но не должен быть показан в пользовательских броузерах 
Nonextensible Указывает, что реализация интерфейса IDispatch включает только те свойства и методы, которые показаны в описании интерфейса
Dual Указывает, что интерфейс предоставляет методы и свойства через интерфейс IDispatch и таблицу виртуальных методов
OLE Automation Указывает, что интерфейс может использовать только совместимые с автоматизацией типы данных. С элементом Displnterface этот флаг использовать нельзя, так как данный элемент совместим с автоматизацией по определению

  



Вкладка Attributes в описании классов составных объектов



В табл. 3.8 перечислены все атрибуты, а в табл. 3.9 — флаги, которые используются в описаниях составных классов.
  Таблица 3.8. Атрибуты составных классов в библиотеках типов

  

Атрибут Описание 
Name Имя составного класса (CoClass) 
GUID Уникальный 128-разрядный идентификатор GUID составного класса (CoClass) 
Help String Краткое описание составного класса. Настоятельно рекомендуется указывать эту строку во всех создаваемых библиотеках
Help Context Идентификатор контекста справки по составному классу
Version Версия библиотеки типов, записанная в формате п. т, где n — старший и m — младший номера версии. В качестве номера версии может использоваться и единичное целое число. В качестве старшего и младшего номеров версий можно использовать числа от 0 до 65 535.

  
  Таблица 3.9. Флаги составных классов в библиотеках типов

  

Флаг  Описание
Licensed Указывает, что во время разработки и выполнения требуется лицензия. Обычно используется вместе с элементами управления ActiveX
Control Указывает, что составной класс является элементом управления
Application Object Указывает, что составной класс помещен во внешний (out-of-process) сервер (ЕХЕ). Используется исключительно с серверами автоматизации

  
 



Вкладка Attributes в описании перечисления



    На рис. 3.2 показано перечисление (Enum), выбранное в окне редактора библиотек типов Delphi с вкладкой Attributes в правой части окна редактора. В табл. 3.3 перечислены все возможные атрибуты, которые можно использовать с перечислением.  

Рис. 3.2. Редактирование перечисления в библиотеке типов

  Таблица 3.3. Атрибуты перечисления в библиотеке типов

  

Атрибут Описание
Name Имя перечисления
GUID 128-разрядный идентификатор GUID-перечисления
Help String Краткое описание перечисления. Настоятельно рекомендуется указывать эту строку во всех создаваемых библиотеках
 Help Context  Идентификатор контекста справки по перечислению
Version Версия библиотеки типов, записанная в формате п.т, где n — старший и m — младший номера версии. В качестве номера версии может использоваться и единичное целое число. В качестве старшего и младшего номеров версий можно использовать числа от 0 до 65 535

  



Вкладка Attributes в описании свойств и методов интерфейса



На рис. 3.6 показано свойство интерфейса, выбранное в окне редактора библиотек типов, с вкладкой Attributes в правой части окна редактора. В табл. 3.6 перечислены все атрибуты, которые используются в определении членов интерфейса, а в табл. 3.7 — все возможные флаги.
  Таблица 3.6. Атрибуты членов интерфейса в библиотеках типов:

  

Атрибут  Описание 
Declaration Объявление свойства или метода 
ID  Значение идентификатора DispID 
Help String  Краткое описание свойства или метода 
Help Context Идентификатор контекста справки по свойству или методу

    

 

Рис. 3.6. Редактирование атрибутов в библиотеке типов

  Таблица 3.7. Флаги членов интерфейса в библиотеках типов

  

Флаг Описание
Restricted  Запрещает использовать библиотеку типов в средах программирования макросов, таких как Visual Basic
Source  Указывает, что член возвращает объект или значение типа VARIANT, являющееся источником событии
Bindable Указывает, что свойство поддерживает связывание (binding) данных
Request Edit  Указывает, что свойство поддерживает сообщение OnRequestEdit
Display Bindable Указывает, что свойство должно быть показано пользователю как поддерживающее связывание данных (bindable)
 Default Bindable Указывает на одно поддерживающее связывание данных свойство, которое наилучшим образом представляет объект 
Hidden Указывает, что интерфейс существует, но не должен быть показан в пользовательских броузерах 

  



Вкладка Members в описании интерфейса



    Вкладка Members в описании интерфейса содержит свойства интерфейса и методы, определенные в этом интерфейсе. За исключением незначительных отличий, синтаксис объявлений констант и методов совпадает с синтаксисом языка Object Pascal. Первое отличие проявляется в том, что после описания каждого свойства и метода должен следовать уникальным идентификатор или DispID. Обычно значения DispID начинаются с 1 и увеличиваются на 1 для каждого следующего элемента. Вторым отличием являются ключевые слова readonly и writeonly, которые позволяют запрещать запись и чтение свойств соответственно. Ниже показан пример определения методов и свойств.

    property FrameCount: Integer; readonly; dispid 1;
    property Play(FromFrame, ToFrame: Smallint; Count: Integer); dispid 2;
    property OpenDatabase[DatabaseName, TableName, UserName, Password : WideString]: WordBool; dispid 3;

    Последним является определение параметризованного свойства с разрешением только чтения. В примере это свойство использовано не только для демонстрации такого типа свойств, но и потому, что некоторые серверы ActiveX предпочитают использовать параметризованные свойства вместо методов. На рис. 3.5 показана вкладка Members описания интерфейса в редакторе библиотек типов Delphi.  

Рис. 3.5. Редактирование членов интерфейса в библиотеке типов

    Если для описания интерфейса используется инструкция Displnterface, то для определения методов и свойств интерфейса можно использовать только совместимые с автоматизацией OLE типы данных. Совместимыми с OLE являются следующие типы данных: Byte, Smallint, Integer, Single, Double, Currency, TDateTime, WideString, WordBool и OleVariant. Для передачи многомерных структур данных можно использовать массивы данных типа OleVariant.



Вкладка Members в описании перечисления



Во вкладке Members определяются сами константы, составляющие перечисление. Формат определения константы показан ниже.

    <Имя константы> = <Значение константы>;
    helpstring = 'Строка описания';

    Настоятельно рекомендуется указывать строку описания для членов перечисления, так как приложения, использующие ваш объект СОМ, могут зависеть от строк описания. На рис. 3.3 показана вкладка Members описания перечисления.
 

Рис. 3.3. Редактирование элементов перечисления в библиотеке типов



Вкладка Members в описании составного класса



    Во вкладке Members в описании составного класса можно добавлять и удалять интерфейсы и перечисления, которьк составляют класс СОМ. В рассматриваемой вкладке содержится следующая информация.

Имена интерфейсов и диспинтерфейсов, которые реализованы в классе СОМ.

Идентификаторы GUID интерфейсов и диспинтерфейсов, реализованных в классе СОМ.

Указания, является ли интерфейс или диспинтерфейс источником сообщений.

Указания, является ли интерфейс или диспинтерфейс программируемым интерфейсом, используемым в языке программирования макросов, таких как Word Basic, Visual Basic, Delphi, Object PAL и Excel Basic.

Указания, запрещено ли использование интерфейса или диспинтерфейса в языках программирования макросов таких как Word Basic, Visual Basic, Delphi, Object PAL и Excel Basic.

    Чтобы добавить интерфейсы в составной класс или удалить их, нужно щелкнуть правой кнопкой мыши в облает вкладки Members. На экране появится контекстное меню, в котором нужно выбрать команду Insert Interface или Remove Interface. С помощью контекстного меню можно также установить флаги Source, Default и Restricted. Новые интерфейсы можно выбирать из текущей библиотеки или из библиотек, на которые ссылается текущая библиотека типов.
 
 
 
 
 
 
 



Вкладка Uses в описании библтотеки типов



Во вкладке Uses показаны все библиотеки, на которые ссылается просматриваемая библиотека. С помощью ссылок на другие библиотеки типов можно заимствовать определение элементов, таких как пересечение или интерфейсы. Это поможет разработчику определить собственные интерфейсы в собственной библиотеке типов. Например, основной интерфейс сервера автоматизации порожден от интерфейса IDispatch, но вам не придется изобретать колесо, так как Delphi автоматически создает ссылку на библиотеку типов STDOLE32. TLB, в которой определен интерфейс IDispatch. Библиотека STDOLE32.TLB является основной библиотекой типов Windows.
    С каждой записью вкладки Uses связано две части информации. Первая часть — имя библиотеки, на которую создается ссылка, вторая — идентификатор GUID, который идентифицирует библиотеку типов в реестре Windows.



Включение в код отладочной информации



    Перед началом отладки следует убедиться, что в приложение включена отладочная информация Delphi.


    Для компиляции проекта с отладочной информацией следует выполнить команду Project/Options и в диалоговом окне Project Options выбрать вкладку Compiler (рис. 2.9).


 

Рис. 2.8. Окно редактора с отладочными значками

Рис. 2.9 Вкладка Compiler диалогового окна Project Options

    Включение отладочной информации регулируется следующими установками

Debug Information. Опция контролирует включение отладочной информации. При отключении этой опции вы не сможете трассировать код или ставить точки прерывания в любом модуле. Опция эквивалентна директивам компилятора $D и $DEBUGINFO

Local Symbols. Опция контролирует включение информации о локальных переменных, декларированных, например, внутри функций, процедур и раздела implementation. Вряд ли у вас возникнет необходимость в отключении этой опции, тем более что она игнорируется при выключенной предыдущей опции. Эквивалентные директивы компилятора— $L и $LOCALSYMBOLS.

Symbol Info. Эту опцию нельзя целиком отнести к разряду отладочных, так как ее действие направлено на броузер объектов, а не на встроенный отладчик. Если опция включена, броузер объектов сможет выводить информацию для объектов, определенных в модулях Опция игнорируется при выключенных предыдущих двух опциях Эквивалентные директивы компилятора — $Y и $REFERENCEINFO

    Обычно вы будете включать опции Debug Information и Local Symbols для пошаговой трассировки приложения. Однако, как упоминалось ранее, вы можете отключить отладочную информацию для некоторых модулей (просто используйте соответствующую директиву в начале модуля).

    unit MyUnit;


    {$D-}


    interface


    ...

    Использование директивы $D- автоматически отключает опции Local Symbols и Symbol Info, так что вам не надо отключать их отдельно.

Совет: Если вы распространяете модули Delphi в виде DCU-файлов (например, VCL) и не распространяете их исходных текстов позаботьтесь о том, чтобы в скомпилированных модулях не содержалась отладочная информация



Вывод на консоль



Еще один способ вывода отладочной информации— вывод на консоль с использованием процедур Write и WriteLn. Вы можете конвертировать проект в консольное приложение, например, выбрав соответствующую опцию (команду Project/Options, вкладку Linker и опцию Generate Console Application) или поместив директиву $APPTYPE CONSOLE в главный DPR-файл. Учитывая, что ваше приложение— не консольное, воспользуйтесь возможностями условной компиляции и используйте директиву $APPTYPE как показано ниже:

    {$ifdef Debug}


    {$APPTYPE CONSOLE}


    {$endif}

    Теперь вывод на консоль будет осуществляться только в отладочной версии вашего приложения.


    Если вы попытались использовать функцию Write или WriteLn и получили сообщение об ошибке I/O Еггог,  значит, вы забыли сделать проект консольным приложением.


    Обратите внимание, что здесь применяется тот же код, что и раньше, но теперь мы используем вывод на консоль вместо ShowMessage. Убедитесь, что вы создаете консольное приложение, и измените обработчик так, как показано ниже.

    procedure TFormI.ButtonlClick(Sender: T0bject);


    var MemStat: TMemoryStatus;


    begin


        MemStat.dwLength:= SizeOf(TMemoryStatus);


        GlobalMemoryStatus(MemStat);


        with MemStat do


        begin


            WriteLn(Format('Memory load: %d%%',[dwMemoryLoad]));


            WriteLn(Format('Total physical: %d',[dwTotalPhys]));


            WriteLn(Format('Available physical: %d',[dwAvailPhys]));


            WriteLn(Format('Total page file: %d',[dwTotalPageFile]));



            WriteLn(Format('Available page file: %d',[dwAvailPageFile]));

            WriteLn(Format('Total virtual: %d',[dwTotalVirtual]));

            WriteLn(Format('Available virtual: %d',[dwAvailVirtual]));

        end;

    end;
Результат показан на рис. 2.24.

Рис. 2.24. Использование консоли для вывода отладочной информации.
    Опытные пользователи Pascal заметят, что функция Format использовалась там, где это не было необходимо (WriteLn имеет свои возможности форматирования). Однако я везде использую Format как мощный инструмент; кроме того, используя везде одну лишь функцию Format, я избавляюсь от необходимости помнить два набора правил форматирования.

Вывод отладочной информации в форме.



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


    Посмотрите на описания функций ExtractFileDir и ExtractFilePath в справочной системе Delphi 4. Я не берусь точно судить по документации о различии между этими функциями, но я знаю, что мне делать. Я создаю новое приложение (выбрав пункт меню File/New Application) и помещаю в главную форму элемент TButton и два элемента TLabel (форма будет выглядеть так, как на рис. 2.20).


    Дважды щелкните на кнопке TButton и добавьте код к обработчику события OnClick.

    procedure TFormI.ButtonlClick(Sender: TObject);


    begin


        Labell.Caption:= ExtractFileDir(Application.ExeName);


        Label2.Caption:= ExtractFilePath(Application.ExeName);


    end;

    (Application. ExeName возвращает полное имя файла приложения). Нажмите клавишу <F9>

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


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


     Чтобы посмотреть, как это делается, создадим новое приложение и разместим в форме элементы управления TMemo и TButton (и не забудем установить значение свойства TMemo.ScrollBars равным ssVertical). Ваша форма будет выглядеть так, как на рис. 2.21.


 

Рис. 2.20. Вывод отладочной информации с использованием элемента управления TLabel.

Рис. 2.21. Вывод отладочной информации в элемент TMemo
    В обработчик события OnClick добавьте следующий код.
    procedure TFormI.ButtonlClick(Sender: TObject);

    var

        MemStat: TMemoryStatus;

    begin

        VirtualAlloc(nil, 1000000, MEM_RESERVE, PAGE_READWRITE);// 1

        MemStat.dwLength:= SizeOf(TMemoryStatus);              // 2

        GlobalMemoryStatus(MemStat);                            // 3

        Memol.Lines.Add(IntToStr(MemStat.dwAvailVirtual));      // 4

    end;
Не беспокойтесь о деталях вызова API-функции VirtualAlloc в строке 1. Здесь ее вызов требует от операционной системы зарезервировать миллион байтов памяти для дальнейшего использования. API-функция GlobalMemoryStatus возвращает информацию об использовании памяти приложением и системой в целом. Информация возвращается в переменной MemStat, представляющей собой запись типа TMemoryStatus. Перед вызовом GlobalMemoryStatus вы передаете системе информацию о размере структуры, как в строке 2, а затем вызываете функцию (строка 3) и выводите информацию в TMemo в строке 4.

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

    Используя этот метод (без вызова VirtualAlloc), я выяснил, что на самом деле DLL затребовала около 60 Мбайт (!) виртуальной памяти при загрузке и не освободила ее. Даже притом, что Windows 95 предоставляет каждому приложению двухгигабайтовое адресное пространство, потерю 60 Мбайт сложно проигнорировать...

 

Рис. 2.22. Вывод в элемент TMemo информации о количестве доступной виртуальной памяти.

What_new


Что нового в Delphi 4

Delphi4 представляет следующие новые свойства и усовершенствования:

Новые расширения языка.


    В Delphi 4 в язык Object Pascal включены динамические массивы, методы обработки переполнения, установка значения параметров по умолчанию, и многое другое.

Менеджер Проекта


    Новый менеджер проекта позволяет Вам объединять проекты которые работают вместе в одину проектную группу. Это позволяет Вам организовать как работу взаимозависимых проектов, таких как однозадачные и многозадачные приложения или DLL, так и совместную работу исполняемых программ.

Новый проводник


    Новый проводник содержит выполняемые классы, навигацию по модулям, и браузер кода. Проводник кода делает создание классов проще, автоматизирую многие из шагов. Введите прототип метода в разделе интерфейса и свойство выполняемого класса сгенерирует скелетный код в разделе реализации. Также проводник позволяет быстро перемещаться через файлы модуля, а так же между интерфейсом и реализацией. Использование символа Tooltip, позволяет просматривать информацию об объявлении любого идентификатора, затем используя борузер код, можно перейти к его объявлению.

Закрепляемые окна инструментов.


    IDE (Интегрированная Среда Разработки) содержит более перенастраеваемую конфигурацию окон инструментов, которые можно закреплять с редактором кода. Просто перетащите и отпустите окно инструмента к тому месту, к которому хотите. Проводник кода и менеджер проекта можно как закреплять, так и
незакреплять.

Улучшенная отладка.


    Интегрированный отладчик имеет много новых свойств, включая удаленную и многопроцессорную отладку, просмотр кода центрального процессора, инспекторов, усовершенствованные точки прерывания, отладчик специфических подменю и закрепленных окон.

Поддержка MTS.


    Явная поддержка для использования MTS интегрирована в поддержку многоуровневых баз данных. Кроме того, новый мастер облегчит Вам создание объектов сервера MTS.


Усовершенствования ActiveX.

    Delphi4 обеспечивает расширенную поддержку ActiveX.

Усовершенствования VCL.

    Иерархия объектов Delphi быда расширена, чтобы включить новый компонент для NT Service приложений. Кроме того, новый компонент выполняемого списка (на Стандартной странице палитры), позволяет Вам централизовать управление меню и команд от кнопок. Управление VCL расширено, чтобы поддерживають
drag-and-drop перетаскивания, обеспечивать дополнительный контроль над размещением окна, и многое другое.

Поддержка RTL для 2000-го года.

    Глобальная переменная TwoDigitYearCenturWwindow используется функциями StrtToDate и StrToTateTime, чтобы управлять интерпретацией лет с двумя цифрами при преобразовании дат.

Поддержка CORBA.

    Версии Клинт/Сервер и предприятие включают поддержку для CORBA клиент и сервер приложений. Мастера помогут Вам легко создать сервер CORBA и Динамический Интерфейс Вызова (DII), позволяя Вам записывать клиентов для существующих серверов CORBA. CORBA имеет возможность поддержки
в много-уровневых баз данных. Вы можете даже создать сервер, который обрабатывает COM клиентов и CORBA клиентов одновременно.


WindowMenu



    Профессиональные MDI-приложения позволяют активизировать необходимое дочернее окно, выбрав его из списка в меню. Свойство WindowMenu определяет объект TMenuItem, который Delphi будет использовать для вывода списка доступных дочерних форм.


    Для вывода списка TMenuItem должно быть меню верхнего уровня. Это меню имеет свойство Caption, равное swindow.



WindowState



    Свойство перечислимого типа WindowState определяет состояние окна— свернутое, развернутое или нормальное. По умолчанию оно имеет значение wsNormal (при этом окно выводится в состоянии, определяемом свойствами Position, Left, Top, Height и Width). Чтобы свернуть или развернуть форму, используются значения wsMinimize и wsMaximize.



Запись в Log-файл



    Запись отладочной информации в файл протокола (Log-файл) существенно отличается от предыдущих приемов записи, так как это уже нельзя назвать "быстро и грязно". Это отличная технология, которую можно использовать в любом приложении.


    Запись в файл протокола выполняется так же, как и вывод на консоль, но вместо WriteLn (. . . ) используется WriteLn (LogFile, . . . ), где LogFile — имя файловой переменной типа TextFile. Надо также не забывать открывать этот файл в начале работы приложения и закрывать — в конце. Проще всего этого добиться, поместив соответствующий код в свой модуль, который благодаря возможности условной компиляции подключается только в отладочной версии вашей программы.

Листинг 2.1. Модуль протоколирования отладочной информации.

    unit uLoq;


    interface


    procedure Log(S: Strings-implementation uses


        Windows, SysUtils;


    var


        LogFile: TextFile;


        LogCriticalSection: TRtlCriticalSection;


    procedure Log(S: String);


    var


        SystemTime: TSystemTime;


        FileTime: TFileTime;


    begin


        GetSystemTime (SystemTime) ;


        SystemTimeToFileTime(SystemTime, FileTime) ;


        EnterCriticalSection(LogCriticalSection);


        WriteLn(LogFile, Format('%s %.8x%.8x %5',


            [FormatDateTime('yy.mm.dd hh.inm.ss'. Now),


            FileTime.dwHighDateTime, FileTime.dwLowDateTime, S])) ;


        LeaveCriticalSection(LogCriticalSection) ;



    end;

    procedure Startup;

    var

        FileName: String;

    begin

        InitializeCriticalSection(LogCriticalSection);

        FileName := Format("Log file for %s at %s.txf,

            [ParamStr(O), DateTimeToStr(Now)]) ;

        while Pos(':', FileName) 0 do

            FileName[Pos(':', FileName)] := '.';

        while Pos('/', FileName) 0 do

            FileName[Pos('/', FileName)] := '-';

        while Pos('\', FileName) 0 do

            FileName[Pos('\', FileName)] := '.';

        AssignFile(LogFile, FileName);

        Rewrite(LogFile) ;

    end;

    procedure Shutdown;

    begin

        CloseFile(LogFile) ;

        DeleteCriticalSection(LogCriticalSection) ;

    end;

    initialization Startup;

    finalization Shutdown;

end.

    Этот модуль сам создает, открывает и закрывает файл протокола. Имя файла создается с учетом имени приложения и текущих даты и времени, что исключает возможность записи информации поверх существующего файла. Для использования модуля условно включите его, как показано ниже.

    unit MyUnit;
    interface
    uses
        ($ifdef Debug} uLog, {$endif)
        Windows, Messages, SysUtils, Classes,
        . . .



    Затем используйте его приблизительно так.

    {$ifdef Debug)

    Log(Format(' Entering the Foo procedure; Bar = %d',[Bar]));

    {$endif}

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

    Модуль uLog обладает двумя интересными и полезными свойствами. Во-первых, каждая запись в файл предваряется информацией о дате, времени и шестнадцатеричным числом, соответствующим системному времени в миллисекундах. Эта информация может быть весьма полезной, особенно когда вы хотите отследить последовательность событий в приложении. Во-вторых, модуль использует критические разделы (critical section), что обеспечивает доступ к файлу только одной подзадачи в один момент времени.

    На рис. 2.25 показан типичный файл протокола в программе Notepad.

 


Рис. 2.25. Пример отладочного файла протокола

    Как правильно использовать файл протокола? Какую информацию в него записывать? Сколько программистов, столько и ответов на эти вопросы. Лично я предпочитаю придерживаться золотой середины между "записывай все" и "записывай только то, что отлаживаешь".


Записи



С помощью зарезервированного слова record (запись) в одном типе можно объединять данные разных типов. Общий синтаксис объявления этого типа выглядит следующим образом:

    record


        fieldnamel: fieldtypel;


        fieldname2, fieldname3: fieldtype2;


        case optional tagfield: required ordinal type of


        1: variantnamel: varianttype3;


        2, 3: variantname2: varianttype4;


    end;

    Данное объявление состоит из фиксированной и вариантной частей. Однако вовсе не обязательно вставлять в одно объявление записи обе эти части. Обычно удобнее работать с каждой из этих частей отдельно.