Delphi: обмен данными между приложениями

КОМПЬЮТЕРНЫЕ КУРСЫ "ПОИСК"

[Главная страница] [Delphi] [Контакты]

Использование буфера обмена


Буфер обмена представляет собой область оперативной памяти, которая используется операционной системой для временного хранения данных. Он выступает в роли общего хранилища данных для всех приложений системы, фактически любая программа может записывать данные в буфер обмена и считывать их оттуда. Он способен хранить данные различных типов и, кроме данных, содержит сведения о типе хранимой информации. Буфер обмена является неотъемлемым компонентом операционной системы типа Windows.

Буфер обеспечивает простейший обмен данными между приложениями. Одно приложение помещает туда данные, другое — считывает данные из буфера. Как правило, эти действия (чтение и запись) выполняются при непосредственном участии пользователя. В использовании буфера может участвовать и одно приложение, в этом случае проходит обмен данными внутри его.

Для выполнения операции обмена данными через буфер в Delphi предназначен специальный класс TClipboard. В Delphi также имеется глобальный объект Clipboard, который является экземпляром класса TClipboard и представляет буфер обмена Windows.

При помощи свойств и методов объекта Clipboard возможно осуществление различных операций обмена или анализа хранимых данных. Для доступа к объекту буфера в разделе uses модуля, в котором выполняются операции с объектом буфера обмена, указывается модуль Clipbrd.

Общее количество форматов, поддерживаемых буфером обмена, содержится в свойстве FormatCount типа Integer. Для отображения количества форматов, которые распознает буфер, можно использовать следующий листинг:

//В разделе uses указываем модуль Clipbrd
Label1.Caption := IntToStr(Clipboard.FormatCount);

Буфер обмена поддерживает самые разнообразные типы данных. Приведем список поименованных констант некоторых форматов.

  • CF_TEXT - обычный текст (коды ANSI). Символ окончания строки — #10 и #13, окончание текста — #0.
  • CF_BITMAP - рисунок ВМР-формата.
  • CF_MetaFilePic - рисунок WMF-формата.
  • CF_TIFF - рисунок TIFF-формата.
  • CF_OEMTEXT - текст.
  • CF_DIB - рисунок DIB-формата.
  • CF_Wave - звук.
  • CF_UniCodeText - текст (коды Unicode).
  • CF_Picture - объект типа TPicture.
  • CF_COMPONENT - объект типа Persistent.

При необходимости можно создать и зарегистрировать свои форматы данных в дополнение к имеющимся базовым.

При использовании нестандартных форматов данных, помещаемых в буфер обмена и извлекаемых оттуда, программы должны соблюдать устанавливаемые разработчиками соглашения об обмене такими данными.

В листинге 1 приводится обработчик нажатия кнопки, загружающий в список ListBox1 о значения констант, идентифицирующих каждый формат данных буфера обмена.

Листинг 1. Отображение форматов буфера обмена


var
  i: Integer;
begin
  for i := 0 to Clipboard.FormatCount - 1 do
    ListBox1.Items.Append(IntToStr(Clipboard.Formats[i]));
end;

Приложение может помещать информацию в буфер обмена и извлекать ее только в тех форматах, которые будет поддерживать буфер. Список поддерживаемых форматов создается при инициализации приложения.

Перед доступом к данным, содержащимся объектом Clipboard, может потребоваться анализ формата данных, для этого служит метод НаsFomat. Процедура HasFormat(Format: Word) : Boolean используется для запроса к буферу обмена и позволяет узнать, можно ли извлечь хранимые в нем данные в заданном формате, указанном параметром Format. При положительном ответе возвращаемое значение равно True, в противном случае — False.

Буфер обмена часто используется для хранения текста, поэтому объект Clipboard имеет специальное свойство AsText типа String, предназначенное для обработки содержимого буфера как данных текстового формата. Свойство AsText предназначено как для чтения, так и для записи. При чтении свойства данные извлекаются из буфера, а при записи — заносятся в буфер обмена (листинг 2).

Листинг 2. Пример на использование HasFormat, AsText.


procedure TForm1.Button1Click(Sender: TObject);
begin
  if Clipboard.HasFormat(CF_TEXT) then
    Edit1.Text := Clipboard.AsText
else
  MessageDlg('There is no text on the Clipboard', mtInformation, [mbOK],0);
end;

Также копировать текст в буфер обмена можно при помощи метода SetTextBuf. Единственое, что необходимо здесь учесть, это то, что обязательно параметр передаваемый в SetTextBuf привести к типу PChar.

Clipboard.SetTextBuf(PChar(Edit1.Text));

Как правило, различные приложения используют буфер обмена. Но в случае, когда необходимо получить монопольный доступ к буферу, приложение должно открыть его для себя в специальном режиме. Для этого вызывается метод Open, позволяющий программе получить полный (исключительный) доступ к общей области обмена. После вызова метода Open содержимое буфера не может быть изменено другими приложениями, поэтому после окончания монопольного использования приложение должно вызвать метод Close объекта Clipboard. Если открытый буфер не был закрыт с помощью метода Close, то он будет автоматически закрыт системой после завершения программы, открывшей буфер обмена.

Листинг 3. Пример на использование Open, Close, GetAsHandle.


uses clipbrd;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  MyHandle: THandle;
  TextPtr: PChar;
begin
  ClipBoard.Open;
  try
    {$IFNDEF UNICODE}
    MyHandle := Clipboard.GetAsHandle(CF_TEXT);
    {$ELSE}
    MyHandle := Clipboard.GetAsHandle(CF_UNICODETEXT);
    {$ENDIF}

    TextPtr := GlobalLock(MyHandle);
    ListBox1.Items.Add(StrPas(TextPtr));
    GlobalUnlock(MyHandle);
  finally
    Clipboard.Close;
  end;
end;

Для очистки содержимого буфера обмена используется метод Clear. Он вызывается автоматически при изменении содержимого в буфере. Перед записью новых данных, помещаемых в буфер, старая информация удаляется.

Класс TClipboard используется многими другими классами и компонентами, которые поддерживают обмен данными через буфер обмена. К примеру, компоненты Memo и Edit имеют специальные методы для обмена текстовой информацией посредством буфера. Методы CopyToClipBoard и CutToClipBoard помещают текстовые данные в буфер обмена, копируя и вырезая их из источника (компонента) соответственно, а метод PasteFromClipBoard вставляет текстовый фрагмент из буфера в текстовое поле.

Только при использовании подобных методов лучше проверять, является ли содержимое буфера обмена текстовой информацией. В листинге 4 показан пример копирования в буфер обмена всего текста, введенного в текстовое поле.

Листинг 4. Копирование текста из поля редактора Memo1 в буфер обмена


procedure TForm1.Button1Click(Sender: TObject);
begin
  //Выделяем весь текст в поле редактора
  Memo1.SelectAll;
  //Копируем текст
  Memo1.CopyToClipboard;
end;

Буфер обмена часто используется для хранения текста, поэтому объект Clipboard имеет специальное свойство AsText типа String, предназначенное для обработки содержимого буфера как данных текстового формата. Свойство AsText предназначено как для чтения, так и для записи. При чтении свойства данные извлекаются из буфера, а при записи — заносятся в буфер обмена (листинг 2).

При работе с графическими компонентами для операций, связанных с обменом информацией через общую область, удобно использовать метод Assign. Процедура Assign (Source: TPersistent) присваивает буферу обмена объект, указанный параметром Source. Если объект является изображением и принадлежит таким графическим классам, как TBitmap,TPicture или TMetafile, то в буфер обмена копируется изображение установленного формата. Для извлечения изображения также может использоваться метод Assign.

Пример использования буфера обмена для копирования изображений приводится в листинге 5.

Листинг 5. Обмен изображением через буфер обмена.


procedure TForm1.Button1Click(Sender: TObject);
begin
  //Открываем монопольный доступ
  Clipboard.Open;
  //Заносим изображение в буфер
  Clipboard.Assign(Image1.Picture);
  //Проверяем формат находящихся в буфере данных
  if Clipboard.HasFormat(CF_PICTURE) then
    Image2.Picture.Assign(Clipboard);
  //Закрываем монопольный доступ к буферу
  Clipboard.Close;
end;

Используемая литература: Программирование в Delphi. Трюки и эффекты. Александр Чиртик