Создание DLL-библиотеки для работы с Word/Excel из приложений на Delphi
Весь набор функций, который рассмотрен в предыдущих статьях
можно реализовать в виде DLL-библиотеки. Реализация в виде DLL дает большие
преимущества программисту в гибкости, надежности использования своих
программных продуктов и сокращает время на разработку программного обеспечения.
В своих библиотеках вы можете заложить базовые функции, которые не будут
изменяться довольно часто, при этом основное приложение, которое использует
библиотеки, может меняться достаточно часто и совершенствоваться от версии к
версии. Функции, оформленные в виде DLL, называются иначе
- API-функциями. Система Windows использует как системные, так и
пользовательские функции API.
Если вы решите создавать библиотеку для работы с Word.Application
(Excel.Application), то столкнетесь с некоторыми особенностями, которые
укладываются в общее представление о создании динамических библиотек. Эти
особенности связаны с преобразованием формата данных, передаваемых через
механизм DDE.
Приступим к созданию нашей библиотеки (назовем ее MyLWord).
Выполним команду меню "File" -> "New..." . В открывшемся
окне выберите закладку "New" и далее пиктограмму "DLL", нажмите
кнопку "OK". Получим новый проект. Его название изменим на MyLWord и
сохраним под тем же именем. Используем нашу библиотеку MyWord, которая была
создана ранее (см. "Суперфункции"). Изменим эту библиотеку, дописав в
конец объявления каждой процедуры в секции interface ключевое слово StdCall,
которое определяет соглашение о передаче параметров через стек. В файле проекта
MyLWord.dpr в секцию подключения внешних модулей uses допишем ссылку на
библиотеку MyWord. После секции uses создадим секцию экспортируемых процедур и
функций, напишем ключевое слово exports, после которого через запятую
перечислим список всех экспортируемых процедур и функций. Если откомпилировать
этот проект, то получим файл динамической библиотеки MyLWord.dll. Ниже
представлены фрагменты перечисленных выше файлов.
Файл - MyLWord.dpr
Code:
library MyLWord;
uses
SysUtils,
Classes,
MyWord;
{$R *.RES}
exports
CreateWord,
VisibleWord,
................,
GetNameIndexShape;
Begin
//
Секция инициализации модуля, можно вставлять функции,
которые
должны выполняться при загрузке модуля,например
начальная
загрузка данных, которые будут использоваться
всеми
функциями и процедурами модуля.
end.
Файл - MyWord.pas
Code:
unit MyWord;
interface
const
wdBorderTop=-1;
......................
wdLineStyleEngrave3D=22;
Function CreateWord:boolean; StdCall
Function VisibleWord(visible:boolean):boolean; StdCall
.........................................
Function SetNewNameShape(NameShape:variant;
NewNameShape:string):string;
StdCall
Function GetNameIndexShape(NameIndex:variant):string; StdCall
var W:variant;
implementation
uses ComObj;
Function CreateWord: boolean;
begin
CreateWord:=true;
try
W:=CreateOleObject ('Word.Application');
.........................................
Function DeleteShape (NameShape:variant): variant;
Begin
DeleteShape:=true;
try
W.ActiveDocument.Shapes.Item(NameShape).Delete;
except
DeleteShape:=false;
end;
end;
end.
После создания динамической библиотеки процедур и функций
рассмотрим ее использование. Для этого возьмем пример, описанный в предыдущих
статьях "Суперфункции". Любую динамическую библиотеку можно
использовать двумя основными способами: загрузка библиотеки при старте
EXE-модуля и динамическая загрузка, которая выполняется в местах программы,
там, где это необходимо. Преимущество первого метода заключается в простоте
написания кода, второго - в гибкости, например, в зависимости от каких-либо
условий программы можно загружать различные модули, содержащие одинаковые
функции. Если используется первый вариант, то при отсутствии модуля DLL программа просто
не загрузится, при втором варианте программа загрузится, но в местах вызова
модуля будет сгенерирована ошибка, которую можно обработать.
Рассмотрим подробнее вариант загрузки модуля DLL при старте
программы, которая его использует. Если вы хотите использовать какую-либо
функцию динамической библиотеки, то достаточно в модуле, где будет
использоваться функция, добавить строку объявления такого типа:
Function (Procedure) <Имя функции (процедуры)>(<список
переменных и типов>): <возвращаемое значение>; external '<Имя файла
библиотеки с расширением>' name ' Имя функции или процедуры ';
Конкретные примеры:
Code:
Function CreateWord:boolean;
external 'MyLWord.dll' name 'CreateWord';
Function VisibleWord(visible:boolean):boolean;
external 'MyLWord.dll' name 'VisibleWord';
.........................
Begin
.....................
if CreateWord then VisibleWord(true);
.....................
End.
Для объявления функций и процедур динамической библиотеки удобно
использовать отдельный модуль Unit. В таком модуле в секции interface
перечисляются функции и процедуры с указанием имен, параметров и типов
возвращаемых значений как в обычном модуле, в секции implementation они
описываются с указанием на модули (имена файлов) DLL и оригинальные
имена. Например:
Code:
unit MyDWord;
interface
Function CreateWord: boolean; StdCall
Function VisibleWord (visible:boolean):boolean; StdCall
.........................................
Implementation
Function CreateWord:boolean;
external 'MyLWord.dll' name 'CreateWord';
Function VisibleWord (visible:boolean):boolean;
external 'MyLWord.dll' name 'VisibleWord';
.........................................
End.
Чтобы использовать данный модуль в приложении, достаточно указать
на него ссылку в секции uses. Рассмотрим пример:
Code:
Uses
MyDWord;
.........................................
Begin
//
Выполним загрузку Word'а, вызвав необходимые функции.
if CreateWord then VisibleWord(true);
end;
Рассмотрим динамическое выполнение процедур и функций модуля DLL. Для динамической
загрузки и выполнения необходимо определить типы вызываемых процедур (функций),
загрузить библиотеку DLL, получить адреса входа в процедуру
(функцию), выполнить процедуру (функцию) и выгрузить библиотеку.
Для этого рассмотрим следующий пример:
Code:
//Выполним
загрузку и отображение Word'а, используя
функции
CreateWord и VisibleWord. В секции type
определим
их типы, они должны совпадать с оригиналом
вмодулеDLL.
type
TCreateWord=function: boolean;
TVisibleWord=function (visible:boolean):boolean;
//В
разделе описания переменных определим переменную
hdll:thandle,
через которую будем обращаться к функциям
работы
с библиотекой, и переменные - ссылки на процедуры
//
Выполним загрузку Word'а, вызвав необходимые функции.
if CreateWord then VisibleWord(true);
//
Выгрузим библиотеку (очистим память от библиотеки).
FreeLibrary(hdll);
end;
Как
видно, динамическая загрузка библиотеки немного сложнее, но, несмотря на это,
она оправдывает себя. Используя данный материал, вы сможете создать и
использовать свою персональную динамическую библиотеку для работы с редакторами
Word и Excel.