Доброго времени суток дорогие читатели сайта. В этой статье, я хотел бы поговорить о том, как можно создать собственный формат данных и поместить его в буфер обмена, а затем вытащить его оттуда. Мы уже с Вами рассматривали статью о том, как работать с буфером обмена в Delphi. В данной статье мы рассмотрим продолжение.
Вообще, копирование пользовательского формата данных в буфер обмена, очень интересная и полезная штука в Ваших собственных приложениях, особенно для тех, в которых необходимо вводить похожие данные. Введя такую функцию в свою программу (сохранение в буфер обмена пользовательского формата данных), Вы бы, может, облегчили работу пользователя по вводу похожих данных, либо еще что-то.
Для этих целей, можно использовать различные временные файлы (.dat, .txt, .ini), это тоже будет правильно, но использование буфера для данных целей, будет более правильно.
Самое что интересное, Вы сможете использовать пользовательский формат данных в буфере обмена и в других своих приложениях, если будете знать название пользовательского формата данных для буфера обмена.
Ну что, давайте приступим. Для начала создадим новый проект и в Uses подключим модуль Clipbrd, который отвечает за работу буфера обмена.
Далее нам необходимо объявить переменную, которая будет отвечать за регистрацию нашего пользовательского формата данных в буфере обмена. У меня выглядит это следующим образом:
var
Form1: TForm1;
MyBufferFormat:Word;
Как видите, переменная MyBufferFormat будет отвечать за код формата, который будет зарегистрирован, а для регистрации нашего пользовательского формата, мы будем использовать функцию:
RegisterClipboardFormat(lpsz:Pchar):Integer
Как видите, в данную функцию необходимо передать только один параметр, и этот параметр означает имя нашего пользовательского формата. Если другие приложения будут знать имя или код пользовательского формата данных в буфере обмена, то они также смогут работать с ним.
Поэтому, для того, чтобы зарегистрировать новый формат данных, на событие OnCreate нашей формы напишем следующий код:
procedure TForm1.FormCreate(Sender: TObject);
begin
MyBufferFormat:=RegisterClipboardFormat('MyBufferFormat');
end;
В итоге, функция, как я говорил раньше, возвратит код формата. Но, если другое приложение будет пытаться зарегистрировать в своем приложении, с таким, же именем пользовательский формат данных, то ему возвратится код формата данных, зарегистрированного, ранним приложением, но работать с ним также сможет.
После того, как наш формат зарегистрированный (он будет регистрировать после каждого запуска нашего приложения), то нам необходимо его заполнить данным и поместить в буфер обмена. Для этого, нам необходимо объявить запись, которая будет помещаться в наш буфер.
У Вас запись может быть любого формата и любого названия, у меня она вышла про студентов:
type
TStudent = record
FIO:string[200];
Group:string[100];
PrepodFIO:string[200];
end;
Далее, нам необходимо объявить два метода, которые будут непосредственно отвечать за копирование нашего пользовательского формата, в буфер обмена, а также за извлечение наших пользовательских данных, из буфера обмена.
Для этого, я в спецификаторе доступа public, объявляю следующие методы:
public
{ Public declarations }
procedure CopyBuffer(Student:TStudent);
function LoadBuffer:TStudent;
end;
Это не обязательно делать в спецификаторе доступа public, по Вашему желанию.
Далее, курсором становися на процедуру CopyBuffer и нажимаем сочетание клавиш – Ctrl+Shift+C, в итоге, нам необходимо написать код, для нашей процедуры. Он, у нас будет выглядеть, примерно, следующим образом:
procedure TForm1.CopyBuffer(Student: TStudent);
var
h:THandle;
F:Pointer;
begin
h:=GlobalAlloc(GMEM_MOVEABLE,SizeOF(TStudent));
try
F:=GlobalLock(h);
Move(Student,F^,SizeOF(TStudent));
Clipboard.SetAsHandle(MyBufferFormat,h);
except
on e:Exception do
GlobalUnlock(h);
end;
end;
Давайте немного разберемся с ним. Функция GlobalAlloc выделяет некоторую область памяти (размер которой, равен размеру нашей записи), для того, чтобы мы могли записать в нее, пользовательские данные.
С помощью функции GlobalLock, мы фиксируем дискрептор объекта в области памяти и в дальнейшем, данная функция нам возвращает указатель на начальный байт блока памяти объекта.
Далее, мы с помощью Move помещаем содержимое нашей записи в область памяти, которая определена байтом F^ (мы это получили, при помощи функции GlobalLock).
Далее, для того, чтобы отправить данные в наш буфер, мы используем процедуру SetAsHandle, в параметрах которой, мы указываем наш пользовательский формат данных, а также указатель на дескриптор.
Вот и все. Если Вы это сделаете и нажмете на кнопку копировать и перейдете, например в MS Word или Блокнот, и попробуете вставить туда данные, то у Вас ничего не получится. Как я уже говорил, приложению необходимо знать код пользовательского формата данных, чтобы работать с ним.
Ну, теперь давайте перейдем к вставки данных из буфера обмена. Для этих целей, у нас используется функция LoadBuffer. Поэтому, давайте поставим на нее указатель мыши и нажмем сочетание клавиш Ctrl+Shift+C и начнем писать код, который будет идентичен, только все наоборот.
Ну, давайте посмотрим. Нам необходимо получить дескриптор нашего пользовательского формата данных, затем узнать область памяти, в которой размещаются наши данные и с помощью функции Move из памяти в нашу запись, скопировать данные (при копировании в буфер, мы из записи копировали в буфер обмена, то есть, наоборот). Вот и все, поэтому функция у меня выглядит следующим образом:
function TForm1.LoadBuffer: TStudent;
var
h:THandle;
F:Pointer;
begin
h:=Clipboard.GetAsHandle(MyBufferFormat);
if h<>0 then
begin
try
F:=GlobalLock(h);
Move(F^,Result,SizeOF(TStudent));
except
on e:Exception do
GlobalUnlock(h);
end;
end;
end;
Все, теперь нам необходимо лишь написать код для того, чтобы данные записывались в буфер и наоборот, оттуда извлекались.
Давайте на нашей форме разместим 3 компонента TEdit и два TButton. Поэтому на событие кнопки OnClick, которая отвечает за помещение пользовательских данных в буфер обмена, мы напишем следующий код:
procedure TForm1.Button1Click(Sender: TObject);
var
Stud:TStudent;
begin
Stud.FIO:=Edit1.Text;
Stud.Group:=Edit2.Text;
Stud.PrepodFIO:=Edit3.Text;
CopyBuffer(Stud);
end;
Все понятно тут, я думаю, заполняем нашу запись и вызываем процедуру, которая помещает данные в буфер обмена.
Как я говорил раньше, если Вы нажмете кнопку «Копировать» и попробуете вставить, например, в MS Word, у Вас ничего не получится, поэтому давайте на событие OnClick кнопки, которая отвечает за извлечение пользовательских данных из буфера обмена, напишем следующий код:
procedure TForm1.Button2Click(Sender: TObject);
var
Stud:TStudent;
begin
Stud:=LoadBuffer;
Edit1.Text:=Stud.FIO;
Edit2.Text:=Stud.Group;
Edit3.Text:=Stud.PrepodFIO;
end;
Тут, тоже должно быть все понятно. Вызываем функцию, которая извлекает пользовательские данные из буфера обмена, а она, как мы помним, возвращает нашу запись, которую потом мы выводим в TEdit. Вот так, выглядит наше приложение:
Заключение
В статье «Как работать с буфером обмена в Delphi«, мы рассматривали отличное свойство Formats. Используя данное свойство, мы можем получить доступ к любому пользовательскому формату данных, которые зарегистрированы в системе (а их может быть несколько), в параметр главное указать пользовательский формат, например:
Clipboard.Formats[MyBufferFormat];
Исходные коды статье, можно скачать здесь