Когда необходимо обеспечить взаимодействие 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, чтобы избежать запуска дублирующихся копий клиента и обеспечить "бесшовную" обработку новых запросов.
