Difference between revisions of "Clipboard/ru"

From Lazarus wiki
Jump to navigationJump to search
 
(7 intermediate revisions by 4 users not shown)
Line 17: Line 17:
 
|-
 
|-
 
| pcfPicture || image/lcl.picture
 
| pcfPicture || image/lcl.picture
 +
|-
 +
| pcfMetaFilePict || image/lcl.metafilepict
 
|-
 
|-
 
| pcfObject || application/lcl.object
 
| pcfObject || application/lcl.object
Line 24: Line 26:
 
| pcfCustomData || application/lcl.customdata
 
| pcfCustomData || application/lcl.customdata
 
|-
 
|-
| pcfDelphiText || text/plain
 
|-
 
| pcfDelphiBitmap || text/delphi.bitmap
 
|-
 
| pcfDelphiPicture || Delphi picture
 
|-
 
| pcfDelphiMetaFilePict || image/delphimetafilepict
 
|-
 
| pcfDelphiObject || application/delphi.object
 
|-
 
| pcfDelphiComponent || Delphi component
 
|-
 
| pcfKylixPicture || image/delphi.picture
 
|-
 
| pcfKylixBitmap || image/delphi.bitmap
 
|-
 
| pcfKylixDrawing || image/delphi.drawing
 
|-
 
| pcfKylixComponent || application/delphi.component
 
 
|}
 
|}
  
Line 50: Line 33:
  
 
Запись текста:
 
Запись текста:
<syntaxhighlight>Clipboard.AsText := 'Hello clipboard!';</syntaxhighlight>
+
<syntaxhighlight lang="pascal">Clipboard.AsText := 'Hello clipboard!';</syntaxhighlight>
  
 
Чтение текста:
 
Чтение текста:
<syntaxhighlight>ShowMessage('Clipboard content: ' + Clipboard.AsText);</syntaxhighlight>
+
<syntaxhighlight lang="pascal">ShowMessage('Clipboard content: ' + Clipboard.AsText);</syntaxhighlight>
  
 
'''Clipboard''' является объектом класса '''TClipboard''' и для его использования необходимо подключить модуль ''Clipbrd'' в разделе ''uses'':
 
'''Clipboard''' является объектом класса '''TClipboard''' и для его использования необходимо подключить модуль ''Clipbrd'' в разделе ''uses'':
  
<syntaxhighlight>uses
+
<syntaxhighlight lang="pascal">
 +
uses
 
..., Clipbrd;</syntaxhighlight>
 
..., Clipbrd;</syntaxhighlight>
  
Line 64: Line 48:
 
Некоторые визуальные компоненты, такие как [[TEdit/ru|TEdit]], [[TMemo/ru|TMemo]], [[TStringGrid/ru|TStringGrid]], [[TLabeledEdit/ru|TLabeledEdit]], [[TMaskEdit/ru|TMaskEdit]], [[TSpinEdit/ru|TSpinEdit]] и [[TFloatSpinEdit/ru|TFloatSpinEdit]] обладают возможностью выделения части текста, находящегося в них, и предоставляют дополнительные функциональные возможности для выделенного текста при работе с буфером обмена.  
 
Некоторые визуальные компоненты, такие как [[TEdit/ru|TEdit]], [[TMemo/ru|TMemo]], [[TStringGrid/ru|TStringGrid]], [[TLabeledEdit/ru|TLabeledEdit]], [[TMaskEdit/ru|TMaskEdit]], [[TSpinEdit/ru|TSpinEdit]] и [[TFloatSpinEdit/ru|TFloatSpinEdit]] обладают возможностью выделения части текста, находящегося в них, и предоставляют дополнительные функциональные возможности для выделенного текста при работе с буфером обмена.  
  
<syntaxhighlight>  procedure CopyToClipboard;  
+
<syntaxhighlight lang="pascal">   
 +
procedure CopyToClipboard;  
 
   procedure CutToClipboard;  
 
   procedure CutToClipboard;  
   procedure PasteFromClipboard;</syntaxhighlight>
+
   procedure PasteFromClipboard;
 +
</syntaxhighlight>
  
 
==Текст в формате HTML==
 
==Текст в формате HTML==
Line 73: Line 59:
  
 
Пример чтения из буфера обмена и записи в буфер обмена текста в формате HTML:
 
Пример чтения из буфера обмена и записи в буфер обмена текста в формате HTML:
<syntaxhighlight>uses
+
<syntaxhighlight lang="pascal">
 +
uses
 
   Clipbrd, ...;
 
   Clipbrd, ...;
 
var
 
var
Line 95: Line 82:
 
===Загрузка из буфера обмена===
 
===Загрузка из буфера обмена===
  
<syntaxhighlight>uses  
+
<syntaxhighlight lang="pascal">
 +
uses  
 
   Clipbrd, LCLIntf, LCLType, ...;
 
   Clipbrd, LCLIntf, LCLType, ...;
  
Line 104: Line 92:
 
   if Clipboard.HasFormat(PredefinedClipboardFormat(pcfBitmap)) then
 
   if Clipboard.HasFormat(PredefinedClipboardFormat(pcfBitmap)) then
 
     Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));
 
     Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));
end;</syntaxhighlight>
+
end;
 +
</syntaxhighlight>
  
 
===Сохранение в буфере обмена===
 
===Сохранение в буфере обмена===
  
<syntaxhighlight>uses  
+
<syntaxhighlight lang="pascal">
 +
uses  
 
   Clipbrd, ...;
 
   Clipbrd, ...;
  
Line 126: Line 116:
 
Пример кода для реализации обработчика сообщения:
 
Пример кода для реализации обработчика сообщения:
  
<syntaxhighlight>unit Unit1;
+
<syntaxhighlight lang="pascal">
 +
unit Unit1;
  
 
{$mode delphi}{$H+}
 
{$mode delphi}{$H+}
Line 206: Line 197:
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
  
==View the clipboard contents==
+
==Просмотр содержимого буфера обмена==
  
Sometimes its useful to see whats actually in the clipboard at any one time. Here are a couple of methods I use, on a form with a TMemo and a one second timer to do just that -  
+
Иногда бывает полезно посмотреть, что находится в данный момент в буфере обмена. Вот несколько методов, которые я использую (на форме расположен элемент [[TMemo/ru|TMemo]] и один таймер с интервалом 1 секунда) -  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
procedure TForm1.CheckClipboard();
 
procedure TForm1.CheckClipboard();
 
var
 
var
Line 221: Line 212:
 
         ClipBoard.SupportedFormats(List);
 
         ClipBoard.SupportedFormats(List);
 
         for i := 0 to List.Count-1 do begin
 
         for i := 0 to List.Count-1 do begin
             //Memo1.Append(List.Strings[i]);        // uncomment to see all available formats
+
             //Memo1.Append(List.Strings[i]);        // раскомментируйте, чтобы увидеть все доступные форматы
             case List.Strings[i] of                // show these specific ones
+
             case List.Strings[i] of                // показать конкретные форматы
 
                 'Rich Text Format', 'text/plain', 'UTF8_STRING' :
 
                 'Rich Text Format', 'text/plain', 'UTF8_STRING' :
 
                     ReadClip(List.Strings[i]);
 
                     ReadClip(List.Strings[i]);
Line 258: Line 249:
 
end;</syntaxhighlight>
 
end;</syntaxhighlight>
  
==How to fix empty GTK2 clipboard on exit==
+
==Как исправить пустой буфер обмена GTK2 при выходе==
  
Usually when your GTK2 app exits, it's clipboard becomes empty. Bad for usual user.
+
Обычно, когда ваше GTK2-приложение заверщается, его буфер обмена становится пустым. Для обычного пользователя это плохо. Этот модуль - грубое исправление, добавьте его где-нибудь в <code>uses</code>.
This unit is a dirty fix, add it to "uses" somewhere.
 
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
unit fix_gtk_clipboard;
 
unit fix_gtk_clipboard;
  
Line 287: Line 277:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
In May 2018 I (dbannon) found that putting this bit of code in a finalization section did fix the problem when the clipboard contents had come from the application itself but if it was there before the application started, that is, the application did not write to the clipboard, it introduces another, similar problem. Clipboard contents are, again, cleared in that case. And appears to happen because by time the finalization clause is executed, the clipboard has already been cleared.
+
В мае 2018 года я (dbannon) обнаружил, что помещение этого фрагмента кода в раздел <code>finalization</code> решает проблему, когда содержимое буфера обмена пришло из самого приложения, но если оно было там до запуска приложения, то есть приложение не записывало в буфер обмена, он представляет другую, похожую проблему. В этом случае содержимое буфера обмена снова очищается. И, похоже, это происходит потому, что к моменту выполнения условия завершения буфер обмена уже очищен.
  
An easy solution is to put that same code into the main form's onClose event. Its early enough that the contents, from either source are still there and late enough not to be subsequently cleared.
+
Простое решение - поместить этот же код в событие <code>OnClose</code> основной формы. Достаточно рано, чтобы содержимое из любого источника все еще было там, и достаточно поздно, чтобы впоследствии его не очистить.
<syntaxhighlight>uses .... {$ifdef LINUX}gtk2, gdk2, Clipbrd{$endif};
+
<syntaxhighlight lang="pascal">
 +
uses ....  
 +
{$ifdef LINUX}gtk2, gdk2, Clipbrd{$endif};
 
.....
 
.....
 
procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 
procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
Line 307: Line 299:
 
==Внешние ссылки==
 
==Внешние ссылки==
  
* [http://delphi.about.com/od/vclusing/a/tclipboard.htm Базовые операции для работы с буфером обмена (вырезать/скопировать/вставить) при использовании объекта TClipboard]
+
* [http://delphi.about.com/od/vclusing/a/tclipboard.htm Базовые операции для работы с буфером обмена (вырезание/копирование/вставка) при использовании объекта TClipboard]
  
[[Category:Russian (unfinished translation)]]
+
[[Category:Russian]]

Latest revision as of 22:56, 10 July 2020

Deutsch (de) English (en) magyar (hu) русский (ru)


Предопределенные типы

TPredefinedClipboardFormat тип MIME
pcfText text/plain
pcfBitmap image/bmp
pcfPixmap image/xpm
pcfIcon image/lcl.icon
pcfPicture image/lcl.picture
pcfMetaFilePict image/lcl.metafilepict
pcfObject application/lcl.object
pcfComponent application/lcl.component
pcfCustomData application/lcl.customdata

Текст

Для использования с простым текстом объект Clipboard предоставляет свойство AsText, которое может быть использовано для чтения и записи текста.

Запись текста:

Clipboard.AsText := 'Hello clipboard!';

Чтение текста:

ShowMessage('Clipboard content: ' + Clipboard.AsText);

Clipboard является объектом класса TClipboard и для его использования необходимо подключить модуль Clipbrd в разделе uses:

uses
..., Clipbrd;

Текстовые элементы управления

Некоторые визуальные компоненты, такие как TEdit, TMemo, TStringGrid, TLabeledEdit, TMaskEdit, TSpinEdit и TFloatSpinEdit обладают возможностью выделения части текста, находящегося в них, и предоставляют дополнительные функциональные возможности для выделенного текста при работе с буфером обмена.

  
procedure CopyToClipboard; 
  procedure CutToClipboard; 
  procedure PasteFromClipboard;

Текст в формате HTML

Объект ClipBoard поддерживает чтение и запись текста в формате HTML.

Пример чтения из буфера обмена и записи в буфер обмена текста в формате HTML:

uses
  Clipbrd, ...;
var
  Html, PlainText: String;
...
begin
  Html := ClipBoard.GetAsHtml;
  ...
  Html := '<b>Formatted</b> text';
  PlainText := 'Simple Text';
  ClipBoard.SetAsHtml(Html, PlainText);
end.

Windows

Для обработки Html-текста в буфере обмена Windows требуется подключение заголовочных файлов.
В то время, как раньше пользователям необходимо было делать это вручную, теперь это прозрачно делается с помощью подключения модуля ClipBrd.

Изображения

Загрузка из буфера обмена

uses 
  Clipbrd, LCLIntf, LCLType, ...;

procedure LoadBitmapFromClipboard(Bitmap: TBitmap);
begin
  if Clipboard.HasFormat(PredefinedClipboardFormat(pcfDelphiBitmap)) then
    Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfDelphiBitmap));
  if Clipboard.HasFormat(PredefinedClipboardFormat(pcfBitmap)) then
    Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));
end;

Сохранение в буфере обмена

uses 
  Clipbrd, ...;

procedure SaveBitmapToClipboard(Bitmap: TBitmap);
begin
  Clipboard.Assign(Bitmap);
end;

Пользовательский формат

Multiple objects

Получение уведомления об изменении буфера обмена

LCL не передает сообщения Windows (передаются только сообщения WM_USER). Это означает, что вы должны написать свой обработчик сообщения.

Пример кода для реализации обработчика сообщения:

unit Unit1;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  Clipbrd, StdCtrls, Windows, Messages;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FNextClipboardOwner: HWnd;   // хэндл на следующий вьювер в цепочке
    // обработчики события буфера обмена
    function WMChangeCBChain(wParam: WParam; lParam: LParam):LRESULT;
    function WMDrawClipboard(wParam: WParam; lParam: LParam):LRESULT;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}
var
  PrevWndProc:windows.WNDPROC;

function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall;
begin
  if uMsg = WM_CHANGECBCHAIN then begin
    Result := Form1.WMChangeCBChain(wParam, lParam);
    Exit;
  end 
  else if uMsg=WM_DRAWCLIPBOARD then begin
    Result := Form1.WMDrawClipboard(wParam, lParam);
    Exit;
  end;
  Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  PrevWndProc := Windows.WNDPROC(SetWindowLong(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback))); // для x64 необходимо использовать SetWindowLongPtr
  FNextClipboardOwner := SetClipboardViewer(Self.Handle);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ChangeClipboardChain(Handle, FNextClipboardOwner);
end;

function TForm1.WMChangeCBChain(wParam: WParam; lParam: LParam): LRESULT;
var
  Remove, Next: THandle;
begin
  Remove := WParam;
  Next := LParam;
  if FNextClipboardOwner = Remove then FNextClipboardOwner := Next
    else if FNextClipboardOwner <> 0 then
      SendMessage(FNextClipboardOwner, WM_ChangeCBChain, Remove, Next)
end;

function TForm1.WMDrawClipboard(wParam: WParam; lParam: LParam): LRESULT;
begin
  if Clipboard.HasFormat(CF_TEXT) Then Begin
    ShowMessage(Clipboard.AsText);
  end;
  SendMessage(FNextClipboardOwner, WM_DRAWCLIPBOARD, 0, 0);   // ВАЖНО!
  Result := 0;
end;

end.

Просмотр содержимого буфера обмена

Иногда бывает полезно посмотреть, что находится в данный момент в буфере обмена. Вот несколько методов, которые я использую (на форме расположен элемент TMemo и один таймер с интервалом 1 секунда) -

procedure TForm1.CheckClipboard();
var
    I : integer;
    List : TStringList;
begin
    memo1.clear;
    Memo1.Append('[' + Clipboard.AsText + ']');
    List := TStringList.Create;
    try
        ClipBoard.SupportedFormats(List);
        for i := 0 to List.Count-1 do begin
            //Memo1.Append(List.Strings[i]);        // раскомментируйте, чтобы увидеть все доступные форматы
            case List.Strings[i] of                 // показать конкретные форматы
                'Rich Text Format', 'text/plain', 'UTF8_STRING' :
                    ReadClip(List.Strings[i]);
            end;
        end;
    finally
      List.Free;
    end;
end;

function TForm1.ReadClip(TheFormat : ANSIString) : ANSIString;
var
  Stream: TMemoryStream;
  Fmt : TClipboardFormat;
  List : TStringList;
begin
    if TheFormat = '' then exit;
    Stream := TMemoryStream.Create;
    List := TStringList.Create;
  try
    if Clipboard.HasFormatName(TheFormat) then begin
        Memo1.Append(#10+TheFormat);
        Fmt := ClipBoard.FindFormatID(TheFormat);
        ClipBoard.GetFormat(Fmt, Stream);
        if Stream.Size > 0 then begin
            Stream.Seek(0, soFromBeginning);
            List.LoadFromStream(Stream);
            Memo1.Lines.AddStrings(List, False);
        end;
    end;
  finally
    List.Free;
    Stream.Free;
  end;
end;

Как исправить пустой буфер обмена GTK2 при выходе

Обычно, когда ваше GTK2-приложение заверщается, его буфер обмена становится пустым. Для обычного пользователя это плохо. Этот модуль - грубое исправление, добавьте его где-нибудь в uses.

unit fix_gtk_clipboard;

{$mode objfpc}{$H+}

interface

uses
  gtk2, gdk2, Clipbrd;

implementation

var
  c: PGtkClipboard;
  t: string;

finalization
  c := gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
  t := Clipboard.AsText;
  gtk_clipboard_set_text(c, PChar(t), Length(t));
  gtk_clipboard_store(c);
end.

В мае 2018 года я (dbannon) обнаружил, что помещение этого фрагмента кода в раздел finalization решает проблему, когда содержимое буфера обмена пришло из самого приложения, но если оно было там до запуска приложения, то есть приложение не записывало в буфер обмена, он представляет другую, похожую проблему. В этом случае содержимое буфера обмена снова очищается. И, похоже, это происходит потому, что к моменту выполнения условия завершения буфер обмена уже очищен.

Простое решение - поместить этот же код в событие OnClose основной формы. Достаточно рано, чтобы содержимое из любого источника все еще было там, и достаточно поздно, чтобы впоследствии его не очистить.

uses .... 
{$ifdef LINUX}gtk2, gdk2, Clipbrd{$endif};
.....
procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
  c: PGtkClipboard;
  t: string;
begin
    {$ifdef LINUX}
    c := gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
    t := Clipboard.AsText;
    gtk_clipboard_set_text(c, PChar(t), Length(t));
    gtk_clipboard_store(c);
    {$endif}
end;

Внешние ссылки