Recent

Author Topic: [SOLVED] Copy file to clipboard  (Read 5125 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 951
[SOLVED] Copy file to clipboard
« on: September 28, 2020, 01:43:30 pm »
Hi All,

How do I copy a file to the clipboard?

Thanks in advance.
« Last Edit: September 29, 2020, 12:09:08 pm by pcurtis »
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Thaddy

  • Hero Member
  • *****
  • Posts: 14210
  • Probably until I exterminate Putin.
Re: Copy file to clipvoard
« Reply #1 on: September 28, 2020, 01:46:10 pm »
 E/g Tmemo.copytoclipboard?
Specialize a type, not a var.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipvoard
« Reply #2 on: September 28, 2020, 02:29:11 pm »
No, something like CopyToClipboad('c:\myfile.xml');
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #4 on: September 28, 2020, 03:13:47 pm »
I've tried

Code: Pascal  [Select][+][-]
  1. uses
  2.   Windows, ShlObj, Clipbrd;
  3.  
  4. procedure CopyFileToClipboard(FileList : string);
  5. var
  6.   DropFiles: PDropFiles;
  7.   hGlobal: THandle;
  8.   iLen: integer;
  9. begin
  10.   iLen := Length(FileList) + 2;
  11.   FileList := FileList + #0#0;
  12.   hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
  13.     SizeOf(TDropFiles) + iLen);
  14.   if (hGlobal = 0) then
  15.     raise Exception.Create('Could not allocate memory.');
  16.   begin
  17.     DropFiles := GlobalLock(hGlobal);
  18.     DropFiles^.pFiles := SizeOf(TDropFiles);
  19.     Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
  20.     GlobalUnlock(hGlobal);
  21.     OpenClipboard(Form1.Handle);
  22.     EmptyClipboard;
  23.     SetClipboardData(CF_HDROP,hGlobal);
  24.     CloseClipboard;
  25.    end;
  26. end;
  27.  
  28. procedure TForm1.btnPasteClick(Sender: TObject);
  29. begin
  30.   CopyFileToClipboard('d:\Lazarus\Icons\bug-64.ico');
  31. end;
  32.  

And can't get it to work.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Copy file to clipboard
« Reply #5 on: September 28, 2020, 03:26:39 pm »
And can't get it to work.
Works perfectly fine for me (just tested it)... but "can't get it to work" isn't a valid problem description.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #6 on: September 28, 2020, 03:28:47 pm »
I am trying emulate this :

1. Open Explorer and navigate to an image (test.xml for example)
2. Press CTRL+C
3. Open Wordpad
4. Press CTRL+V, and the image (test.xml in this example) appears
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Copy file to clipboard
« Reply #7 on: September 28, 2020, 03:36:23 pm »
I am trying emulate this :

1. Open Explorer and navigate to an image (test.xml for example)
2. Press CTRL+C
3. Open Wordpad
4. Press CTRL+V, and the image (test.xml in this example) appears
Ah, that's better.
The code you showed works fine in Windows Explorer. Run it, go to a empty folder and press CTRL+V (or right click and paste).
You see that it works for copying files in Explorer.

For pasting in Wordpad you need to copy it a different way.
Try a Clipboard viewer to see what's on the clipboard when you copy a file.
You'll see a FileList entry (which is for pasting in Explorer etc) and another format.
You need to emulate that format (I'm currently not sure what format that is, probably a CF_OBJECT - Any persistent object).
(Or with CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR)
« Last Edit: September 28, 2020, 03:38:44 pm by rvk »

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #8 on: September 28, 2020, 03:48:32 pm »
I can confirm that for copying the physical file it works.

I'm not sure what you mean by

Quote
You need to emulate that format (I'm currently not sure what format that is, probably a CF_OBJECT - Any persistent object).
(Or with CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR)
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Copy file to clipboard
« Reply #9 on: September 28, 2020, 04:20:05 pm »
I can confirm that for copying the physical file it works.
I'm not sure what you mean by
Quote
You need to emulate that format (I'm currently not sure what format that is, probably a CF_OBJECT - Any persistent object).
(Or with CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR)
Described as second method here: https://stackoverflow.com/a/44509407/1037511

Not sure if The Drag and Drop Component Suite for Delphi can be used or is already ported to Lazarus/FPC/
https://github.com/DelphiPraxis/The-Drag-and-Drop-Component-Suite-for-Delphi
https://www.freepascal.org/~michael/articles/dragdrop2/dragdrop2.pdf

Ah, there is a Fork: https://forum.lazarus.freepascal.org/index.php/topic,38761.msg264283.html#msg264283
Not sure if it compiles in current version.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #10 on: September 28, 2020, 05:38:46 pm »
OK.

Where or how do I get  CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS?
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Copy file to clipboard
« Reply #11 on: September 28, 2020, 08:03:20 pm »
Where or how do I get  CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS?
Code: Pascal  [Select][+][-]
  1. begin
  2.   CF_Names:=RegisterClipBoardFormat(CFSTR_FILEDESCRIPTOR);  
  3.   CF_Contents:=RegisterClipBoardFormat(CFSTR_FILECONTENTS);
  4. end;
but that's not the only thing you need if you look at the links I gave you.

Quote
2. use CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS instead of CF_HDROP. Then you can provide an IStream to your data (look at the RTL's TStreamAdapter class for wrapping a TStream inside of an IStream implementation). However, you cannot do this with SetClipboardData(), you would need to implement the IDataObject interface and use it with OleSetClipboard() instead.

It's also in the Drag and Drop Component Suite but I don't know how that one works for copying files to clipboard.
But you will always need to provide the data when the file is pasted (for Explorer it works because that one is alway in the air).

What are you using this for exactly????
It might be easier to issue a copy command to explorer.exe or Windows itself.
As an example this code from here works fine in Delphi.
It uses OleSetClipboard() to put the file descriptors on the clipboard and will paste fine to Wordpad.

Code: Pascal  [Select][+][-]
  1. uses
  2.   System.Classes, Winapi.Windows, Winapi.ActiveX, Winapi.Shlobj, Winapi.ShellAPI, System.Win.ComObj;
  3.  
  4. procedure CopyFilesToClipboard(const Folder: string; FileNames: TStrings);
  5. var
  6.   SF: IShellFolder;
  7.   PidlFolder: PItemIDList;
  8.   PidlChildren: array of PItemIDList;
  9.   Eaten: UINT;
  10.   Attrs: DWORD;
  11.   Obj: IDataObject;
  12.   I: Integer;
  13. begin
  14.   if (Folder = '') or (FileNames = nil) or (FileNames.Count = 0) then Exit;
  15.   OleCheck(SHParseDisplayName(PChar(Folder), nil, PidlFolder, 0, Attrs));
  16.   try
  17.     OleCheck(SHBindToObject(nil, PidlFolder, nil, IShellFolder, Pointer(SF)));
  18.   finally
  19.     CoTaskMemFree(PidlFolder);
  20.   end;
  21.   SetLength(PidlChildren, FileNames.Count);
  22.   for I := Low(PidlChildren) to High(PidlChildren) do
  23.     PidlChildren[i] := nil;
  24.   try
  25.     for I := 0 to FileNames.Count-1 do
  26.       OleCheck(SF.ParseDisplayName(0, nil, PChar(FileNames[i]), Eaten, PidlChildren[i], Attrs));
  27.     OleCheck(SF.GetUIObjectOf(0, FileNames.Count, PIdlChildren[0], IDataObject, nil, obj));
  28.   finally
  29.     for I := Low(PidlChildren) to High(PidlChildren) do
  30.     begin
  31.       if PidlChildren[i] <> nil then
  32.         CoTaskMemFree(PidlChildren[i]);
  33.     end;
  34.   end;
  35.   OleCheck(OleSetClipboard(obj));
  36.   OleCheck(OleFlushClipboard);
  37. end;
  38.  
  39. procedure TForm1.Button1Click(Sender: TObject);
  40. var
  41.   FileNames: TStringList;
  42. begin
  43.   FileNames := TStringList.Create;
  44.   try
  45.     FileNames.Add('test.txt');
  46.     CopyFilesToClipboard('D:\', FileNames);
  47.   finally
  48.     FileNames.Free;
  49.   end;
  50. end;

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #12 on: September 28, 2020, 08:29:49 pm »
I want to use it to put an image into a Richedit component.

Richedit doesn't support images directly, but you can copy/paste them.

How would / could I compile the above code in Laz?

And thanks for your time and help.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Copy file to clipboard
« Reply #13 on: September 28, 2020, 08:43:19 pm »
How would / could I compile the above code in Laz?
I don't know how to implement OleSetClipboard in Lazarus.
The only reference to OleSetClipboard I found for laz was in virtualtreeview.
You could look at that one to see how it's implemented.
(Can't look at it myself right now)

I want to use it to put an image into a Richedit component.
Richedit doesn't support images directly, but you can copy/paste them.
Richedit does support images.
What component are you using?

For example https://wiki.lazarus.freepascal.org/RichMemo#InsertImageFromFile

Another option could be to insert raw rtf data containing the picture.
https://stackoverflow.com/a/1490785/1037511

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Copy file to clipboard
« Reply #14 on: September 28, 2020, 08:58:38 pm »
The problem with InsertImageFromFile is that the image isn't rendered (just an icon appears), but works with copy / paste.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

 

TinyPortal © 2005-2018