Главная » Delphi » Новые возможности  Delphi 6

0

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

Варианты

Ранее  поддержку  типа  данных  Variant осуществлял сам компилятор, теперь она реализована в составе  специального модуля Variants, отвечающего за пользователь ские типы данных.

Значения перечислимого типа

Для большей совместимости с языком C++ нынешний компилятор способен при

сваивать значения элементам перечислимого типа, как в данном примере:

type

TFoo = (fTwo=2, fFour=4, fSix=6, fEight=8);1 Метод идентификации  расположения файла на удаленном сервере  с помощью соглашения Uniform

Naming Convention (UNC). Имена UNC начинаются с символов  \\. — Прим. ред.

Директива $IF

Еще  одна  долгожданная  возможность —   директива  $IF дополнена  директивой

$ELSEIF, что позволяет не только проверять наличие предопределенных идентифи 

каторов, но и выполнять сложные логические операции с использованием констант,

как и показано ниже:

{$IF Defined(MSWINDOWS) and SomeConstant >= 6}

// Если определен идентификатор MSWINDOWS и SomeConstant больше

// или равно 6, то выполнять операторы, расположенные здесь

{$ELSEIF SomeConstant < 2}

// В противном случае, если SomeConstant меньше 2, то выполнять

// операторы, расположенные здесь

{$ELSE}

// Во всех остальных случаях выполнять операторы, расположенные

// здесь

{$ENDIF}

Потенциальная несовместимость бинарных DFM

Механизм хранения и загрузки форм Delphi из потока (DFM — Delphi  Forms  Mechanism) изменился, преимущественно в области представления символов ASCII, номера кото рых  больше  127 (вторая половина таблицы). Прежние версии Delphi  не смогут про читать  бинарный  код  DFM,  содержащий  символы  из  второй  половины  таблицы ASCII. Совместимы лишь текстовые версии файлов хранения форм.

Переход от Delphi 5

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

Переприсвоение типизированных констант

Теперь, в отличие от  предыдущих версий,  переключатель компилятора  $J (известный также как $WRITEABLECONST) по умолчанию выключен. Это означает, что попытки присваивать значение типизированной  константе приведет к возникнове нию ошибки во время  компиляции, если не разрешить такую возможность явно,  при менив директиву $J+.

Унарное вычитание

До версии 6 Delphi  использовал для выполнения операции унарного вычитания чисел  типа  Cardinal 32 разрядную арифметику. Это могло  привести к непредвиден ным результатам. Рассмотрим следующий фрагмент кода:var

c: Cardinal;

i: Int64;

begin

c := 4294967294;

i := -c;

WriteLn(i);

end;

Delphi 5 отобразит значение i как 2. Хоть это и неправильно, но на подобное по ведение иногда  и рассчитывают при  разработке программ. Если подобный код имеет место,  то при переходе на Delphi 6 возникнут проблемы, поскольку  теперь эта ошибка исправлена: приведение типа  Cardinal к Int64 будет выполнено до вычитания. По этому результирующим значением переменной i в Delphi  6 будет 4294967294.

Переход от Delphi 4

Настоящий раздел  посвящен ряду  проблем, с которыми можно  столкнуться при переходе от Delphi  4.

Проблемы  RTL

Единственная проблема, с которой придется иметь  дело,  связана с установкой управляющего  слова   обработки  вещественных  чисел   (FPU)   в  библиотеках   DLL. В предыдущих версиях Delphi  подпрограммы библиотек DLL имели  право  устанавли вать управляющее слово FPU, а следовательно, и изменять его значение, заданное при запуске  основного приложения. В новой версии в коде  инициализации библиотек DLL  установить значение  управляющего слова  FPU  больше  нельзя. Если  установка этого  управляющего слова  необходима для достижения некоторого особого поведе ния FPU, следует выполнить ее вручную, вызвав  функцию Set8087(), определенную в модуле System.

Проблемы  VCL

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

•  Тип  свойства, представляющего индекс  в списке  графических изображений, был изменен с Integer на тип  TImageIndex. Тип  TImageIndex —  это  строго типизированное целое, определяемое в модуле ImgList следующим образом:

TImageIndex = type Integer;

Проблемы такого рода могут возникнуть только в тех случаях, когда необходи

мо точное соответствие типов (например при передаче var параметров).

•  В  методе   TCustomTreeview.CustomDrawItem() появился  новый  var пара метр  типа Boolean, называющийся PaintImages. Если в приложении этот  ме тод  переопределен, то  потребуется добавить в него  этот  параметр, иначе  ус пешная компиляция в Delphi  5 или выше будет невозможна.•  Если  приложение Delphi 4 выводит контекстные меню  в ответ  на сообщение WM_RBUTTONUP или  при  обработке события OnMouseUp, то после  его  компиля ции  в Delphi  5 и выше  оно  будет выводить либо  “удвоенные”  контекстные ме ню, либо совсем  прекратит их вывод.  Теперь в Delphi  для организации вывода контекстного меню используется сообщение WM_CONTEXTMENU.

Проблемы приложений для Internet

Для тех, кто занят разработкой приложений для Internet, у нас есть как плохие но

вости, так и хорошие.

•   Компонент TWebBrowser, инкапсулирующий элементы управления ActiveX для Microsoft Internet  Explorer, заменил в новой версии Delphi  компонент THTML компании  Netmasters. Компонент  TWebBrowser имеет   существенно  больший диапазон возможностей, но при  замене  им компонента THTML потребуется зна чительная переработка приложений, так как интерфейсы этих компонентов различны. Если нет желания вносить изменения в уже созданные приложения, можно  обеспечить использование в них  прежнего компонента, для чего  необ ходимо  импортировать файл  HTML.OCX, расположенный в каталоге \Info\ Extras\NetManage на инсталляционном компакт диске.

•   Теперь при создании библиотек DLL ISAPI и NSAPI обеспечивается поддержка пакетов. Чтобы воспользоваться этой  возможностью, достаточно заменить в разделе uses модуль HTTPApp модулем WebBroker.

Проблемы баз данных

При  переводе из  Delphi  4 приложений, работающих с базами  данных, перечень возможных осложнений совсем  невелик и включает в себя  переименование несколь ких  существовавших ранее имен  в соответствии с новой архитектурой приложений DataSnap (прежде вызывавшейся MIDAS).

•  Тип  события TDatabase.OnLogin был  изменен с  TLoginEvent на  TData- baseLoginEvent. Это изменение едва ли способно вызвать проблемы, по скольку они  возможны только  в том случае,  когда в приложении присутствует обработчик события OnLogin.

•   Глобальные подпрограммы FMTBCDToCurr() и CurrToFMTBCD() были  замене ны новыми: BCDToCurr() и CurrToBCD(). (Соответствующие им закрытые ме тоды  класса  TDataSet были  заменены закрытым и недокументированным  ме тодом DataConvert.)

•  Со времени появления Delphi 4 DataSnap (прежде MIDAS) подвергся ряду сущест венных изменений. Более  подробная информация об  этих  изменениях и новых возможностях приведена в главе 21, “Разработка приложений DataSnap”.

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

32  разрядные беззнаковые целые

В Delphi  4 введен  тип LongWord — 32 разрядный беззнаковый целый  тип. В преды дущих  версиях наибольшим целым  типом  был  32 разрядный  знаковый целый  тип. По этой  причине многие  типы, которые должны  принимать только  беззнаковые (положительные) значения, такие  как DWORD, UINT, HResult, HWND, HINSTANCE, и некоторые  типы   дескрипторов,  ранее  определявшиеся  просто  как   Integer,  в Delphi 4 и  последующих версиях  переопределены  как  LongWord. Кроме   того,  тип Cardinal, ранее определявшийся в диапазоне 0..MaxInt, сейчас  также  представля ет собой тип LongWord. За исключением некоторых описанных ниже случаев, все эти изменения не оказывают никакого влияния на поведение программы.

•  При  передаче var параметров типы  Integer и LongWord не совместимы. Нельзя передавать значение типа  LongWord в var параметр типа  Integer, и наоборот. В подобном случае  компилятор сообщает об ошибке, поэтому  для решения этой проблемы следует либо изменить тип параметра или переменной, либо выполнить явное приведение типов.

•   Литеральные константы со значениями от $80000000 до $FFFFFFFF рассмат риваются как тип  LongWord. Если такую константу необходимо присвоить це лому типу, то потребуется приведение к типу Integer:

var

I: Integer;

begin

I := Integer($FFFFFFFF);

•  Любой  литерал, имеющий отрицательное значение, выходит за пределы диа пазона  LongWord. Поэтому  перед  присвоением литерала с отрицательным зна чением переменной типа  LongWord необходимо выполнить соответствующее приведение типов:

var

L: LongWord;

begin

L := LongWord(-1);

•  Если знаковые и беззнаковые целые  участвуют в одном  арифметическом выра жении или в одной  операции сравнения, то для вычисления этого  выражения или выполнения сравнения компилятор автоматически приводит каждый  опе ранд  к типу Int64. Это  неявное действие может  послужить источником труд новыявляемых ошибок. Рассмотрим следующий код:var

I: Integer; D: DWORD;

begin

I := -1;

D := $FFFFFFFF;

if I = D then DoSomething;

В Delphi 3  будут выполнены действия оператора  DoSomething, так  как  -1 и

$FFFFFFFF имеют  одинаковое значение при переводе в тип Integer. В Delphi 4

каждый операнд преобразуется в тип Int64 для выполнения более точного срав 

нения, поэтому   результирующий  код  будет  сравнивать  $FFFFFFFFFFFFFFF и

$00000000FFFFFFFF, которые определенно не равны  между собой,  и операторы

DoSomething выполняться не будут.

CОВЕТ

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

64  разрядный целый тип

В Delphi  4 также  был введен  новый тип,  называемый Int64, который представля ет собой  64 разрядный знаковый целый  тип. Он широко используется в библиотеках RTL и VCL. Так,  например, стандартные функции  Trunc() и Round() возвращают значение типа  Int64. Кроме  того,  появились новые  версии функций  IntToStr(), IntToHex() и других связанных с ними функций, работающих с int64.

Действительный тип

В Delphi  версии 4 и  последующих тип  Real является псевдонимом типа  Double. В предыдущих версиях Delphi  и Turbo Pascal тип  Real представлял собой  6 байтовый тип чисел с плавающей точкой. Это не станет причиной проблем, если только  значения типа Real не сохранялись записанными в двоичных файлах (например в file of re- cord), созданных приложениями предыдущих версий, и код программ не  зависит от конкретной организации значений типа Real в памяти. Можно  принудительно сделать тип  Real прежним, 6 байтовым типом,  включив директиву  {$REALCOMPATIBILITY ON} в модули, в которых нужно использовать старое представление действительных ти пов данных.  Если же требуется просто “заставить” некоторое ограниченное количество экземпляров типа  Real иметь  прежний размер, то вместо  этой  директивы следует вос пользоваться типом Real48.

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

Изменения в булевых типах

Реализация булевых типов  в Delphi  2 (Boolean, ByteBool, WordBool, LongBool) подразумевает, что  значение True соответствует значению 1, а значение False —  0. Для обеспечения лучшей совместимости с интерфейсом API Win32 реализация Byte- Bool, WordBool и LongBool немного изменилась: значение True теперь представля ется целым — -1 ($FF, $FFFF и $FFFFFFFF соответственно). Тип же Boolean остался прежним. Эти  изменения могут сказаться на поведении программ, но только  если  в них используются числовые представления значений таких  типов.  Взгляните на сле дующее объявление:

var

A: array[LongBool] of Integer;

В  Delphi 2  данный  код  вполне  безобиден —   он   объявляет  массив   целых   ar- ray[False..True] или  [0..1] с двумя элементами. Но  в Delphi 3 это  объявление может  привести к некоторым весьма  неожиданным результатам: поскольку  True оп ределено для LongBool как $FFFFFFFF, то  подобное объявление приводит к созда нию  массива  целых  чисел  array[0..$FFFFFFFF] или  массива  из четырех миллиар дов (!) целых  типа Integer. Во избежание этой  проблемы в качестве индекса  массива используйте тип Boolean.

Как ни странно, но необходимость в таком  изменении возникла в связи  с тем, что получившие широкое распространение  элементы управления ActiveX и контейнеры элементов управления (как у Visual Basic) проверяют значение булевых  переменных, сравнивая их с -1, а не с нулем или значением, отличным от нуля.

CОВЕТ

Во избежание ошибок и проблем совместимости никогда не пишите код подобный это-

му:

if BoolVar = True then …

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

if BoolVar then …

Строковые ресурсы ResourceString

Если в приложении используются строковые ресурсы, рекомендуем воспользо ваться  преимуществом ResourceString. Более подробная информация по  данной теме приведена в главе 2, “Язык программирования Object Pascal”. Это не повлияет нина размер приложения, ни на скорость его выполнения, но упростит процесс транс ляции. ResourceString и  связанные с  ним  методы   использования  ресурсов DLL важны  при  написании многоязычных (локализованных) приложений, работающих с единым  пакетом ядра библиотеки VCL.

Изменения в RTL

Некоторые изменения, внесенные в динамическую библиотеку (RTL — Runtime Library) после выхода версии Delphi  2, могут привести к возникновению проблем при переносе приложений в новую  среду.  Во первых, изменилось значение глобальной переменной HInstance — теперь она содержит дескриптор экземпляра текущей DLL, исполняемого файла  или  пакета.  Для получения дескриптора экземпляра основного приложения используйте новую глобальную переменную MainInstance.

Второе важное изменение касается глобальной переменной IsLibrary. В Delphi 2

ее значение проверялось для выяснения способа выполнения данного кода — из кон

текста  библиотеки .DLL или  исполняемого файла  .EXE. Переменная IsLibrary не обслуживает пакеты, поэтому  не следует полагаться на нее при  определении способа вызова  программы (из исполняемого файла, библиотеки DLL или модуля пакета). Для этого лучше использовать глобальную переменную ModuleIsLib, которая возвращает True при вызове программы из библиотеки DLL или пакета.  Кроме  того,  переменную ModuleIsLib можно  применять в комбинации с глобальной переменной ModuleIs- Package, что позволит отличить библиотеку DLL от пакета.

Класс TCustomForm

В библиотеке VCL Delphi 3 появился новый промежуточный класс между классами TScrollingWinControl и TForm, называемый TCustomForm. Сам по себе этот  факт не усложняет перенос приложений Delphi 2 в новую среду, но, если программа рабо тает с экземплярами класса TForm, то ее код следует обновить так, чтобы  вместо  клас са TForm использовался класс TCustomForm. В частности, подобные действия необ ходимы  при  вызове  в программе функций GetParentForm(), ValidParentForm(), а также при любом использовании класса TDesigner.

CОВЕТ

Со  времен  Delphi 2  несколько  изменилась  семантика  методов  GetParentForm(), ValidParentForm() и других методов компонентов библиотеки VCL, возвращающих указатели Parent. Теперь они могут возвращать значение nil, даже если компонент имеет контекст родительского окна, в котором выполняется прорисовка. Например, если компонент инкапсулирован в элемент управления ActiveX, то он может иметь родитель- ское окно, но не элемент управления Parent. Это означает, что необходимо проследить, чтобы в коде Delphi 2 не встречались подобные вещи:

with GetParentForm(xx) do …

Теперь метод GetParent() может вернуть nil, в зависимости от того, каким образом инкапсулирован компонент.

Метод GetChildren()

Разработчики компонентов! Имейте в виду, что объявление TComponent.Get- Children() изменилось и выглядит сейчас так:

procedure GetChildren(Proc: TGetChildProc;

Root: TComponent); dynamic;

Новый параметр Root содержит указатель  на  владельца корневого компонента, т.е. на тот компонент, который можно  получить, пройдя по цепочке владельцев ком понента до самого начала, когда свойство Owner окажется равным nil.

Серверы автоматизации

Код, необходимый для использования функций автоматизации, значительно из менился по сравнению с тем, каким  он был в Delphi 2. (Создание серверов автомати зации  в Delphi  описано в главе 15, “Разработка приложений COM”.) Авторы полагают, что нет смысла подробно описывать эти различия, достаточно сказать, что стили  соз дания  серверов автоматизации, применяемые в Delphi 2, не  следует  использовать в последующих  версиях Delphi.

В Delphi  2 автоматизация  осуществляется с использованием возможностей моду лей OleAuto и Ole2. Эти модули присутствуют в последующих версиях Delphi лишь в целях  совместимости с прежними версиями, и их не  рекомендуется использовать в новых  проектах. В настоящее время  те же функции обеспечивают модули ComObj, ComServ и ActiveX. Не следует смешивать старые модули с новыми в одном проекте.

Переход от Delphi 1

Если кому то повезло оказаться обладателем антикварного кода,  который необхо димо  откомпилировать и выполнять одновременно и под  16,  и  под  32 разрядными версиями Windows,  то  примите наши  соболезнования, поскольку  точек  несовмести мости между Delphi 1 и более поздними версиям очень  много.  Они  расположены практически везде,  начиная с несовпадения большинства основных типов  данных  и до библиотек VCL и API Windows. Однако  из за относительно малого  количества раз работчиков, продолжающих создавать и поддерживать приложения для 16 разрядных платформ, эта информация исключена из текста  настоящей книги, но она есть в пре дыдущем издании в главе 15 ? “Переход на Delphi  5”.

Резюме

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

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии