ГЛАВА 4

- Для чего используются пакеты
- Использование пакетов в приложениях
- Динамическая загрузка пакетов
- Установка пакетов компонентов
- Создание и редактирование пакетов
- Структура пакета
- Компиляция пакета

Пакеты - это специальные динамически присоединяемые компоненты (аналоги DLL - динамически компонуемых библиотек Dynamic Link Library), которые используются приложениями Delphi и IDE Delphi (о компонентах Delphi и о создании собственных компонентов читайте во второй части книги). По своему использованию пакеты делятся на:
- пакеты, загружаемые во время работы приложения (Runtime Packages), мы их будем далее называть пакетами времени выполнения. Они содержат в себе код, компоненты и используются приложением во время выполнения. Если ваше приложение ссылается на отсутствующий пакет - оно не будет работать;
- пакеты, используемые во время разработки приложения (Design time Packages), будем их называть пакетами разработки. Пакеты разработки содержат в себе компоненты, редакторы свойств, мастера и другие элементы, предназначенные для работы в среде Delphi;
- пакеты, которые могут работать как во время разработки приложения, так и во время работы приложения;
- пакеты, не являющиеся ни пакетами времени выполнения, ни пакетами разработки. Данный вид пакетов предназначен для использования их другими пакетами. На них не могут ссылаться ни приложение, ни сама среда Delphi.
Для того чтобы пакеты можно было отличить от других динамически присоединяемых библиотек, имеющих расширение DLL, для пакетов используется расширение BPL - пакет библиотеки Delphi (Borland Package Library).
Так же, как и остальные динамические библиотеки, пакеты содержат код, который может быть использован одновременно несколькими приложениями. Например, самым часто используемым пакетом Delphi 5.0 является VCL50.BPL. Когда вы создаете практически любое приложение на Delphi, вы используете этот пакет. Сама среда Delphi также использует данный па кет. При этом достаточно, чтобы в памяти компьютера находилась всего одна копия данного пакета для скольких угодно приложений, использующих VCL50.BPL. Ту же копию пакета будет использовать и сама среда Delphi.
Вы можете строить ваши приложения с использованием пакетов или без них. Но, если вы хотите включать в свое приложение самостоятельно созданные компоненты, вам придется установить пакет, используемый во время разработки приложения и содержащий данные компоненты.
В этой главе мы рассмотрим, для чего нужны пакеты, как используются пакеты в приложениях, как можно динамически загружать пакеты. Рассмотрим процедуру инсталляции пакетов компонентов. Научимся создавать новые пакеты и редактировать уже имеющиеся. Изучим общую структуру пакета.
Для чего используются пакеты
Как мы уже говорили выше, пакеты разработки необходимы для упрощения задачи распределения и установки компонентов, созданных разработчиком. Программирование с помощью пакетов разработки, по определению, имеет некоторое преимущество по сравнению с обычным программированием. Главное преимущество - сокращение размера кода. Например, все ваши приложения, включая среду программирования Delphi, могут одновременно использовать стандартные компоненты Delphi, расположенные в одном и том же пакете. Так как приложения не содержат отдельные копии библиотек компонентов, то их размер становится намного меньше. Более того, время компиляции пакетов существенно меньше, т. к. для конкретного приложения компилируется тот код, который ему необходим.
Для того чтобы приложение использовало пакеты, нужно установить флажок Build with Runtime Packages (Строить с пакетами времени выполнения) в диалоговом окне Project Options (Настройки проекта) на странице Packages (Пакеты). Для открытия этого диалогового окна выберите пункт главного меню Delphi Project/Options (Проект/Настройки). При такой компиляции приложения оно значительно сократится в размерах (примерно в 8-10 раз), но вам придется при распространении приложения передавать и все используемые приложением пакеты (включая и такой большой пакет, как VCL50.DCP, который имеет объем почти 3 Мбайт).
Рассмотрим, когда нужно использовать пакеты, а когда стандартные динамически загружаемые библиотеки Windows:
- если вы хотите использовать самостоятельно написанные компоненты в среде Delphi - создавайте пакеты. Помните, что пакеты Delphi поддерживаются только приложениями, разработанными в Delphi или Borland C++ Builder;
- если же вы хотите использовать созданную вами библиотеку различными приложениями, созданными в разных средах программирования, вам необходима динамически загружаемая библиотека (*.DLL).
Кроме рассмотренного выше расширения файла пакета BPL, с файлами пакетов связаны следующие расширения (табл. 1.4):
Таблица 1.4. Типы файлов пакетов

| Расширение файла | Содержание файла |
| DPK | Исходный файл пакета, содержащий список модулей, расположенных в пакете. Он создается при запуске редактора пакета (по своему назначению и функциональности он похож на файл проекта Delphi *.DPR) |
| DCP | Двоичный файл, содержащий заголовок пакета и описание всех файлов *.DCU, расположенных в пакете, включая всю символьную информацию, которая требуется для компилятора. Всего один файл данного типа создается для одного пакета |
| DCU | Двоичный файл, содержащий текст модуля, находящийся в пакете. Для каждого модуля создается один файл *.DCU |
| BPL | Файл пакета, используемого во время работы приложения. Этот файл является аналогом динамически загружаемой библиотеки (*.DLL) Windows, которая содержит специфичные характеристики среды Delphi. Если это пакет времени выполнения, то вы должны передавать данный пакет пользователю вместе с файлом приложения. В случае, если это пакет разработки, он должен распространяться среди программистов, использующих его для написания приложений |

Использование пакетов в приложениях
Для того чтобы приложение, которое использует пакеты, благополучно запустилось, нужно, чтобы имелись все необходимые приложению файлы ЕХЕ и BPL. Файлы BPL должны быть прописаны в путях приложения.
Примечание
При разработке коммерческих приложений обратите внимание на то, чтобы пользователи получили правильную версию файлов пакетов (*.BPL).
Для использования пакетов времени выполнения в вашем приложении нужно выполнить следующие шаги:
1. Загрузите или создайте новый проект в среде Delphi.
2. В главном меню Delphi выберите пункт Project/Options (Проект/Настройки).
Рис. 1.27. Вкладка Packages диалогового окна Project Options
3. В открывшемся диалоговом окне выберите вкладку Packages (Пакеты) (рис. 1.27).
4. Установите флажок Build with runtime packages (Строить с пакетами времени выполнения). Затем в открывшееся поле введите один или несколько названий пакетов, которые вы хотите использовать в своем приложении. Вы можете воспользоваться также кнопкой Add (Добавить) для поиска необходимого пакета (рис. 1.28).
Рис. 1.28. Окно добавления пакета в проект
Примечание
При изменении пути поиска (Search path) в диалоговом окне добавления пакета (рис. 1.28) вы измените глобальные настройки путей к библиотекам Delphi.
При ручном вводе имени пакета (в поле для редактирования без применения кнопки Add (Добавить) вам не потребуется вводить расширение пакета. Обратите внимание, что названия пакетов записываются через точку с запятой: VCL50;VCLX50;VCLSMPbO;VCLDB50;VCLAD050
Пакеты, перечисленные в поле для редактирования, при компиляции вашего приложения будут автоматически связаны с ним. Если в поле для ввода имен пакетов не будет ни одного названия пакета, ваше приложение будет откомпилировано как не использующее пакеты. В случае если один и тот же пакет будет записан в поле для редактирования несколько раз, все лишние записи будут проигнорированы.
Примечание
Вся информация об используемых приложением пакетах будет сохранена только для данного приложения. Если вы хотите, чтобы настройки сохранялись для других приложений, установите флажок Defaults (По умолчанию), находящийся в нижней части диалогового окна Project Options (Настройки проекта).
Очень важно помнить, что даже если вы используете в своем приложении пакеты, вы все равно должны прописывать имена модулей среды Delphi в блоке uses:
unit Unitl;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,. Dialogs;
Хотя все из вышеперечисленных модулей входят в один пакет VCL50.BPL, если убрать их описание из блока uses, компилятор сгенерирует ошибку.
Динамическая загрузка пакетов
Иногда требуется загружать необходимый пакет во время работы приложения. Для этой цели служит функция LoadPackage. Данная функция находится в модуле Delphi SysUtils. Описание функции имеет следующий вид: function LoadPackage(const Name: string): HMODULE;
В качестве передаваемого функции параметра служит имя файла пакета типа string. Вызов данной функции очень прост: LoadPackage('Имя файла пакета');
Для динамической выгрузки пакета применяется процедура unioadPackage. Эта процедура также содержится в модуле SysUtils. Ее описание имеет вид: procedure UnioadPackage(Module: HMODULE);
При вызове данной процедуры будьте осторожны, чтобы не уничтожить экземпляры классов, определенных в пакете.
Среда Delphi поставляется с уже установленными пакетами компонентов, которые поддерживают основные компоненты, необходимые для создания стандартных приложений Windows. Наибольшее число стандартных компонентов Delphi содержится в уже знакомом нам пакете VCL50.BPL. Но данный пакет не содержит многие компоненты, например компоненты для работы с базами данных, компоненты для Windows 3.1 и др. Эти компоненты находятся в других пакетах Delphi (например, компоненты, предназначенные для работы с базами данных, находятся в пакете VCLDB50.BPL). Однако, несмотря на это, для работы с базами данных, вам понадобятся оба пакета VCL50.BPL и VCLDB50.BPL. В приведенной ниже табл. 1.5 перечислены пакеты времени выполнения, поставляемые с Delphi (версии 5.0), а также модули (units), входящие в данные пакеты.
Таблица 1.5. Основные runtime-пакеты Delphi

| Имя файла пакета | Модули, входящие в пакет |
| VCL50.BPL | Ax, Buttons, Classes, Clipbrd, Comctrls, Coraractrl, Commdlg, Comobj, Comstrs, Consts, Controls, Ddeml, Dialogs, Digs, Dsgnintf, Dsgnwnds, Editintf, Exptintf, Extctrls, Extdlgs, Fileintf, Forms, Graphics, Grids, Imm, IniFiles, Isapi, Isapi2, Istreams, Libhelp, Libintf, Lzexpand, Mapi, Mask, Math, Menu, Messages, Mmsystem, Nsapi, 01e2I, Oleconst, Olectnrs, Olectrls, Oledlg, Penwin, Printers, Proxies, Registry, Regstr, Richedit, Shellapi, Shlobj, Stdctrls, Stdvcl, Sysutils, Tlhelp32, Toolintf, Toolwin, Typinfo, Vclcom, Virtintf, Windows, Wininet, Winsock, Winspool, Winsvc |
| VCLX50.BPL | Checklst, Colorgrd, Ddeman, Filectrl, Mplayer, Outline, Tabnotbk, Tabs |
| VCLDB50.BPL | Bde, Bdeconst, Bdeprov, Db, Dbcgrids, Dbclient, Dbcommon, Dbconsts, Dbctrls, Dbgrids, Dbinpreq, Dblogdlg, Dbpwdlg, Dbtables, Dsintf, Provider, Smintf |
| VCLDBX50.BPL | Dblookup, Report |
| DSS50.BPL | Mxarrays, Mxbutton, Mxcommon, Mxconsts, Mxdb, Mxdcube, Mxdssqry, Mxgraph, Mxgrid, Mxpivsrc, Mxqedcom, Mxqparse, Mxqryedt, Mxstore, Mxtables, Mxqvb |
| QRPT50.BPL | Qr2const, Qrabout, Qralias, Qrctrls, Qrdatasu, Qrexpbld, Qrextra, Qrprev, Qrprgres, Qrprntr, Qrqred32, Quickrpt |
| TEE50.BPL | Arrowcha, Bubblech, Chart, Ganttch, Series, Teeconst, Teefunci, Teengine, Teeprocs, Teeshape |
| TEEDB50.BPL | Dbchart, Qrtee |
| TEEUI50.BPL | Areaedit, Arrowedi, Axisincr, Axmaxmin, Baredit, Brushdlg, Bubbledi, Custedit, Dbeditch, Editchar, Flineedi, Ganttedi, leditcha, Pendlg, Pieedit, Shapeedi, Teeabout, Teegally, Teelisb, Teeprevi, Teexport |
| VCLSMP50.BPL | Sampreg, Smpconst |

Рассмотрим теперь пакеты разработки, которые поставляются вместе с Delphi 5.0 (табл. 1.6). Напомним, что данные пакеты используются IDE Delphi для установки компонентов в палитру компонентов, задания свойств компонентов и многого другого.
Таблица 1.6. Основные design-time-компоненты Delphi

| Имя файла пакета | Вкладки палитры компонентов |
| DCLSTD50.BPL | Standard, Additional, System, Win32, Dialogs |
| DCLTEE50.BPL | Additional (компонент TChart) |
| DCLDB50.BPL | Data Access, Data Controls |
| DCLMID50.BPL | Data Access (MIDAS) |
| DCL31W50.BPL | Win 3.1 |
| DCLNET50.BPL, NMFAST50.BPL | Internet |
| DCLSMP50.BPL | Samples |
| DCLOCX50.BPL | ActiveX |
| DCLQRT50.BPL | Qreport |
| DCLDSS50.BPL | Decision Cube |
| IBSMP50.BPL | Samples (компонент IBEventAlerter) |
| DCLINT50.BPL | Мастер многоязыковой поддержки |
| RCEXPERT.BPL | Мастер ресурсов |
| DBWEBXPRT.BPL | Мастер Web |

Все вышеперечисленные пакеты разработки вызывают при своей работе пакеты времени выполнения. Например, пакет DCLSTD50.BPL вызывает VCL50.BPL. Первый пакет содержит код, который позволяет делать доступ ными многие компоненты, входящие во второй пакет на палитре компонентов Delphi.
В дополнение ко всем рассмотренным выше пакетам, вы можете устанавливать в IDE пакеты собственного производства, а также пакеты, созданные другими разработчиками. Пакет Delphi DCLUSR50.BPL является стандартным контейнером для новых компонентов.
Установка пакетов компонентов
Для того чтобы установить собственные пакеты или пакеты, созданные другими разработчиками, вам нужно выполнить следующие шаги:
1. В случае, когда вы устанавливаете новый пакет, скопируйте файлы пакета в директорию библиотеки Delphi. Убедитесь, что скопировали все необходимые файлы пакета (имеющие расширения BPL, DCP, DCU). Если вы устанавливаете файл пакета с расширением DCP (Delphi Package Collection), то вам не нужно копировать никакие другие файлы, т. к. DCP-файл содержит внутри себя все файлы пакета.
2. В главном меню Delphi выберите команду Component/Install Packages (Компонент/Установить пакеты), либо воспользуйтесь вкладкой Packages (Пакеты) в диалоговом окне свойств проекта, вызываемого командой главного меню Delphi Project/Options (Проект/Настройки) (рис. 1.29).
Рис. 1.29. Окно просмотра компонентов, входящих в пакет
3. В вызванном диалоговом окне вы можете видеть список всех доступных пакетов. Для установки любого пакета, имеющегося в списке, поставьте флажок напротив наименования пакета. Для удаления пакета из проекта уберите флажок напротив наименования пакета. Для просмотра компонентов, входящих в пакет, щелкните мышью на имени пакета и нажмите кнопку Components (Компоненты). На рис. 1.29 показан список компонентов, входящих в состав пакета Borland ADO DB Components.
4. Для добавления нового пакета в список нажмите кнопку Add (Добавить) и в открывшемся окне выберите файл пакета. При выборе файла пакета, имеющего расширение DPC, появляется диалоговое окно для обработки процесса извлечения файлов пакета из файла коллекции пакета (*.DPC).
5. Чтобы удалить пакет из списка, выберите пакет и нажмите кнопку Remove (Удалить).
Компоненты пакета устанавливаются на вкладки палитры компонентов Delphi.
Создание и редактирование пакетов
Процесс создания пакета включает в себя: - задание названия пакета;
- указание списка других пакетов, связанных с новым пакетом или требуемых для его работы;
- составление списка файлов модулей, содержащихся в пакете или связанных с ним. По существу, пакет является лишь оболочкой для этих файлов.
Рис. 1.30. Щелкните на значке Package, чтобы создать новый пакет
Для создания пакета вам необходимо выполнить перечисленные ниже шаги:
Примечание
Для хорошего понимания перечисленных ниже шагов вам нужно ознакомиться со структурой пакета. Структура пакета рассматривается в следующем разделе.
1. Выберите в главном меню Delphi команду File/New (Файл/Новый). В появившемся диалоговом окне выберите значок Package (Пакет) (рис. 1.30). Сгенерированный пакет будет отображен в редакторе пакета (рис. 1.31).
Редактор пакета отображает два раздела: содержания (Contains) и требований (Requires).
Рис. 1.31. Редактор пакета
2. Для добавления нового модуля в раздел Contains (Содержание) выберите этот раздел, затем щелкните на кнопке Add (Добавить) редактора пакета. Появится диалоговое окно Add (Добавление) (рис. 1.32).
На странице Add Unit (Добавление модуля) диалогового окна Add (Добавление) запишите в поле имени файла модуля имя файла *.PAS, который вы хотите включить в пакет, либо воспользуйтесь кнопкой Browse (Обзор) для непосредственного указания файла. В результате, выбранный файл модуля будет добавлен в раздел contains вашего пакета.
Можете повторить вышеперечисленные действия для добавления дополнительных модулей в пакет.
Рис. 1.32. Диалоговое окно добавления нового модуля раздела Contains пакета
3. Для добавления пакетов в раздел Requires выберите этот раздел щелчком мыши, затем нажмите кнопку Add (Добавить) редактора пакета.
В появившемся диалоговом окне (рис. 1.33) в поле имени пакета (Package Name) впишите имя файла пакета (*.DCP), требуемого для работы вашего пакета. Вы также можете использовать кнопку Browse (Обзор) для непосредственного указания файла пакета. Повторяя данный шаг, вы можете добавить несколько файлов пакетов в раздел Requires вашего пакета.
Рис. 1.33. Диалоговое окно добавления нового модуля раздела Requires пакета
4. Для выбора типа создаваемого пакета (runtime или design-time) щелкните на кнопке Options (Настройки) редактора пакета. Откроется диалоговое окно Project Options (Настройки проекта) (рис. 1,34).
5. Теперь выберите нужный тип пакета, выбором переключателя в разделе Usage Options (Параметры использования).
6. Последний шаг - компиляция созданного пакета. Нажмите кнопку Compile (Компилировать) редактора пакета.
Редактировать уже существующий файл пакета можно по-разному:
- выбрать пункт главного меню Delphi File/Open (Файл/Открыть) и найти файл пакета, который необходимо редактировать;
- выбрать пункт главного меню Delphi Component/Install Component (Компонент/Установить компонент), выделить нужный пакет в списке пакетов и нажать кнопку Edit (Правка);
- в открытом редакторе пакета выбрать в разделе Requires (Требования) нужный пакет, щелкнуть на нем правой кнопкой мыши для появления контекстного меню, где выбрать пункт Open (Открыть).
Рис. 1.34. Диалоговое окно Project Options
Кроме того, вы можете редактировать файл пакета (*.DPK) точно так же, как и файл проекта (*.DPR) - вручную, как текстовый файл. Файл пакета содержит в себе три раздела:
- название пакета (в разделе Package);
- раздел требуемых файлов для данного пакета (раздел Requires);
- раздел, содержащий названия файлов модулей, входящих в данный пакет (раздел Contains).
Приведем в качестве примера содержимое файла пакета VCLDB50.DPK:
package VCLDB50;
requires VCL50;
contains Db, Dbcgrids, Dbctrls, Dbgrids, Dbinpreq, Dblogdlg, Dbpwdlg, Dbtables, mycomponent in 'C:\components\mycomponent.pas';
end.
Структура пакета
Вспомним все, что мы уже знаем о пакетах, и нам нетрудно будет понять, из чего состоит пакет.
Пакет состоит из имени, разделов Requires и Contains.
package имя пакета;
requires файлы пакетов, необходимые для работы пакета;
contains файлы модулей, входящие в состав пакета;
end.
Имя пакета должно быть уникальным внутри проекта. Например, вы назвали пакет MyPack. При этом редактор пакета создает файл ресурсов с именем MyPack.dpk. При компиляции проекта образуются еще два файла с именами MyPack.blp и MyPack. dcp.
Файл MyPack.bpl является исполняемым файлом пакета (аналог *.DLL), a файл MyPack.dcp - двоичным файлом (аналог *.DCU).
Имя пакета нужно для того, чтобы вызывать его из приложения или вписывать его в раздел Requires другого пакета.
Раздел Requires, как нами уже говорилось ранее, содержит имена файлов пакетов, которые использует данный пакет. Следует заметить, что пакеты не могут содержать круговые ссылки, т. е. не должно возникать следующих ситуаций:
- пакет не должен содержать ссылку на самого себя;
-если пакет Packagel содержит в разделе Requires пакет Package2, то Package2 не должен содержать в своем разделе Requires пакет Packagel;
-если пакету Packagel Требуется пакет Package2, а пакету Package2 - Packages, то пакет Packages не должен содержать в разделе Requires пакет Packagel.
Раздел Contains включает в себя файлы модулей (*.PAS), входящих в проект.
Компиляция пакета
Как откомпилировать пакет, мы с вами уже знаем, осталось только рассмотреть некоторые особенности.
Для начала рассмотрим директивы компилятора, которые могут включаться в файл, пакета (*.DPK) и файлы модулей пакета (табл. 1.7).
Таблица 1.7. Директивы компилятора пакетов

| Директива | Применение |
| {$IMPLICITBUILD OFF} | Служит для предотвращения перекомпиляции пакета. Применяется в тех случаях, когда пакет не изменяется |
| {$G-} или { IMPORTEDDATA OFF} | Применяется для предотвращения размещения модуля внутри пакета. Данная директива размещается внутри модуля. Желательно, чтобы этот модуль был напрямую связан с приложением |
| { $WEAKPACKAGEUNIT ON} | Когда в файле модуля встречается эта директива, компилятор опускает данный модуль из BPL-файла и создает локальную копию модуля тогда, когда это будет необходимо (при вызове модуля из приложения или пакета). Модуль, имеющий такую директиву, называется слабым пакетом (weakly packaged) |
| {$DENYPACKAGEUNIT ON} | То же, что И {IMPORTEDDATA OFF} |
| {$DESIGNONLY ON} | Компилирует пакет как пакет design time |
| {$RUNONLY ON} | Компилирует пакет как пакет runtime |

Рассмотрим более подробно директиву { $WEAKPACKAGEUNIT }.
Слабый пакет применяется, когда пакет ссылается на отсутствующие библиотеки DLL. Данная директива применяется очень редко. Она позволяет обрабатывать специфические ситуации. Например, есть два компонента (в разных пакетах), которые обращаются к одному и тому же интерфейсному модулю DLL. Если приложение использует сразу оба компонента, то это приведет к загрузке двух экземпляров DLL, при этом могут возникнуть конфликты инициализации и использования глобальных переменных.
Примечание
Обратите внимание, что когда вы поставляете откомпилированную версию приложения вместе со всеми необходимыми пакетами, вам нужно учитывать, что должна совпадать версия пакета. То есть пакет, созданный в Delphi 5, не будет работать вместе с приложением, разработанным в Delphi 4.

Глава 3 Содержание Глава 5