size : 4722 uploaded_on : Tue Oct 13 00:00:00 1998 modified_on : Wed Dec 8 14:03:15 1999 title : Extended clipboard routines org_filename : clpbrd.txt author : Ulli Conrad authoremail : uconrad@gmx.net description : How to copy/paste custom items to/from the clipboard keywords : Custom clipboard formats tested : D3 submitted_by : The CKB Crew submitted_by_email : ckb@netalive.org uploaded_by : nobody modified_by : nobody owner : nobody lang : plain file-type : text/plain category : delphi-system32bit __END_OF_HEADER__ { How to copy/paste custom items to/from the clipboard by U. Conrad <uconrad@gmx.net> } // 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 // This can be done ny a Windows API function (unit ShellAPI) const MyClipboardFormatStr = 'MyData'; var MyClpFormat : integer; MyClpFormat:=RegisterClipboardFormat(MyClipboardFormatStr); // The variable SLMClpFormat will contain a unique format handle for // your own clipboard format. // Then you can start copy items to the clipboard. You will need a // function for pointer incrementation which is given here: procedure IncPointer(var p : Pointer;increment : integer); begin p:=PChar(p)+Increment; end; // Say you have a data record defined as type PMyDataRec = ^TMyDataRec; TMyDataRec = record Name : string[50]; Value : integer; end; // This will work of course also with other types // Furthermore let's say the data records are stored in a Listbox // and shall be copied to a list box. // Copy like this: procedure TForm1.CopyItems; var i : integer; dh : THandle; ic : integer; p : Pointer; pi : pInteger; begin ic:=List1.SelCount; { get number of items to be copied } dh:=GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,(SizeOf(TMyDataRec)*ic)+SizeOf(Integer)); { alloc 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;