Копирование и вставка данных своего формата из буфера обмена
01.01.2007
// The TClipboard provides easy clipboard access. But what if you // want to add (several) custom defined items to the clipboard? // For all actions is the unit Clipboard required. uses Clipboard; // First you have to register your own ClipBoard format // Zuerst registrieren wir unser eigenes ClipBoard Format const MyClipboardFormatStr = 'MyData'; var MyClpFormat: integer; MyClpFormat := RegisterClipboardFormat(MyClipboardFormatStr); { The variable SLMClpFormat will contain a unique format handle for your own clipboard format. Die Variable SLMClpFormat enthalt ein einzigartiges Format Handle fur unser ClipBoard Format. } procedure IncPointer(var p: Pointer; increment: Integer); begin p := PChar(p) + Increment; end; // Say you have a data record defined as: // Definiere zuerst etwa einen solchen Daten Record: type PMyDataRec = ^TMyDataRec; TMyDataRec = record Name: string[50]; Value: Integer; end; { Furthermore let's say the data records are stored in a Listbox and shall be copied to a list box. Angenommen, die Daten Records sind in einer ListBox gespeichert und sollen in eine ListBox kopiert werden. } // Copy like this: procedure TForm1.CopyItems; var i: integer; dh: THandle; ic: integer; p: Pointer; pi: pInteger; begin // get number of items to be copied // Die Anzahl zu kopierenden Items ic := List1.SelCount; dh := GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT, (SizeOf(TMyDataRec) * ic) + SizeOf(Integer)); { allocate memory for all items plus for a integer variable giving you the number of copied items } p := GlobalLock(dh); { Lock the allocated memory } pi := pInteger(p); pi^ := ic; { write number of items to allocated memory } IncPointer(p, SizeOf(Integer)); { increment the pointer behind the written data } // You don't have to create an instance of clipboard, this is done automatically for i := 1 to List1.Items.Count do { check all items if they are selected } begin if List1.Items[i - 1].Selected then begin { This one is selected -> copy it o the clipboard } PMyDataRec(p)^ := PMyDataRec(List1.Items[i - 1].Data)^; { of course data must point to a TMyDataRec } IncPointer(p, SizeOf(TMyDataRec)); { increment the pointer behind the written data } end; end; // You have now filled the allocated memory with all items that shall be copied. // Now you can put them to the clipboard Clipboard.Open; { Open the clipboard will prevent overwriting of so far copied items } Clipboard.Clear; { Clear the clipboard first } Clipboard.SetAsHandle(MyClpFormat, Dh); { Copy to clipboard } Clipboard.Close; { finally close the clipboard } GlobalUnlock(dh); { and unlock the allocate memory. But don't free it, it will be used by the clipboard } if ic = 0 then GlobalFree(dh); { You can free it if you haven't copied anything } end; // Check first if your items are still available before pasting them from the clipbard if Clipboard.HasFormat(MyClpFormat) then begin Form1.Paste1.Enabled := True; { Yes, they are still available } end; // And this is, how you paste them after Paste1 is clicked procedure TMDIForm.Paste1Click(Sender: TObject); var dh: THandle; pdr: PSLMDataRec; i, ic: integer; p: Pointer; pi: pInteger; li: TListItem; begin if Clipboard.HasFormat(MyClpFormat) then // We have already checked, but maybe another application has overwritten the // clipboard in between.... begin ClipBoard.Open; { First open the clipboard again } dh := Clipboard.GetAsHandle(MyClpFormat); { Catch the handle to the stored items } p := GlobalLock(dh); { and lock it } pi := pInteger(p); { The first item is an integer giving the number of items } ic := pi^; { so get the number of items } IncPointer(p, SizeOf(Integer)); { increment the pointer behind the read data } for i := 1 to ic do { get all copied items one after another } begin li := List1.Items.Add; { first create a new listbox item } pdr := New(PMyDataRec); { Then create a new pointer to a TMyDataRec } pdr^ := PMyDataRec(p)^; { and fill it with data from the clipboard } IncPointer(p, SizeOf(TSLMDataRec)); { increment the pointer behind the written data } li.Data := pdr; { Set the data pointer of the list item to the new record } LI.Caption := pdr^.Name; { Let the item display the record field "Name" } // You can of course add more record fields if the item has subitems: LI.SubItems.Add(IntToStr(Value)); end; { All data retrieved from clipboard } Clipboard.Close; { Close it } GlobalUnlock(dh); { and unlock the pointer, but don't free it. This will be done by the clipboard itself, if necessary } end; end;
Взято с сайта: https://www.swissdelphicenter.ch
{ Copyright © 1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira } unit cbdata; interface uses SysUtils, Windows, clipbrd; const DDGData = 'CF_DDG'; // constant for registering the clipboard format. type // Record data to be stored to the clipboard TDataRec = packed record LName: string[10]; FName: string[10]; MI: string[2]; Age: Integer; BirthDate: TDateTime; end; { Define an object around the TDataRec that contains the methods for copying and pasting the data to and from the clipboard } TData = class public Rec: TDataRec; procedure CopyToClipBoard; procedure GetFromClipBoard; end; var CF_DDGDATA: word; // Receives the return value of RegisterClipboardFormat(). implementation procedure TData.CopyToClipBoard; { This function copies the contents of the TDataRec field, Rec, to the clipboard as both binary data, as text. Both formats will be available from the clipboard } const CRLF = #13#10; var Data: THandle; DataPtr: Pointer; TempStr: string[50]; begin // Allocate SizeOf(TDataRec) bytes from the heap Data := GlobalAlloc(GMEM_MOVEABLE, SizeOf(TDataRec)); try // Obtain a pointer to the first byte of the allocated memory DataPtr := GlobalLock(Data); try // Move the data in Rec to the memory block Move(Rec, DataPtr^, SizeOf(TDataRec)); { Clipboard.Open must be called if multiple clipboard formats are being copied to the clipboard at once. Otherwise, if only one format is being copied the call isn't necessary } ClipBoard.Open; try // First copy the data as its custom format ClipBoard.SetAsHandle(CF_DDGDATA, Data); // Now copy the data as text format with Rec do TempStr := FName + CRLF + LName + CRLF + MI + CRLF + IntToStr(Age) + CRLF + DateTimeToStr(BirthDate); ClipBoard.AsText := TempStr; { If a call to Clipboard.Open is made you must match it with a call to Clipboard.Close } finally Clipboard.Close end; finally // Unlock the globally allocated memory GlobalUnlock(Data); end; except { A call to GlobalFree is required only if an exception occurs. Otherwise, the clipboard takes over managing any allocated memory to it.} GlobalFree(Data); raise; end; end; procedure TData.GetFromClipBoard; { This method pastes memory saved in the clipboard if it is of the format CF_DDGDATA. This data is stored in the TDataRec field of this object. } var Data: THandle; DataPtr: Pointer; Size: Integer; begin // Obtain a handle to the clipboard Data := ClipBoard.GetAsHandle(CF_DDGDATA); if Data = 0 then Exit; // Obtain a pointer to the memory block referred to by Data DataPtr := GlobalLock(Data); try // Obtain the size of the data to retrieve if SizeOf(TDataRec) > GlobalSize(Data) then Size := GlobalSize(Data) else Size := SizeOf(TDataRec); // Copy the data to the TDataRec field Move(DataPtr^, Rec, Size) finally // Free the pointer to the memory block. GlobalUnlock(Data); end; end; initialization // Register the custom clipboard format CF_DDGDATA := RegisterClipBoardFormat(DDGData); end.
{ Copyright © 1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira } unit MainFrm; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, clipbrd, Mask, ComCtrls; type TMainForm = class(TForm) edtFirstName: TEdit; edtLastName: TEdit; edtMI: TEdit; btnCopy: TButton; btnPaste: TButton; meAge: TMaskEdit; btnClear: TButton; lblFirstName: TLabel; lblLastName: TLabel; lblMI: TLabel; lblAge: TLabel; lblBirthDate: TLabel; memAsText: TMemo; lblCustom: TLabel; lblText: TLabel; dtpBirthDate: TDateTimePicker; procedure btnCopyClick(Sender: TObject); procedure btnPasteClick(Sender: TObject); procedure btnClearClick(Sender: TObject); end; var MainForm: TMainForm; implementation uses cbdata; {$R *.DFM} procedure TMainForm.btnCopyClick(Sender: TObject); // This method copies the data in the form's controls onto the clipboard var DataObj: TData; begin DataObj := TData.Create; try with DataObj.Rec do begin FName := edtFirstName.Text; LName := edtLastName.Text; MI := edtMI.Text; Age := StrToInt(meAge.Text); BirthDate := dtpBirthDate.Date; DataObj.CopyToClipBoard; end; finally DataObj.Free; end; end; procedure TMainForm.btnPasteClick(Sender: TObject); { This method pastes CF_DDGDATA formatted data from the clipboard to the form's controls. The text version of this data is copied to the form's TMemo component. } var DataObj: TData; begin btnClearClick(nil); DataObj := TData.Create; try // Check if the CF_DDGDATA format is available if ClipBoard.HasFormat(CF_DDGDATA) then // Copy the CF_DDGDATA formatted data to the form's controls with DataObj.Rec do begin DataObj.GetFromClipBoard; edtFirstName.Text := FName; edtLastName.Text := LName; edtMI.Text := MI; meAge.Text := IntToStr(Age); dtpBirthDate.Date := BirthDate; end; finally DataObj.Free; end; // Now copy the text version of the data to form's TMemo component. if ClipBoard.HasFormat(CF_TEXT) then memAsText.PasteFromClipBoard; end; procedure TMainForm.btnClearClick(Sender: TObject); var i: integer; begin // Clear the contents of all controls on the form for i := 0 to ComponentCount - 1 do if Components[i] is TCustomEdit then TCustomEdit(Components[i]).Text := ''; end; end.