Домой Картофель Breakpoint actions, breakpoint groups: новые свойства точек прерывания

Breakpoint actions, breakpoint groups: новые свойства точек прерывания

Delphi является объектно-ориентированной средой визуального программирования для быстрой разработки приложений (RAD). Используя Делфи , можно создавать высокоэффективные приложения для Microsoft Windows с минимумом ручного кодирования. Дэлфи предоставляет все необходимые средства для разработки, тестирования, отладки и развертывания приложений, включая большую библиотеку многократно используемых компонентов, набор инструментов проектирования, шаблоны приложений и форм, а также мастера программирования. Эти инструменты упрощают проектирование и сокращают время разработки.

Название Программы: Delphi
Версия программы: 3
Язык интерфейса: eng
Лечение:
Системные требования:
процесор pentium и выше
200mb жосткий диск
монитор 640х480
32mb оперативки

Название Программы: Delphi
Версия программы: 4
Язык интерфейса: eng
Лечение: не требуется (инсталлятор уже пролечен)
Системные требования:
* прцесор Intel 486/66 MHz и выше
* Microsoft Windows 95 или NT 4.0 (Service Pack 3).
* 16Mb оперативки (32Mb рекомендовано).
* монитор 640x480
*200mb на жостком

Название Программы: Delphi
Версия программы: 5
Последняя Версия программы: 15(xe)
Язык интерфейса: eng
Лечение: в комплекте
Тип лекарства: кейген
Системные требования:
* процесор Intel Pentium 90 (P166 рекомендуется)
* Microsoft Windows 95, 98, или NT 4.0 Service Pack 3
* память 32MB (64MB рекомендуется)
* 200mb жоский диск
* монитор 640 480

Размер: 512 Мб

Первая версия Delphi ориентированная на разработку клиент-серверных приложений.

Корпорация Inprise, до недавнего времени гордо именовавшаяся “Borland”, выпустила в свет новую версию Delphi - популярной у нас среды быстрой разработки приложений, опирающейся на могучие плечи языка Object Pascal (Собственная объектно-ориентированная модификация языка программирования Pascal). Предыдущие версии этого продукта снискали себе славу действительно быстрых и достаточно удобных в использовании RAD, дающих помимо всего прочего возможность опуститься на уровень-другой ниже и обойти таким образом неизбежные проблемы языков высокого уровня. К сожалению, похвальное стремление слить в единое целое преимущества RAD и языков системного уровня приводит, кроме очевидного выигрыша, еще и к объединению проблем обоих подходов к программированию.

Delphi 5
Дистрибутив должен устанавливаться из корня диска

Процедура лечения:
во время установки вводим Ключ: 100-006-1659 6ax0-91x0

Информация:
В 1994 году была выпущена первая версия Delphi. Пакет оказался очень удачным и, по сути, стал флагманским продуктом компании, в котором проходили апробацию все оригинальные технические решения.

Помимо создания средств разработки Borland в разное время работала на рынке СУБД - dBase, Paradox и InterBase.

В 1998 году в компании было принято решение взять курс на корпоративный сектор, это стало причиной смены названия на Inprise (Integration the Enterprise - интеграция предприятий). Однако в ноябре 2000 года компания вернула себе имя Borland Software.

В феврале 2000 года было объявлено о слиянии Inprise и Corel, однако уже в мае это соглашение было разорвано.

В конце 2002 года появились слухи о возможной покупке Borland Microsoft-ом. Эти слухи не подтвердились, но, по неподтверждённым данным, в какой-то момент около 5 % уставного капитала Borland всё-таки принадлежало Microsoft.

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

В феврале 2006 года Borland Software Corporation объявила о своих планах полностью переключиться на разработку и поддержку средств управления жизненным циклом приложений (Application Lifecycle Management, ALM). В рамках этого плана Borland приобрела компанию-поставщика ALM-решений Segue Software Inc и анонсировала планы о поиске покупателя на часть бизнеса компании, связанного с созданием средств разработки приложений, включая линейки Borland Developer Studio (Delphi, C++Builder, C#Builder) и JBuilder. Покупателя не нашлось, поэтому направление интегрированных средств разработки (Integrated Development Environment, IDE), было выделено в коммерчески самостоятельное подразделение CodeGear. А в Интернете даже появился проект по сбору средств на приобретение Delphi с целью сделать его Open Source продуктом.

7 мая 2008 года компания Embarcadero Technologies приобрела у Borland Software её подразделение Codegear за 23 млн долларов и 7 млн долларов в дебиторских задолженностях, доставшихся Borland.

6 мая 2009 стало известно о том, что компания Borland Software будет продана за 75 млн долларов британской компании Micro Focus, специализирующейся на поддержке крупных корпоративных систем на языке COBOL.

delphi 4 давно неподерживается ни Borland ни Embarcadero
есть только обновления на официальном сайте Borland

Страница ActiveX.

Компоненты ActiveX являются "чужими" для Delphi (рисунок 1). Они создаются другими инструментальными средствами разработки программ (например, С ++ или Visual Basic) и внедряются в Delphi с помощью технологии OLE. На странице ActiveX представлены лишь пять компонентов из большого количества, разрабатываемых повсюду в мире производителями программных средств и отдельными программистами. Компоненты страницы ActiveX для Delphi 4 и Delphi 5 одинаковы.

Компонент Chartfx (интерактивный график) дает программистам удобное средство включения в программу интерактивных (диалоговых) диаграмм и графиков.

Компонент VSSpell (спеллер) осуществляет орфографическую проверку правильности написания английских слов.

Компонент FlBook (электронная таблица) позволяет создавать и использовать рабочие книги электронных таблиц, подобно тому, как это делает MS Excel.

Компонент VtChart (мастер диаграмм) обеспечивает средства построения двумерных и трехмерных диаграмм по результатам табличных вычислений.

Компонент Graph (графический сервер) предназначен для включения в программу графических двумерных средств отображения данных.

Методы в Delphi.

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

Всего существует шесть разновидностей методов объектов: методы-процедуры, методы-функции, классовые процедуры, классовые функции, конструкторы, деструкторы.

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

Перед тем как рассмотреть методы-процедуры и методы-функции, рассмотрим, что такое процедуры и функции в Delphi.

Подпрограммы.

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

Подпрограмма - это блок кода с именем, состоящий из заголовка, объявлений и тела, в котором имеется набор исполняемых операторов. Язык программирования Object Pascal предоставляет два различных вида подпрограмм: процедуры и функции.

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

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

Самый простой способ - это определение заголовка процедуры и тела подпрограммы в начале раздела реализации блока. Так как они размещены в начале программы, то компилятору становится известно об их существовании до того, как они будут вызваны из какой-либо ее части, например:

Implementation {$R *.DFM} procedure Information; begin MessageDlg("Информация", mtInformation,,0); end; procedure TForm1.Button1Click (Sender: TObject); begin Information; end; end.

Если процедура будет описана после реализации события OnClick, то компилятор выдаст следующее сообщение: Unit1.pas(28): Undeclared identifier: "Information" - неопределенный идентификатор. Эту проблему можно решить путем помещения объявления процедуры в начале раздела реализации с последующим ключевым словом forward:

Procedure Information; forward;

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

Следующий способ сделать процедуру доступной в модуле - это объявление ее в разделе интерфейса:

Procedure Information; implementation {$R *.DFM}

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

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

Давайте рассмотрим процесс создания подпрограммы на примере процедуры, которая поможет вам изучить технику написания методов в Delphi.

1. Запустите Delphi. Сохраните файл модуля под именем Methods_.pas, а файл проекта под именем Methods. dpr. Нет никакого функционального различия между модулями, созданными вами в Редакторе кода, и модулями, сгенерированными Delphi автоматически. В любом случае модуль состоит из трех разделов:

  • раздел заголовка;
  • раздел interface;
  • раздел implementation.

В разделе interface описывается все то, что должно быть видимо для других модулей (типы, переменные, классы, константы, процедуры, функции). В разделе implementation помещается код, реализующий классы, процедуры или функции.

В Delphi процедурам и функциям (а следовательно и методам классов) могут передаваться параметры для того, чтобы обеспечить их необходимой для работы информацией. Программа Methods продемонстрирует, как использовать передачу параметров в методы Delphi.

Это приложение позволит вам производить вычисления, а конкретно суммирование чисел, помещенных в компоненты Edit1 и Edit2. Результат суммирования переносится в компоненты Edit3, Memo1, Memo2. После нажатия кнопки с заголовком "EnteringALine" строка из управляющего элемента EditSumma (т.е. Edit3) копируется в управляющие элементы Memo1 и Memo2.

2. После того как вы разместите на форме компоненты Edit1, Edit2, Edit3, Memo1, Memo2, произведите переименование с помощью инспектора объекта (свойство Name) компонента Edit3 в EditSumma. Размещение компонентов на форме показано на рисунке 2. Поместите на форму компонент Button1, и в Object Inspector измените его заголовок (свойство Caption) на "EnteringALine". Компоненты Label1, Label2, Label3 используйте для ввода надписей, определяющих назначение компонентов Edit.

3. После завершения проектирования формы класс TForm1 будет выглядеть следующим образом:

TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Edit1: TEdit; Memo2: TMemo; Edit2: TEdit; EditSumma: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; end;

4. Следующий шаг состоит в добавлении метода, вызываемого по нажатию пользователем кнопки Button1. Это можно сделать двумя способами:

  • перейти в Инспекторе Объектов на страницу Events (предварительно выбрав компонент Button1 на форме), выбрать событие OnClick и дважды щелкнуть мышкой на пустой строчке справа от него;
  • просто дважды щелкнуть по компоненту Button1.

Delphi сгенерирует следующую "заготовку":

Procedure TForm1.Button1Click (Sender: TObject); begin end;

Цель приложения Methods - научить вас писать процедуры и передавать в них параметры. В частности, программа Methods реагирует на нажатие кнопки Button1 путем вызова процедуры EnteringALine и передачи ей в качестве параметра содержимого строки редактирования EditSumma (EditSumma.Text).

Procedure TForm1.Button1Click (Sender: TObject); begin EnteringALine(EditSumma.Text); end;

5. Важно понять, что объект EditSumma является экземпляром класса TEdit и, следовательно, имеет свойство Text. Оно содержит набранный в строке редактирования текст. Как вы уже, наверное, успели заметить, по умолчанию свойство Text содержит значение, совпадающее со значением имени компонента (Name) - в данном случае "EditSumma". Его можете редактировать как в режиме проектирования, так и во время выполнения.

6. Текст, который должен быть отображен в компонентах Memo1, Memo2, передается процедуре EnteringALine как параметр. Чтобы проделать это, просто напишите имя этой процедуры и заключите передаваемый параметр (параметры) в скобки следующим образом:

EnteringALine(EditSumma.Text);.

Заголовок этой процедуры выглядит следующим образом:

Procedure TForm1.EnteringALine(NewString: String);

где указано, что передаваемый процедуре параметр NewString должен иметь тип String.

Вспомните, что задача процедуры EnteringALine состоит в копировании содержимого строки редактирования EditSumma в компоненты Memo1, Memo2. Поэтому она должна выглядеть следующим образом:

Procedure TForm1.EnteringALine(NewString: String); var I,J,K:Integer; begin I:= StrToInt(Edit1.Text); J:=StrToInt(Edit2.Text); K:= I + J; EditSumma.Text:=IntToStr(K); Memo1.Text:=EditSumma.Text; Memo2.Text:=EditSumma.Text; end;

Поскольку процедура Entering-ALine не является откликом на какое-либо событие в Delphi, то ее нужно полностью написать "вручную". Простейший способ сделать это - копировать заголовок какой-либо уже имеющейся процедуры, исправить его, а затем дописать необходимый код.

7. Возвратимся еще раз к заголовку процедуры:

Procedure TForm1.EnteringALine(NewString: String);.

Он состоит из пяти частей:

  • Первая часть - зарезервированное слово "procedure". Оно служит определенным синтаксическим целям, а именно: информирует компилятор о том, что определен синтаксический блок "процедура".
  • Вторая часть заголовка - слово "TForm1", которое квалифицирует то обстоятельство, что данная процедура является методом класса TForm1.
  • Третья часть заголовка - имя процедуры, вы можете выбрать его любым, по вашему усмотрению. В данном случае названа процедура "EnteringALine".
  • Четвертая часть заголовка - параметр, он декларируется внутри скобок и, в свою очередь, состоит из двух частей. Первая часть - имя параметра, вторая часть - его тип, они разделены двоеточием.
  • Пятая часть - концевая точка с запятой (;), которая указывает на окончание заголовка (собственно говоря, почти все операторы в Delphi должны заканчиваться точкой с запятой).

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

Procedure Example(Param1: String; Param2: String);

8. После того как вы создали "вручную" заголовок процедуры, являющейся методом класса, вы должны включить его в декларацию класса. Например, путем копирования (еще раз напомню, что для методов, являющихся откликами на события, данное включение производится автоматически):


1. type 2. TForm1 = class(TForm) 3. Button1: TButton; 4. Memo1: TMemo; 5. Edit1: TEdit; 6. Memo2: TMemo; 7. Edit2: TEdit; 9. EditSumma: TEdit; 10. Label1: TLabel; 11. Label2: TLabel; 12. Label3: TLabel; 13. procedure Button1Click(Sender: TObject); 14. procedure EnteringALine(NewString: String); 15. private 16. { Private declarations } 17. public 18. { Public declarations } 19. end;

Четырнадцатый оператор по тексту вставлен "вручную".

В приведенном программном коде нет необходимости оставлять в заголовке метода слово "TForm1", так как оно уже присутствует в описании класса. Результат работы программы показан на рисунке 3.

Компонент ScrollBar.

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


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

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

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

Имеется два вида линеек прокрутки:

  • вертикальная (sbVertical);
  • горизонтальная (sbHorizontal).

Свойство Kind компонента ScrollBar служит переключателем между двумя состояниями.

Минимальные и максимальные значения диапазона прокручивания устанавливаются с использованием свойств Min и Max, которые могут принимать значения целого типа Integer в диапазоне от -32768 до +32767.

Свойство Position определяет текущую позицию бегунка линейки прокрутки. Установив начальное значение, указатель принимает заданное положение.

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

Свойство LargeChange определяет "большой" сдвиг бегунка. Оно устанавливает дискретность изменения позиции указателя, когда пользователь щелкает левой кнопкой мыши на серой области внутри линейки прокрутки, расположенной между указателем и кнопкой со стрелкой с каждого конца компонента ScrollBar. Применяется, например, при перемещении на одну страницу и осуществляется по щелчку мыши по поверхности компонента с соответствующей стороны от указателя или после нажатия клавиш PageUp или PageDown.

Событие property OnScroll: TScrollEvent;

TScrollEvent = procedure (Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer) of object;

вызывается после каждого изменения положения бегунка.

Обработчик события OnChange применяется, когда происходит изменение значений Max, Min, Position.

Значение ScrollCode определяет вид перемещения бегунка и имеет следующие параметры:

  • TScrollCode = (scLineUp, scLineDown, scPageUp, scPageDown, scPosition, scTrack, scTop, scBottom, scEndScroll);
  • scLineUp, scLineDown - на строку вверх, вниз;
  • scPageUp, scPageDown - на страницу вверх, вниз;
  • scTrack, scTop - в заданную позицию;
  • scTop, scBottom - в крайнее верхнее, нижнее положение;
  • ScEndScrol - извещает об окончании процесса прокрутки.

Рассмотрим пример использования компонента ScrollBar (размещение элементов на форме показано на рисунке 5). Данный пример позволит изменять цвет компонента Shape1 и цвет контура компонента Shape2, используя линейки прокрутки.


  1. Запустите Delphi.
  2. Сохраните файл модуля под именем ScrollB_.pas, а файл проекта - под именем ScrollB.dpr.
  3. Поместите на форму компоненты ScrollBar1, ScrollBar2, ScrollBar3 со страницы Standard палитры компонентов. Свойство Kind для данных компонентов оставьте, принятое по умолчанию sbHorizontal. Используя свойство Name, измените имена, принятые по умолчанию для компонентов ScrollBar на ScrollBarRed, ScrollBarGreen, ScrollBarBlue соответственно.
  4. Установите значение свойства Min для этих компонентов, равным 0, а значение свойства Max - равным 255.
  5. Поместите на форму компонент Shape1 со страницы Additional, установите для него свойство Shape равным stEllipse. Поместите на форму компонент Shape2, установите для него свойство Shape в инспекторе объекта на StRoundRect.
  6. Поместите компоненты Label1, Label2, Label3 на форму и, используя свойство Name, измените их имена на LabelRed, LabelGreen, LabelBlue соответственно.
  7. Поместите на форму компоненты TrackBar1, TrackBar2, TrackBar3 со страницы Win32 палитры компонентов.
  8. Поместите на форму компоненты Label3, Label4, Label5. Используя свойство Name, измените имена на LabelScrollRed, LabelScrollGreen, LabelScrollBlue соответственно.

Используя событие OnScroll на странице событий инспектора объекта для компонентов ScrollBar и событие OnChange для компонентов TrackBar, напишите в Редакторе кода следующий программный код:

Procedure TForm1.ScrollBarRedScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin {Свойство Position (положение) говорит о том, как позиционирована линейка прокрутки в данный момент времени. Это свойство содержит целую величину. Вы можете манипулировать этим свойством из программы, если вам нужно динамически изменять положение линейки прокрутки.} LabelRed.Caption:= " Значение красного цвета: " + IntToStr (ScrollPos); Shape1.Brush.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); Shape2.Pen.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); end; procedure TForm1.ScrollBarGreenScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin LabelGreen.Caption:= "Значение зеленого цвета: " + IntToStr(ScrollPos); Shape1.Brush.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); Shape2.Pen.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); end; procedure TForm1.ScrollBarBlueScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin LabelBlue.Caption:= "Значение голубого цвета: " + IntToStr(ScrollPos); Shape1.Brush.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); Shape2.Pen.Color:= RGB (ScrollBarRed.Position, ScrollBarGreen.Position, ScrollBarBlue.Position); Shape2.Pen.Width:=5; end; procedure TForm1.TrackBar1 Change(Sender: TObject); begin LabelScrollRed.Caption:= "Значение LargeChangeRed " + IntToStr(TrackBar1.Position); ScrollBarRed.LargeChange:= TrackBar1.Position; end; procedure TForm1.TrackBar2 Change(Sender: TObject); begin LabelScrollGreen.Caption:="Значение LargeChangeGreen" + IntToStr(TrackBar2.Position); ScrollBarGreen.LargeChange:= TrackBar2.Position; end; procedure TForm1.TrackBar3 Change(Sender: TObject); begin LabelScrollBlue.Caption:= "Значение LargeChangeBlue " + IntToStr(TrackBar3.Position); ScrollBarBlue.LargeChange:= TrackBar3.Position; end; end.

Результат работы программы Scroll показан на рисунке 6.


Литература:

  1. Марко Канту. Delphi 2 для Windows 95/NT. Москва. ООО "Малип". 1997 г.
  2. Джон Матчо. Дэвид Р. Фолкнер. Delphi. Москва. БИНОМ. 1995 г.
  3. Эндрю Возневич. Delphi. Освой самостоятельно. Москва. Восточная книжная компания. 1996 г.
  4. В.В.Фаронов. Delphi 5. Учебный курс. Москва. Издательство Нолидж. 2000 г.
  5. А. Я. Архангельский. Программирование в Delphi 5. Москва. ЗАО "Издательство Бином". 2000 г.

Владимир Скуратов

Исключительные ситуации и отладка приложений в Delphi 5

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

В зависимости от обстоятельств приложение должно по-разному реагировать в ответ на возникновение исключительной ситуации: в одних случаях оно может их «не замечать», то есть не показывать пользователю, а в других - оно просто обязано прервать свою работу. Обязательное требование - пользователь должен иметь возможность спасти несохраненные ранее данные. Приложение, которое ведет себя устойчиво в «плохих» условиях (если мало системных ресурсов, недостаточно места на диске или если пользователь совершает ошибки), именуется робастным . Робастное приложение можно создать только на языке программирования, который поддерживает обработку исключений. Предшественник Delphi - Borland Pascal - не поддерживал обработку исключений, но уже первая версия Delphi ее поддерживала.

Исключения как классы

При возникновении исключительной ситуации происходит генерация объекта, который описывает данное исключение. Этот объект (экземпляр класса) несет в себе информацию о типе исключения, например: деление на ноль, недостаточность системных ресурсов, переполнение переменной. Информация о типе исключения содержится в имени класса, то есть для исключений разного типа создаются экземпляры различных классов.

Кроме того, объект содержит текстовое описание исключения. Все исключения являются потомками класса Exception, у которого имеется свойство Message. В этом свойстве и содержится текстовая информация об исключении.

Помимо этой информации можно узнать адрес исключения, вызвав метод ExceptAddr. Если в приложении в момент вызова этого метода отсутствует объект исключения, то возвращается nil. Поэтому данный метод вызывают обычно в том месте приложения, где определенно присутствует объект Exception (except..end; Application.OnException).

Класс Exception интересен также тем, что он имеет восемь конструкторов. Можно создать объект из ресурсов, с параметрами, с информацией о том, к какому разделу помощи следует обращаться и т.д. Список классов, описывающих исключения, можно увидеть в Object Browser.

Распространение исключений

Рассмотрим следующий фрагмент кода: при щелчке кнопки вызывается метод OnClick, который, в свою очередь, вызывает метод Method1, а из него вызывается метод Method2. При нормальной работе приложения оно выполняет все методы, как это показано на рис. 1 .

Синим цветом отмечен поток исполняемых команд процессору, лиловым - выход из вызываемого метода. Если же, например, в Method2 происходит исключение, то генерируется объект, являющийся экземпляром класса - потомка Exception, а дальнейшее выполнение кода прерывается (рис. 2):

Как и ожидалось, код между finally и end выполнился и при наличии исключения. Именно из-за обязательного выполнения кода в эту область помещают методы, связанные с возвращением ресурсов системе, а блок try…finally…end называется блоком защиты ресурсов .

Теперь в примере выше заменим слово finally на слово except и вновь исследуем вызов данной процедуры при отсутствии (верхний ряд) и наличии (нижний ряд) исключения (рис. 5):

Как и следовало ожидать, при отсутствии исключения код между except и end не выполняется, а при наличии - выполняется. Однако коренное отличие данного блока от блока try…finally…end - это продолжение выполнения кода после произошедшего исключения. Диаграмма выполнения приложения при наличии исключения в этом случае выглядит следующим образом (рис. 6):

По этой причине блок try…except…end именуется ловушкой исключения - он не позволяет исключению прервать выполнение вызванного метода.

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

Работа с исключениями в блоке try…except…end

Анализировать исключение необходимо в тех местах приложения, где присутствует объект - экземпляр потомка Exception. В Delphi 5 можно локализовать три такие области:

  1. Блок try…except…end между except и end.
  2. Application.OnException.
  3. По-видимому, имеется возможность реализовать специальные методы, которые будут вызываться всякий раз, когда происходит исключение операционной системы при выполнении приложений.

Поскольку исключение по возможности следует анализировать на максимально низком уровне, то в основном анализ исключений осуществляется в блоке try…except…end. Операторы между except и end выполняются только при наличии исключения, поэтому для этого места блока предусмотрен специальный синтаксис для анализа исключений.

Как уже упоминалось, имя класса исключения несет в себе информацию о его типе. Для анализа типа исключений в блоке try…except…end используется следующий синтаксис:

Function TForm1.SaveFile(FN:string):integer; {Returns: 0 - saved OK; 1 – programmer has to repeat call of the procedure 2 - All bad, data are lost...} begin Result:=2; try {Save to file} Result:=0; except On E:EOutOfMemory do begin if MessageDlg(E.Message+". Close another application. Retry saving?", mtError,,0)=mrYes then Result:=1; end; On E:EInOutError do begin if MessageDlg(E.Message+". Free disk space. Retry save?", mtError,,0)=mrYes then Result:=1; end; On E:Exception do begin MessageDlg("You have lost data due to "+E.Message,mtError, , 0); end; On E:EMathError do ShowMessage("You will never see this message"); end; end;

Оператор On E:OutOfMemory do… выполняется только в том случае, если объект исключения является классом EOutOfMemory или его потомком . После оператора do c переменной E можно обращаться как с экземпляром класса. Например, как в данном случае, - извлечь текстовое сообщение и показать в диалоге.

Если же класс исключения не относится к EOutOfMemory, то проверяется его принадлежность к классу EInOutError. Если же исключение не относится к данному классу, то проверяется на принадлежность к классу Exception. Поскольку любое исключение является потомком Exception, то данный код будет выполняться всегда, кроме классов EOutOfMemory и EInOutError, для которых будут выполняться описанные выше коды. Поэтому если используют оператор:

On E:Exception do begin

то его всегда помещают в конце кода. В частности, в данном примере вы никогда не увидите диалога с надписью "You will never see this message" - это сообщение будет обработано ранее в секции On E:Exception do…

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

Директива Raise

Этот метод возбуждает исключение, то есть создает объект - экземпляр потомка Exception. В литературе различают использование метода Raise в коде приложения и в секции except..end. В коде приложения синтаксис метода raise выглядит, например, следующим образом:

Raise EConvertError.Create(‘Illegal value’);

После директивы указывается конструктор класса - потомка Exception. Немного по-другому используется этот метод в секции except..end - там просто вызывается эта директива:

Однако, несмотря на кажущееся различие, смысл этой директивы один и тот же, а именно - генерация исключения. Следует вспомнить, что в секции except…end уже имеется объект Exception. Поэтому не требуется конструировать объект - он уже есть.

Raise вне блока try…except используется для генерации исключений, созданных программистами. И хотя можно вызвать конструктор класса Exception, в силу ранее объясненных причин это не делается. Поэтому программист обязан объявлять свои классы для собственных исключений:

EMyException=class(Exception) end;

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

Raise EMyException.Create(‘Something bad happens…’);

Обработчик исключений Application.HandleException

Метод Application.HandleException принимает все исключения, для которых не расставлены ловушки в приложении. Если отсутствует обработчик события Application.OnException, то указанный метод показывает пользователю сообщение об ошибке и разрушает объект-исключение. Если имеется обработчик события Application.HandleException, то вместо показа диалога вызывается этот метод.

Обработчик события Application.OnException необходимо использовать в тех случаях, когда невозможно перехватить исключение ранее или когда такой перехват сопровождается написанием большого количества кода в разных частях приложения. В качестве параметров метод принимает Sender - экземпляр класса, где произошло исключение, и E:exception. Их можно проанализировать и выполнить соответствующие действия.

Удачным примером использования обработчика Application.OnException является работа с компонентом TOleContainer. Поставьте его на форму, запустите приложение на выполнение и дважды щелкните по OleContainer. Немедленно возникает исключение (рис. 7):

хотя представляется разумным при активации пустого OLE-контейнера вместо исключения вывести диалог для вставки OLE-объекта. OleContainer имеет метод DoVerb, который может вызываться различными способами: при получении фокуса ввода или двойном щелчке мыши. Замена исключения на диалог вставки объекта была бы обычным делом, если бы метод DoVerb был виртуальным или динамическим. В этом случае можно было бы создать класс-потомок и в нем переопределить метод DoVerb:

Type TMyOleContainer=class(TOleContainer) public procedure DoVerb(Verb: Integer); override; end; … procedure TMyOleContainer.DoVerb(Verb:integer); begin try inherited DoVerb(Verb); except InsertObjectDialog; end; end;

Но метод DoVerb объявлен как статический – и сделать ничего нельзя. В данном случае можно написать обработчик события Application.OnException:

Procedure TForm1.ShowException(Sender:TObject; E:exception); begin if (Sender is TOleContainer) and (E is EOleError) then TOleContainer(Sender).InsertObjectDialog else MessageDlg(E.Message,mtError,,0); end; procedure TForm1.FormCreate(Sender: TObject); begin Application.OnException:=ShowException; end;

Вместо приведенного выше назначения события OnException при создании главной формы приложения в Delphi 5 можно воспользоваться компонентом ApplicationEvents. Легко убедиться, что если на форму поместить два компонента TOLEContainer, то диалог будет корректно вызываться для того из них, который был активирован.

Данный пример хорошо показывает также и то, как не надо писать распространяемые компоненты. Если какой-либо метод вызывается автоматически, в ответ на реакцию от потока сообщений Windows, и в нем могут произойти исключения, то он должен быть объявлен виртуальным или динамическим. Программист, который будет использовать данный компонент, может придумать что-нибудь получше, чем показывать пользователю диалоговое окно с сообщением об исключении.

Команда Assert

Этот метод в качестве параметра принимает значение логической переменной, которое всегда должно быть равно True. Синтаксис команды:

Assert(Table1.Active);

Если значение логической переменной равно False, то происходит остановка приложения с диагностикой Assertion Failure. Метод Assert следует использовать там, где значение логического выражения ни при каких обстоятельствах не должно равняться False. Возникающая при нарушении логического выражения диагностика напоминает вывод отладчиков некоторых трансляторов (рис. 8):

Широкое использование этого метода настоятельно рекомендуется в таких приложениях, которые ориентированы на коммерческое распространение. При этом бета-тестеры программы могут просто позвонить в головную организацию и сообщить, в каком модуле и в какой строке кода произошла ошибка. Чтобы отключить все проверки Assert в проекте, достаточно изменить один параметр в опциях.

Защита ресурсов в приложениях

При выполнении приложения часто необходимо брать ресурсы у операционной системы – создать экземпляр класса, выделить память, открыть файл и т.д. По правилам программирования в Windows, ресурсы следует возвратить операционной системе, если они больше не требуются для выполнения приложения. Мы уже знаем, что для защиты ресурсов необходимо использовать защищенный блок try..finally..end. Но если ресурсы не были зарезервированы, а программист пытается их освободить, то при этом также произойдут исключения, которых легко избежать, если придерживаться простых правил, например:

Procedure TForm1.Button3Click(Sender: TObject); var P:pointer; N:integer; begin try N:=StrToInt(Edit1.Text); GetMem(P,N); {Some operations} finally FreeMem(P); end; end;

С виду все правильно: резервируются ресурсы GetMem, а их освобождение происходит в защищенном блоке. Но если исключение произойдет ранее - при конвертации строки в целое число, то память не будет выделена. При этом значение указателя P является случайным - так называемый дикий указатель (wild pointer). При вызове оператора FreeMem произойдет уже повторное исключение EAccessViolation. Поэтому перед резервированием системных ресурсов ссылки на них необходимо всегда инициализировать пустыми значениями, а перед освобождением проверять их. Корректный код для примера выше выглядит следующим образом:

Procedure TForm1.Button3Click(Sender: TObject); var P:pointer; N:integer; begin P:=nil; try N:=StrToInt(Edit1.Text); GetMem(P,N); {Some operations} finally if Assigned(P) then FreeMem(P); end; end;

Для защиты файлов необходимо использовать директивы TFileRec и TTextRec:

Procedure TForm1.Button4Click(Sender: TObject); var FText:TextFile; FBin:File; begin TTextRec(FText).Mode:=fmClosed; {Data initialization} TFileRec(FBin).Mode:=fmClosed; try {DoSomething1} AssignFile(FText,"C:\TEST.TXT"); Rewrite(FText); {DoSomething2} AssignFile(FBin,"C:\TEST.BIN"); Rewrite(FBin,1); {DoSomething3} finally if TTextRec(FText).Mode<>fmClosed then CloseFile(FText); if TFileRec(FBin).Mode<>fmClosed then CloseFile(FBin); end; end;

Опции проекта, влияющие на отладку приложений

Опции, которые будут описаны ниже, доступны из команды меню Projects/Options, закладка Compiler. Их грамотное использование позволяет существенно упростить отладку приложений и избежать возможных ошибок.

  1. Range Checking. При включенной этой опции проверяются диапазоны допустимых значений целочисленных переменных, и если во время выполнения какая-либо переменная выходит за пределы допустимых значений, то генерируется исключение. Рассмотрим следующий фрагмент кода: procedure TForm1.Button1Click(Sender: TObject); var B1,B2,B3:byte; begin ... B1:=200; B2:=200; B3:=B1+B2; ... end;

    Диапазон допустимых значений для переменной типа byte 0..255, а в результате выполнения кода получим значение 400. При включенной опции Range Checking произойдет исключение, и программист легко обнаружит эту ошибку и внесет необходимые изменения в код. При отключенной же опции Range Checking исключения не будет, а значение переменной B3 будет содержать 8 самых младших битов результата.

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

    Procedure TForm1.Button1Click(Sender: TObject); var A:array of integer; I,B:integer; begin ... B:=0; for I:=1 to 15 do begin if I<15 then B:=B+A[I] else A[I]:=B; end; ... end;

    В цикле происходит чтение данных из элементов массива A..A, память под хранение которых не была зарезервирована в стеке. С включенной опцией Range Checking немедленно происходит исключение, а с отключенной опцией код выполняется и происходит чтение данных из области памяти, занятой другими переменными. Ясно, что результат такого расчета является абсолютно бессмысленным. Но самые большие неприятности ожидают нас в данном коде при последнем проходе цикла (I=15). В этом случае данные записываются в несуществующий 15-й элемент массива, и эта команда будет успешно выполнена при отключенной опции Range Checking! Записанное значение изменяет значения других переменных и даже может попасть в область исполняемого кода. При этом приложение работает вполне нормально до тех пор, пока не происходит обращение к данной области памяти, а это может быть логически далеко от места возникновения ошибки. По указанной причине обнаружение таких ошибок очень затруднительно - участок кода, где она проявляется, уже может быть идеально отлажен.

    Казалось бы, необходимо все время пользоваться включенной опцией Range Checking. Однако ее использование заметно увеличивает размер исполняемого файла, а если используются только целочисленные операции, то время выполнения замедляется более чем в 10 раз! Поэтому ее настоятельно рекомендуется использовать при создании и отладке приложений, а при передаче проекта конечному пользователю ее необходимо отключать.

  2. Overflow Checking. При включенной опции проверяются значения переменных с плавающей запятой на диапазон допустимых значений. Если, например, возвести в квадрат переменную, значение которой 1E20, а результат присвоить переменной типа single, то при включенной опции произойдет исключение, так как максимальное значение переменной типа single 3.4E38. Как и в предыдущем случае, при отладке приложения необходимо включать эту опцию, а при передаче приложения конечному пользователю - отключать.
  3. I/O checking. Borland Pascal - предшественник Delphi - не поддерживал обработку исключительных ситуаций, и при программировании на этом языке необходимо было делать массу проверок, перед тем как выполнить какое-либо действие. Однако существует класс ошибок, потенциальное возникновение которых часто невозможно обнаружить посредством проверок, - это ошибки ввода-вывода. Например, никакая проверка не защитит от ситуации, когда пользователь во время записи данных на дискету вынимает ее из дисковода. Поэтому в Borland Pascal имелась функция IOResult, которая возвращала переменную типа integer. Если не было ошибок ввода-вывода с момента предыдущего обращения к этой функции, то возвращаемое значение равнялось 0. При наличии же ошибок возвращался ненулевой результат. При возникновении ошибки ввода-вывода все операции по вводу-выводу блокировались до вызова функции IOResult. Рассмотрим следующий фрагмент кода: procedure TForm1.Button1Click(Sender: TObject); var F1,F2,F3:TextFile; S:string; begin IOResult; AssignFile(F1,"J:\TEST.TXT"); Rewrite(F1); Writeln(F1,"Test"); CloseFile(F1); AssignFile(F2,"C:\TEST.TXT"); Reset(F2); Readln(F2,S); CloseFile(F2); IOResult; AssignFile(F3,"C:\TEST.TXT"); Reset(F3); Readln(F3,S); CloseFile(F3); end;

    Предположим, что устройство J: - это лазерный диск, на который нельзя записывать. Поэтому при выполнении оператора Rewrite(F1) происходит ошибка ввода-вывода, а значит, дальнейшие операции по вводу-выводу блокируются. Если файл C:\TEST.TXT существует и содержит значимую информацию, то команда Readln(F2,S) ничего не прочтет из этого файла, и только после вызова IOResult команда Readln(F3,S) вернет первую строку из файла C:\TEST.TXT.

    Такой метод анализа ошибок ввода-вывода и сейчас применим в Delphi при отключенной опции I/O checking. При включенной же опции в случае ошибки ввода-вывода генерируется исключение, которое можно обнаружить и проанализировать. Этот метод - более прогрессивный, но многие программисты, работавшие ранее с Pascal, предпочитают вызов IOResult. В заключение следует добавить, что если выполняется групповая разработка проекта, то у всех участников эта опция должна быть либо включена, либо выключена.

  4. Complete Boolean Evaluation. Рассмотрим, каким образом в VCL Delphi определяется наличие непустого списка, например, ширин столбцов в TStringGrid: if Assigned(FWidths) and (FWidths.Count>0) then…

    Данный код скомпилирован в режиме с отключенной опцией Complete Boolean Evaluation. В этом случае первоначально производится проверка истинности выражения Assigned(FWidths). Если оно истинно, то далее проверяется следующее условие после and, а при ложном значении дальнейшая проверка прекращается. Если же включена опция Complete Boolean Evaluation, то проверка происходит даже тогда, когда первая часть выражения равна False. При этом происходит попытка обращения к объекту с указателем nil, что немедленно приводит к генерации исключения.

    Здесь существует категорическая рекомендация писать код, который работает с отключенной опцией Complete Boolean Evaluation. Написание такого кода означает, что если, например, происходит обращение к функции, которая возвращает результат типа Boolean, и ее необходимо всегда вызывать (кроме результата функция может выполнять и другие необходимые процедуры), то вызов этой функции должен быть первым после оператора if. Соответственно при получении кода со стороны (например, распространяемого как компонента) необходимо потратить некоторое время для выяснения, включить или выключить при компиляции кода опцию Complete Boolean Evaluation, и при необходимости внести требующиеся поправки.

  5. Debug Information. Отладчиком Delphi можно пользоваться только если данная опция будет включена. Однако при ее использовании увеличивается размер окончательного *.exe файла, хотя на время выполнения операций эта опция не влияет. Ее рекомендуется отключать перед передачей приложения конечному пользователю.
  6. Assertions. Эта опция включает или отключает описанную выше команду Assert. Поэтому данной командой можно смело пользоваться в коде повсеместно: для ее удаления не требуется убирать строки из кода, а достаточно лишь отключить эту опцию.

Отладка удаленных приложений

Для тестирования удаленного отладчика необходимо два компьютера, в которых:

  1. Имеется легальный IP-адрес. Желательно проверить связь утилитой Ping.
  2. Разрешен полный доступ (Share) к дискам.

Компьютер-сервер : запускается удаленный отладчик. Перед этим его отдельно следует установить с диска Delphi 5. Удаленный отладчик запускается при помощи команд: Start/Program Files/Borland Remote Debugger/Remote Debugger.

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

  1. Project/Options/Linker/Include Remote Debug - ставится флаг.
  2. Run/Parameters/Remote:

    а) Remote Path - путь к приложению, как его «видит» сервер, то есть локальная директория на сервере, например D:\Project1.exe;

    б) Remote Host - имя компьютера или его IP-адрес, например KLASEC04 или 10.10.10.64;

    с) ставится флаг Debug Project On Remote Machine.

  3. Project/Options/Directories/Output Directory устанавливается путь к серверу, например \\KLASEC04\D.

Следует обратить внимание, что в подпункте 2а и пункте 3 устанавливаются ссылки на одну и ту же директорию, только в одном случае путь записывается с точки зрения локальной директории сервера, а в другом - с точки зрения «гостя».

После этого можно начинать тестирование удаленного отладчика.

Breakpoint actions, breakpoint groups: новые свойства точек прерывания

В прежних версиях Delphi точки прерывания были предназначены только для остановки процесса выполнения в режиме отладки. В Delphi 5 можно указать, какие именно действия (breakpoint actions) следует выполнить в момент достижения точки остановки: приостановить выполнение (как в прежних версиях Delphi); добавить текстовое сообщение в log-файл для регистрации событий отладчика (event log); записать в log-файл результат вычисления выражения, содержащего переменные отлаживаемого процесса (или вычислить выражение и результат никуда не записывать); сделать доступной или недоступной группу точек прерывания (о группах будет сказано ниже). Можно также одновременно выполнить несколько действий в одной точке прерывания (рис. 9).

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

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

В Delphi 5 появилась возможность ставить точки прерывания не только на выполнение какого-либо кода, но и на изменение данных. Рассмотрим фрагмент кода:

Var K:integer=0; procedure TForm1.Button1Click(Sender: TObject); begin K:=K+1; Caption:=IntToStr(K); end; procedure TForm1.Button2Click(Sender: TObject); begin K:=K+2; Caption:=IntToStr(K); end;

Здесь объявлена глобальная переменная K. Предположим, что эта переменная может модифицироваться из различных методов данного проекта и что в результате запущенного процесса K имеет «нелегальное» значение. При традиционной отладке необходимо разыскать в коде все места, где происходит изменение этой переменной, и поставить там точки прерывания. Если таких мест - целая сотня, то программиста ожидает большая работа. В Delphi 5 можно поступить следующим образом:

  1. Запустить приложение из-под среды разработки.
  2. Поставить курсор в строку “K:integer=0;” и вызвать команду меню Run/Add Breakpoint/Data Breakpoint.
  3. В появляющемся диалоге в контроль Address ввести имя переменной K.

После выполнения этой операции появится точка прерывания при изменении данных. В данном проекте при нажатии первой кнопки управление процессом будет передано отладчику и курсор отладчика будет находиться в строке K:=K+1;. При нажатии же второй кнопки управление также передается отладчику, причем курсор будет находиться в строке K:=K+2.

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

Другие полезные нововведения

С помощью пункта меню Run/ Attach to Process можно начать отлаживать любой из уже запущенных процессов, в том числе не имеющий отношения к Delphi. Процесс, подлежащий отладке, можно выбрать из соответствующего диалога (рис. 10):

С помощью выбора пункта меню Run/Run Until Return в процессе пошаговой отладки процедуры или функции можно заставить отладчик выполнить оставшийся код процедуры в нормальном режиме, что обеспечит немалую экономию времени.

При отладке многопоточных приложений можно устанавливать разные опции отладчика для различных потоков.

Помимо окна просмотра CPU, в Delphi 5 имеется также окно просмотра FPU (Floating Point Unit), позволяющее получить информацию о регистрах FPU, флагах и др.

Отметим также, что среда разработки Delphi 5 поддерживает операции drag-and-drop во время отладки. Например, из редактора кода можно перенести выражение в окно Watch List, после чего это выражение останется в соответствующем списке. Можно перенести данное выражение в Debug Inspector или на панель, содержащую дамп памяти в окне CPU, и получить его адрес.

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

Отметим также, что список исключений, которые можно игнорировать при использовании Delphi, пополнился исключениями, связанными с использованием библиотек ADO, внутренними исключениями VisiBroker, а также пользовательскими исключениями.

Заключение

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

КомпьютерПресс 5"2001

Вы готовы создавать лучшие пользовательские интерфейсы в своей жизни? Наш фреймворк библиотеки визуальных компонентов (VCL) для Windows и визуальная среда FireMonkey (FMX) для межплатформенных пользовательских интерфейсов обеспечивают основу для создания интуитивных и красивых пользовательских интерфейсов, поражающих на любой платформе: Windows, macOS, iOS и Android.

Пишите код быстрее и лучше с помощью Delphi

Разработчики и команды разработчиков ПО, следующие идеологии Agile, смогут писать код быстрее и лучше с помощью современных практик ООП, надежных фреймворков Delphi и функциональной интегрированной среды разработки.

  • Проводите меньше времени в ожидании завершения продолжительной компиляции благодаря нашим хорошо оптимизированным компиляторам для всех платформ
  • Выберите один из двух мощных и надежных языков (Delphi и усовершенствованный C++) и настройте среду разработки в соответствии со своим стилем написания кода
  • Code Insight™ обеспечивает автоматическое дополнение кода на основании уже написанного кода и используемых библиотек, чтобы ускорить и упростить дальнейшее написание кода
  • Получайте советы и подсказки из встроенной документации по мере написания кода
  • Сохраняйте гибкость процесса разработки с помощью дизайнера библиотеки визуальных компонентов, реструктуризации исходного кода в рамках методологии Agile и интерактивных шаблонов
  • Интегрируйте систему контроля версий, включая Git, Subversion и Mercurial

Более быстрая отладка с помощью интегрированных средств Delphi для отладки кода для инструментальной платформы?

Быстрее добирайтесь до первопричины ошибки за счет использования интегрированной межплатформенной отладки кода для инструментальной платформы. При помощи интегрированной среды разработки Delphi можно осуществлять отладку приложений, работающих дистанционно под операционными системами Windows, macOS, iOS, Android и Linux.

  • Добавляйте условные точки прерывания, чтобы быстро приостанавливать исполнение программы в указанном положении или при наступлении определенного условия.
  • Анализируйте стек вызовов целиком, чтобы иметь возможность отследить путь исполняемого кода до текущего положения.
  • Проверяйте текущие значения переменных во время приостановки программы в ходе отладки.
  • Проводите отладку на любом устройстве. Разверните приложение на любом устройстве, работающем под операционной системой iOS, Android или macOS, чтобы провести его отладку так же, как если бы приложение работало локально. Воспользуйтесь точками прерывания, анализом стека вызовов, всплывающими подсказками и функцией вычисления выражений на локальных и дистанционных машинах, проводя отладку на всех развернутых платформах.


Компилируйте и развертывайте приложение с помощью Delphi

Создавайте приложения для предпочитаемых платформ своих пользователей. С помощью Delphi создавайте приложения для настольных и мобильных систем из одной кодовой базы и развертывайте их для Windows, macOS, iOS, Android и Linux.

  • Специально для App Store. Быстро создавайте комплекты приложений, которые можно развертывать в Windows Store (с помощью Desktop Bridge), Apple App Store и магазине Google Play
  • Определите файлы для развертывания на конкретной платформе и создайте конфигурацию. Внутри каждого проекта разработчики могут определять файлы для развертывания в зависимости от целевой платформы (например, Windows, macOS, Android, iOS, Linux), а также создавать конфигурации (например, «Отладка» или «Выпуск»)
  • Развертывайте файлы непосредственно из интегрированной среды разработки Delphi. Быстро развертывайте файлы на удаленных машинах с использованием Platform Assistant Server (PA Server). PA Server объединяет файлы, определенные для развертывания, и упаковывает их в один экземпляр приложения.


Повысьте качество своего кода с помощью Delphi

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

  • Сделайте свой код лучше, используя хорошо проверенные и высокооптимизированные межплатформенные библиотеки.
  • Превратите документацию на созданный код во включаемую напрямую справочную информацию, которая доступна как вам, так и другим разработчикам группы.
  • Создавайте тесты для компонентов во всем объеме своего кода, используя включенные фреймворки DUnit и DUnitX.
  • Наблюдайте за тем, что происходит внутри приложения, не прерывая его работу. Добавляйте журналирование в реальном времени для любого приложения с помощью функции CodeSite Logging


Сотрудничайте более эффективно с помощью Delphi

Функции сотрудничества и контроля версий Delphi позволяют быстрее создавать более качественные продукты при независимой работе разработчика или его деятельности в составе группы. Code Collaboration обеспечивает более глубокое и точное понимание кода, более высокое качество тестирования, а также создание усовершенствованных продуктов.

  • Отслеживайте изменения и управляйте ими с помощью систем контроля версий, включая репозитории Subversion, Git и Mercurial
  • Переходите между изменениями и отслеживайте их историю во вкладке «История» в модуле просмотра кода с помощью встроенного просмотрщика различий
  • Use Delphi command line compilers that are ideal for integrating into continuous build configurations quickly using our support for MSBuild or CMake projects.


Расширяйте интегрированную среду разработки Delphi

Delphi включает в себя сотни компонентов, обеспечивающих все необходимое: от создания пользовательских интерфейсов до подключения к базам данных. Это ускоряет и упрощает построение бизнес-приложений для настольных компьютеров и мобильных платформ. Помимо встроенных компонентов VCL и FireMonkey доступен широкий ассортимент инструментов и компонентов, предлагаемых сообществами Delphi и C++Builder.

  • Менеджер пакетов GetIt. Быстро расширяйте функциональность своих приложений, загружая и интегрируя новые компоненты.
  • Создание приложений для Интернета вещей. Быстро добавляйте в интегрированную среду разработки Delphi возможности Интернета вещей. Более 50 компонентов для Интернета вещей доступны БЕСПЛАТНО через GetIt.
  • Расширяйте интегрированную среду разработки с помощью инструментов и компонентов от партнеров компании Embarcadero Technologies.
  • Интегрированные инструменты и компоненты. Beyond Compare, FastReport, TeeChart, InterBase, IP*Works, CodeSight!
  • Расширяйте интегрированную среду разработки с помощью расширений и дополнений, созданных десятками сторонних лиц, чтобы настроить ее так, как хочется именно вам



Мобильные устройства

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

Internet of Things (IoT)

Легко подключайте свои приложения к гаджетам, устройствам, датчикам, корпоративным сервисам передачи и обработки данных.

Облако

Delphi имеется клиентская библиотека HTTP и REST, доступная для всех платформ и позволяющая вызывать не только REST-сервисы, но даже и специфические компоненты AWS и Azure.

Расширения

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

Проектируйте, создавайте, запускайте

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

Delphi XE5 я взял в руки по случаю конкурса «Осенняя Мобилизация». Идея (и возможность) писать под Андроид не на си-шарпе или яве, а на знакомом вдоль и поперёк паскале мне определённо понравилась. Расскажу тут о своих впечатления, проблемах, которые встретились, а также развенчаю некоторые «городские легенды».

Использовал триал-версию Update-1. Теперь уже вроде второй апдейт вышел и, возможно, что-то поменялось. Сразу замечу, что менять в установке настройки по умолчанию лучше не стоит. Установленный до этого Андроид-SDK прицепить к Делфи не удалось, поэтому ставил заново с тем, который к ней прилагается. После первого запуска выяснилось, что не работает Хелп. Нашёл решение
support.embarcadero.com/article/43035

Хелп оказался толковый и довольно подробный. Содержит не только свойства и методы, но и примеры и даже описание методик разработки. В общем, возвращение к истокам, как оно было ещё у Борланда.

Cама среда мне очень нравится. В Визуал Студио всё какое-то аморфное и невнятное. Юнити визуально неплох, но там совсем другая специфика. Короче – язык программиста всё равно не опишет то, что видит глаз эстета, даже если они принадлежат одному человеку…

Интерфейс пользователя
FireMonkey порадовал своей гибкостью. На любой контрол можно повесить другой, на тот ещё один, и так далее, достигая очень интересных результатов. По сравнению с VCL стандартизовано именование свойств. Никаких больше Caption’ов и прочего, если где-то есть текст – это всегда Text. Позиция – всегда Position. Масса способов выравнивания. Кроме того, есть TLayout – нечто «невещественное» (об этом будет и ниже), невидимое, на что можно положить контролы и выравнивать их «в пустоте», а не обязательно на какой-нибудь панели.

Когда много всего на форме, становится очень полезным свойство DesignVisible – скрыть в дизайн-тайме. Набор стилей для Андроида прилагался только один, но очень элегантный – белым по чёрному, как мне нравится.
В инете ходят слухи, что ссылки на стиль для контрола (StyleLookup) иногда «не сохраняются». Для многих типов контролов (а может и для всех) существует для каждого своя ссылка «по умолчанию», которая будет назначена, даже если не указана, и которая-то и не сохраняется, как я понимаю, для экономии места в ресурсе формы.

Контролу можно добавить анимацию, и даже несколько, и даже одновременно. И это не только перемещение по экрану, но и изменение любых вещественно-численных свойств (размеров, цвета, масштаба и т.д.). Для каждой анимации можно указать временную задержку её начала, что очень удобно в сложных случаях, т.к. можно обойтись без дополнительных таймеров, просто запустив все нужные анимации одновременно из одного блока кода.

Теперь о жестах. В принципе всё просто – назначаем контролу Touch.GestureManager, галочками помечаем интересующие жесты, назначаем искусственное расширение границ ловли жестов (если контрол мелкий) в TouchTargetExpantion, создаём для него событие OnGesture и ловим там по EventInfo.GestureID нужный жест. Но есть тонкости.

Например, на большом TLayout мы разместили какие-то мелкие (относительно него) контролы и независимо от того, насколько «попал» пользователь пальцем по этим контролам своим жестом, надо что-то там делать. Замечу – если всё описанное в абзаце выше сделано для этого TLayout, то мы поймаем только те жесты, начало которых приходится на «видимые» объекты – т.е. на один из тех самых мелких контролов. Это я определил экспериментально. В принципе ничего удивительного – лайоута-то как бы и нет, он невидим и виртуален, и все «экранные сообщения», которые он может получить – от положенных на него «видимых» объектов. Можно сделать по-другому - не лениться, назначить менеджера и создать событие для формы (как и делается в демках) и гарантированно его всегда получать – но тогда придётся вручную разбираться с координатами, чтобы определить, к какому контролу какой жест относится.

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

И пример. Долго не мог сообразить, как показать баннер в TWebBrowser. Решение нашёл на одном форуме и творчески переработал. Но, если быть уж совсем точным, не до конца. Практикующие перфекционисты могут поразвлечься и этот недочёт поискать. Однако код при этом абсолютно рабочий и именно его я использую:

Procedure ShowHtml(WebBrowser: TWebBrowser; const Html: string); {$IF DEFINED(ANDROID)} const tempFile: string = "/sdcard/Download/temp.htm"; filePrefix: string = "file:/"; var StrList: TStringList; MemStrem: TMemoryStream; begin with WebBrowser do try StrList:= TStringList.Create; StrList.Text:= Html; StrList.SaveToFile(tempFile); URL:= ""; Navigate(filePrefix + tempFile); finally DeleteFile(filePrefix + tempFile); StrList.Free; end; {$ELSE} begin {$ENDIF} end;
HTML тут – это код этого самого банера.

Базы данных

В XE5 включён набор компонентов для универсального доступа к базам данных – FireDAC. В принципе все названия свойств и методов как у других аналогичных наборов, так что тут всё ясно. Я использовал его для общения с SQLite. Всё настолько просто и обычно, что даже не знаю, что рассказать. К тому же и не помню ничего – в это время смотрел что-то по медиаплейеру, руки сами всё сделали.

Чтобы почувствовать разницу, желающие могут для сравнения после FireDAC сделать что-нибудь с базой данных из программы на той же Юнити. Да ладно Юнити, она игровая, – вон из той же Визуал Студии. После этого начинаешь понимать, где пули свистят, а где туземки коктейли разносят…

Ну и для любителей делать всё своими руками приведу небольшой пример, как заполнять ListBox без Bindings:

Procedure TSomeForm.FillList(aList: TListBox; BegDate, EndDate: TDateTime); var aItem: TListBoxItem; begin aList.Items.Clear; with SomeQuery do try ParamByName("beg_date").AsDateTime:= BegDate; ParamByName("end_date").AsDateTime:= EndDate; Open; while not EOF do begin aItem:= TListBoxItem.Create(aList); aItem.StyleLookup:= "listboxitemrightdetail"; aItem.Tag:= FieldByName("id").AsInteger; aItem.Text:= Format("%s (%s) "%s"", ); case FieldByName("d_result").AsInteger of -1: aItem.ItemData.Bitmap.Assign(NoImage.Bitmap); 0: aItem.ItemData.Bitmap.Assign(WaitImage.Bitmap); 1: aItem.ItemData.Bitmap.Assign(YesImage.Bitmap); end; aItem.ItemData.Detail:= FormatDateTime("dd-mmm-yy", FieldByName("d_date").AsDateTime); aItem.ItemData.Accessory:= TListBoxItemData.TAccessory.aMore; aList.AddObject(aItem); Next; end; finally Close; end; end;

Кроме всего прочего, в зависимости от кода в столбце d_result в строчку лист-бокса помещается та или иная картинка:

AItem.ItemData.Bitmap.Assign

Главное, что тут не забыть – это aList.AddObject(aItem);

Ну и Next, конечно, чтобы не зависло.

Манипуляции с формами

То, к чему приучает Делфи – это каждому действию свою форму. Под Андроидом в ней можно точно так же, как и под Виндоуз, создавать, показывать и закрывать формы. Каждая новая так или иначе созданная и показанная форма будет как бы «модальной», т.е. закрывающей всё пространство приложения. Однако Form.ShowModal делать не следует (Андроид этого «не понимает»), а следует по старинке просто вызывать Form.Show. По системной кнопке Back автоматом вызывается Form.Close и самая верхняя на данный момент форма закрывается. Можно её потом опять использовать. При закрытии главной (первой) формы приложение, как и следовало ожидать, закрывается. Замечу, что не следует закрывать форму с параметром caFree либо явно её уничтожать (Free, Release) – не любит Андроид этого!

Подсчёт ссылок.

Читал в инете про проблемы у людей с ARC. Уверен, дело не в этом. Если всё правильно спроектировано, то вообще без разницы, считаются ссылки или нет, ходит там сборщик мусора с косой по расписанию как в.Net или уничтожается сразу как в Delphi. Я всё писал по-старинке:

Try Create; finally Free; end

И работало как часы и под Андроидом, и под Виндами.

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

Массивы

При разработке под мобильный компилятор в руководстве по адаптации кода сказано «не использовать статические массивы». Указано также одно исключение – когда статический массив является членом структуры. И всё. Не совсем ясно, относится ли это к константам-массивам. Например, таким как

Const SomeNames: array of string = (‘First’, ‘Last’);

Не исключено, что так делать можно, хотя я такого старался избегать и формировал массивы строк в initialization динамически. В си-шарпе там хоть это можно в описании делать… Короче, вопрос требует дальнейшего исследования и разъяснения.
Следует также помнить, что элементы строки (string) в мобильном компиляторе нумеруются с нуля.

Операторы

Появился (уж не знаю в какой версии) новый оператор

For item in container do
Похоже, все языки стремятся к общему знаменателю. Кстати, перебирать им в паскале можно не только массивы, но и множества.

Вопросы и ценные замечания приветствуются.

Новое на сайте

>

Самое популярное