Когда необходимо обеспечить взаимодействие c данными вашего приложения, можно использовать специальные механизмы операционной системы. Если говорить о приложениях WIndows, то для них доступно множество различных механизмов, но в рамках этой статьи коснемся только некоторых из них:
Открытие файлов через ассоциацию с приложением
Это классический метод, когда файл открывается двойным щелчком, при этом в системе должно быть определено, какая программа обрабатывает открытие файла данного расширения. В результате будет автоматически запущено связанное с расширением файла приложение и система передаст ему путь к файлу в форме параметра командной строки.Реализация собственного протокола в системе
Этот механизм позволяет приложениям обрабатывать специфические ссылки. Например, при установке мессенджера Telegram в Windows регистрируется протоколtg://
. Когда пользователь нажимает на такую ссылку в браузере или документе, система понимает, что ее должен обработать клиент Telegram, поскольку информация о протоколе хранится в реестре Windows. Такая возможность реализуется по аналогии с типовыми протоколами, такими какhttp://
,mailto:
илиftp://
, — разработчики могут создавать собственные, кастомные протоколы для запуска приложений и передачи в них данных.-
Механизм Drag & Drop (перетаскивание файлов)
Drag In (перетаскивание внутрь) — когда пользователь перетаскивает файл в окно приложения, то программа его открывает.Drag Out (перетаскивание наружу) — приложение позволяет пользователю «вытянуть» объект за пределы окна приложения, передав его в другую программу или создав файл-ярлык в Windows.
Копирование и вставка данных через буфер обмена
Буфер обмена Windows позволяет приложениям передавать данные между собой с помощью копирования и вставки. Информация в буфере может храниться в разных форматах: простой текст, изображения, файлы, специальные ссылки и даже структурированные данные в виде XML или JSON. Возможна регистрация и использование своего уникального формата данных.
Поскольку я сейчас работаю над проектами, связанными с ЛОЦМАН:PLM, на примере десктопного приложения ЛОЦМАН:PLM Клиент покажу, где применяются эти механизмы. А в примерах кода более подробно продемонстрирую, как можно реализовать их в приложениях, написанных в Lazarus IDE.
ЛОЦМАН:PLM — это решение для управления инженерными данными и жизненным циклом изделий, разрабатываемое компанией АСКОН. Система предоставляет инструменты для работы с данными на всех этапах жизненного цикла продукта.

Десктопный клиент ЛОЦМАН:PLM — это классическое Windows-приложение, которое позволяет пользователю работать с базой данных комплекса PLM, управляя проектами и информационными объектами. В зависимости от своей роли пользователь может взаимодействовать с определёнными типами объектов, обеспечивающих поддержку различных этапов жизненного цикла изделия. Это могут быть объекты системной инженерии, а также конструкторской или технологической подготовки производства.

ЛОЦМАН:PLM Клиент работает с понятием информационного объекта, который имеет идентификационные данные, позволяющие ссылаться на него. Для передачи этих данных и последующего поиска соответствующего объекта в приложении реализованы специальные функции.
Примеры функций работы с объектом в ЛОЦМАН:PLM Клиент
Клиент поддерживает копирование и вставку объектов через буфер обмена. Если в дереве выбрать объект и скопировать его в буфер обмена, через пункт контекстного меню или с помощью горячих клавиш, то данные в буфере обмена будут сохранены в специальном формате LoodsmanBuffer
.
Для анализа содержимого буфера обмена можно воспользоваться утилитой Free Clipboard Viewer, она позволит увидеть как там хранится информация скопированная в него. Утилита покажет, что в записи LoodsmanBuffer
хранится информация в виде JSON-объекта следующего содержания:

Сам формат LoodsmanBuffer
поддерживается только ЛОЦМАН:PLM, вставить такие данные в другие приложения не получится.
Однако, для передачи информации о конкретных объектах во внешние программы или пересылки ее пользователям, реализован механизм создания специальных ссылок. Выделив объект в дереве, можно воспользоваться командой «Инструменты → Ссылки → Копировать ссылку», после чего в буфер обмена будет помещена строка следующего вида: ask:Loodsman.URL?Action=Navigate,params=NTF8REJfTkFNRXw0ODR8NDg1fHw0ODV8NDU4fDQ3OXw1MDR8NTA1
Здесь можно видеть что эта ссылка зарегистрированного протокола, которая имеет специальный формат, в которой ask:
— это имя протокола, который обрабатывает ЛОЦМАН:PLM Клиент. Параметр Action=Navigate
говорит приложению о том, что нужно перейти в дереве объектов на определенный объект, а params=
содержит закодированную в Base64 строку, содержащую идентификационные данные.
Декодированная строка имеет следующий вид: 51|DB_NAME|484|485||485|458|479|504|505,
Здесь в строке, через разделитель |
указаны имя базы данных и уникальные идентификаторы объектов: выбранного и его родительского.
Ссылка может быть вставлена в текст и будет обрабатываться как гиперссылка. При переходе по этой ссылке система автоматически запустит ЛОЦМАН:PLM Клиент, и передаст ему ее в качестве параметра. Клиент в свою очередь обработает полученные данные, найдет в дереве и выделит требуемый объект.
Помимо копирования в буфер обмена, имеется еще один способ создания ссылки на объект — это перетаскивание объекта за пределы приложения. В этом случае ЛОЦМАН:PLM Клиент генерирует специальный файл-ярлык (.lnk), который сохраняется в том месте, где пользователь отпустит кнопку мыши после перетаскивания.
Внутри файла хранится информация в следующем виде:
[InternetShortcut]
URL=ask:Loodsman.URL?Action=Navigate,params=MHxBS19QbG0wMXwyODk4fDEwMTI=
IconIndex=0
IconFile=C:\Program Files (x86)\ASCON\Loodsman\Client\Loodsman.exe
При двойном клике по ярлыку, как и при щелчке по ссылке вида ask:
автоматически запускается ЛОЦМАН:PLM Клиент, или активируется уже запущенный экземпляр. А далее он получает из ярлыка необходимые данные и отображает окно с нужным объектом.
Файл-ярлык с расширением .lnk — это стандартный ярлык в системе Windows, предназначенный для быстрого доступа к программам, файлам, папкам или сетевым ресурсам. Его обработку выполняет сама система. Однако, помимо этого, ЛОЦМАН:PLM может работать с собственными ярлыками, поскольку при установке регистрируются следующие типы файлов, которые открываются с помощью приложения:
.lnd -Loodsman.LinkDocument (Ссылка на документ ЛОЦМАН:PLM)
.lnf - Loodsman.LinkFile (Ссылка на файл ЛОЦМАН:PLM)
.lno - Loodsman.LinkObject (Ссылка на объект ЛОЦМАН:PLM)
Выше были приведены примеры применения системных механизмов на примере ЛОЦМАН:PLM, а далее будет приведена информация для реализации этих механизмов в собственном приложении.
Реализация механизмов в собственном приложении
В качестве примеров буду использовать код из заглушки, которая была написана для партнёров, разрабатывающих механизм интеграции с ЛОЦМАН:PLM. Заглушка позволяла протестировать нужный функционал без установки и развёртывания всего комплекса PLM на машинах разработчиков. Конечно, после отладки основных взаимодействий между приложениями, комплекс PLM был развернут на отдельной машине и уже там тестировалась совместная работа в полном объёме.
Открытие файла на двойной клик
Для поддержки функции открытия файла на двойной клик, необходимо выбрать для него расширение, которое желательно не занято другими приложениями, и добавить записи в реестр. А в приложении реализовать обработку параметров командной строки. Для того чтобы иконка документа имела свой вид, необходимо добавить в ресурсы самого приложения иконку, на которую можно будет сослаться.
Файл приложения
Для внесения в заглушку тестовых данных, которые были сгенерированы с помощью отчета из базы данных ЛОЦМАН:PLM, они были помещены в файл с расширением .lpf. Данные внутри файла представляют собой JSON массив объектов.
Добавление записи в реестр
Обычно все действия, связанные с добавлением записей в реестр Windows, прописываются в установщике приложения. Однако возможен и вариант создания REG-файла, который нужно было импортировать вручную. При составлении параметров записи важно учитывать, для какого пользователя вносятся изменения: если запись добавляется только для текущего пользователя, то используется ветка HKCU (HKEY_CURRENT_USER). Если же требуется реализация изменений для всех пользователей системы, то необходимо работать с веткой HKLM (HKEY_LOCAL_MACHINE), но это требует административных прав.
В установщиках приложений для указания пути до приложения обычно используются макросы, а в файле REG приходится указать полный путь до приложения заранее. В приведённом ниже примере предполагается, что приложение будет расположено в папке C:\tmp\loo_plug\
, а иконка для файла будет браться из ресурса 1
.
Пример добавления записей в реестр:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\.lpf]
@="loo_plug_file"
[HKEY_CURRENT_USER\Software\Classes\loo_plug_file]
@=""
"EditFlags"=dword:00000000
"BrowserFlags"=dword:00000008
[HKEY_CURRENT_USER\Software\Classes\loo_plug_file\DefaultIcon]
@="\"C:\\tmp\\loo_plug\\loo_lpug.exe\",1"
[HKEY_CURRENT_USER\Software\Classes\loo_plug_file\shell]
[HKEY_CURRENT_USER\Software\Classes\loo_plug_file\shell\open]
@=""
[HKEY_CURRENT_USER\Software\Classes\loo_plug_file\shell\open\command]
@="\"C:\\tmp\\loo_plug\\loo_lpug.exe\" \"%1\""
Обработка передаваемых параметров командной строки
После внесения записи в реестр при двойном клике на файле с расширением .lpf система Windows будет запускать наше приложение и передавать путь к этому файлу в качестве аргумента командной строки. Поэтому необходимо, чтобы приложение корректно обрабатывало параметры командной строки, которые в него передаются.
Важно учитывать, что помимо пути к файлу могут передаваться и другие параметры с аргументами. Например, путь к файлу может быть не первым, а вторым или даже третьим аргументом. По этой причине при обработке параметров желательно анализировать их последовательно и выбирать тот, который соответствует нужному критерию — в нашем случае, заканчивается на ".lpf".
В заглушке я включил обработку передаваемых параметров командной строки в процедуру, которая назначена на создание главной формы OnFormCreate
.
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
param: string;
begin
for i := 1 to ParamCount do
begin
param := ParamStr(i);
if LowerCase(ExtractFileExt(param)) = '.lpf' then
begin
// Найден параметр с расширением .lpf
// Выполняется загрузка данных ...
end;
end;
end;
Открытие файла перетаскиванием
Открытие файла перетаскиванием на форму в самой заглушке не реализовывалось, но реализация такой функции достаточно проста. Для этого в настройках формы необходимо включить пункт AllowDropFiles
, а далее создать функцию обработчика событий OnDropFiles
. В функцию будет передан массив строк с путями до файлов, которые были перенесены на форму приложения. После фильтрации их можно передавать в функцию загрузки данных из файла.
Поддержка открытия ссылки собственного протокола
Для того чтобы обрабатывать собственный протокол, как и в случае с ассоциацией типа файла, необходимо внести записи в реестр. Для обработки протокола ASK приложением заглушкой, которое будет находиться по пути C:\tmp\loo_plug\
, необходимо добавить в реестр следующие записи:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\ask]
"URL Protocol"=""
[HKEY_CURRENT_USER\Software\Classes\ask\DefaultIcon]
@="C:\\tmp\\loo_plug\\loo_lpug.exe,0"
[HKEY_CURRENT_USER\Software\Classes\ask\Shell]
[HKEY_CURRENT_USER\Software\Classes\ask\Shell\Open]
[HKEY_CURRENT_USER\Software\Classes\ask\Shell\Open\Command]
@="\"C:\\tmp\\loo_plug\\loo_lpug.exe\" \"%1\""
Поскольку ранее мы реализовали обработку только аргументов, оканчивающихся на ".lpf", теперь необходимо добавить поддержку строк, начинающихся с "ask:", и передавать такие строки в функцию, которая вернёт ИД объекта.
Пример кода функции, для сборки нужно включить в uses модуль base64
function ExtractAndDecode(const input: string; out ObjectID: Integer; out DatabaseName: string): Boolean;
var
paramsStart, paramsEnd: Integer;
paramsValue, decodedString: string;
elements: TStringArray;
begin
ObjectID := 0;
DatabaseName := '';
paramsStart := Pos('params=', input);
if paramsStart = 0 then Exit(False);
paramsStart := paramsStart + Length('params=');
paramsEnd := Length(input);
paramsValue := Copy(input, paramsStart, paramsEnd - paramsStart + 1);
decodedString := DecodeStringBase64(paramsValue);
if decodedString = '' then Exit(False);
elements := decodedString.Split(['|']);
if Length(elements) < 4 then Exit(False);
DatabaseName := elements[1];
try
ObjectID := StrToInt(elements[3]);
except
Exit(False);
end;
result:=True;
end;
Чтобы для каждой новой ссылки не запускался свой экземпляр приложения, нужно организовать передачу информации от вновь запускаемого дубликата в уже запущенное приложение. Такой вариант можно реализовать, используя связку Mutex и Named Pipes, но об этом расскажу в следуюoщей статье.
Создание ярлыка со ссылкой "вытягиванием" объекта
В Lazarus, к сожалению, отсутствует встроенная поддержка простого механизма "вытягивания" объектов за пределы формы, аналогичного механизму перетаскивания файлов из системы на форму. Однако для упрощения этой задачи, можно использовать модуль uShellDragDrop, который предоставляет готовые функции для реализации как вытягивания объектов за пределы формы, так и копирования их в буфер обмена.
Модуль был найден на форуме Lazarus в ветке, где участник форума под псевдонимом ASerge, представил этот модуль в ответ на запрос другого пользователя, желающего реализовать перетаскивание файлов из приложения Lazarus в другие программы, поддерживающие WM_DROPFILES.
Основная идея состоит в следующем:
На основе данных приложения создается временный файл.
С помощью функции DragandDropCopyComplete из модуля uShellDragDrop.pp этот файл передается в целевую директорию.
Файл, который мы создаём, представляет собой обычный INI-файл с расширением .URL, содержащий ссылку на нужный ресурс или действие. Пример содержимого такого файла:
[InternetShortcut]
URL=ask:Loodsman.URL?Action=Navigate,params=MHxBS19QbG0wMXwyODk4fDEwMTI=
IconIndex=1
IconFile=C:\tmp\loo_plug\loo_lpug.exe
Что записано внутри файла:
URL указывает на специальный протокол ask:, который будет обработан соответствующим приложением.
IconFile задаёт путь к иконке, которая будет использоваться для ярлыка.
После выполнения функции DragandDropCopyComplete, в целевой директории появится копия временного .URL-файла — полноценный ярлык. При его запуске будет автоматически вызвано приложение, ответственное за обработку протокола ask:
.
Заключение
Надеюсь, приведенные выше примеры пригодятся вам для понимания того, как организовать взаимодействие между пользователем, системой и вашим приложением. А в следующем материале я продолжу эту тему и расскажу, как организовать передачу данных между экземплярами приложения с помощью Mutex и Named Pipes, чтобы избежать запуска дублирующихся копий клиента и обеспечить "бесшовную" обработку новых запросов.