osapiutils
212 строк · 6.2 Кб
1unit OSAPIClipboardFile;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses Forms, Classes, SysUtils, ShlObj, ClipBrd, Windows, LazUtils;
8
9
10//Поместить ссылку на файл в буфер обмена для вставки в файловом менеджере
11function CopyFilesToClipboard(AFileList: TStrings; AMoveFiles: Boolean=False): boolean;
12
13
14implementation
15
16{
17DROPEFFECT Constants
18https://docs.microsoft.com/ru-ru/windows/win32/com/dropeffect-constants
19CF_HDROP
20https://docs.microsoft.com/en-us/windows/win32/shell/clipboard#cf_hdrop
21
22https://habr.com/ru/post/179131/
23}
24
25
26function HDropTrueString(Strs: TStrings) : string;
27{
28Функция преобразует TStirngs в спец-строку для Shell
29это спец-строка для буфера обмена, где строки разделены знаком #0
30и вся спец-строка строка заканчивается #0#0
31}
32var
33i:Integer;
34begin
35Result := '';
36
37for i:=0 to Strs.Count-1 do
38begin
39//Strs.Strings[i] := StringReplace(Strs.Strings[i], '\', '\\', [rfReplaceAll]);
40Result := Result + Strs.Strings[i] + char(0);
41end;
42
43Result := Result + char(0);
44
45end;
46
47//Поместить ссылку на файл в буфер обмена для вставки в файловом менеджере
48function CopyFilesToClipboard(AFileList: TStrings; AMoveFiles: Boolean=False): boolean;
49const
50CFSTR_PREFERREDDROPEFFECT = 'Preferred DropEffect';
51DROPEFFECT_COPY = 1;
52DROPEFFECT_MOVE = 2;
53var
54DropFiles : PDropFiles;
55hGlobal : THandle;
56iLen : Integer;
57f : Cardinal;
58d : PCardinal;
59FileList : String;
60begin
61Result :=False;
62FileList :=HDropTrueString(AFileList);
63try
64clipboard.Clear;
65OpenClipboard(Application.MainForm.Handle);
66
67iLen := 2*Length(FileList) * SizeOf(char);
68hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + iLen);
69try
70Win32Check(hGlobal <> 0);
71DropFiles := GlobalLock(hGlobal);
72try
73DropFiles^.pFiles := SizeOf(TDropFiles);
74
75{$IFDEF UNICODE}
76DropFiles^.fWide := true;
77{$ENDIF}
78
79Move(FileList[1], (PAnsiChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
80if SetClipboardData(CF_HDROP, hGlobal)<>0 then
81Result := True;
82finally
83GlobalUnlock(hGlobal);
84end;
85except
86GlobalFree(hGlobal);
87end;
88if Result and AMoveFiles then
89begin
90f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
91hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
92try
93d := PCardinal(GlobalLock(hGlobal));
94try
95d^ := DROPEFFECT_MOVE;
96if SetClipboardData(f, hGlobal)<>0 then
97Result := True;
98finally
99GlobalUnlock(hGlobal);
100end;
101except
102GlobalFree(hGlobal);
103end;
104end;
105finally
106CloseClipboard;
107end;
108end;
109
110{
111//== Paste
112procedure ClipBoard_DataPaste(const Target: string);
113{
114Эта функция вставит из буфера обмена файлы/папки,
115которые копировали/вырезали(Ctrl+C / Ctrl+X) в буфер в каком-либо фаловом менеджере(Проводник, ТоталКоммандер)
116
117Target - папка в которую будет вставлены данные
118Clipboard_OperationType - подфункция которая определяет что надо сделать: Копировать или Вырезать
119}
120
121var
122h : THandle;
123Sourse, sr : string;
124
125begin
126
127//Если то, что находиться в буфере
128//НЕ является файлами/папками, которые копированы/вырезаны, то выходим
129//CF_HDROP - дескриптор который идентифицирует список файлов.
130//Прикладная программа может извлечь информацию о файлах, передавая дескриптор функции DragQueryFile.
131if not Clipboard.HasFormat(CF_HDROP) then exit;
132
133
134Clipboard.Open;
135
136try
137
138h := GetClipboardData(CF_HDROP); //Не знаю будет ли работать
139
140if h <> 0
141then
142begin
143
144Sourse := Shell_Str( ClipBoard_GetDataList(h) );
145
146sr := Copy( Sourse, 0, Pos(#0, Sourse)-1 ); //Path №1
147sr := ExtractFilePath(sr); //Родительская папка Data
148
149
150if IncludeTrailingBackslash(sr) = IncludeTrailingBackslash(Target)
151
152then//Делаем копию фала: откуда copy туда и paste
153begin
154case Clipboard_SendType
155of
1565: Shell_DataOperations(sourse, target, FO_COPY, FOF_SIMPLEPROGRESS or FOF_RENAMEONCOLLISION );
1572: Shell_DataOperations(sourse, target, FO_MOVE, FOF_SIMPLEPROGRESS );
158end;
159end
160
161else
162begin
163case Clipboard_SendType
164of
1655: Shell_DataOperations(sourse, target, FO_COPY, FOF_SIMPLEPROGRESS );
1662: Shell_DataOperations(sourse, target, FO_MOVE, FOF_SIMPLEPROGRESS );
167end;
168end;
169
170end;
171
172finally
173Clipboard.Close;
174end;
175
176end;
177}
178{
179//==== List
180function ClipBoard_GetDataList(h: THandle) : TStrings;
181{
182Вы нажали Ctrl+C или Ctrl+X => послали данные в буфер обмена.
183Так вот эта функция возвращает список файлов/папок, которые посланы в буфер.
184}
185
186var
187FilePath: array [0..MAX_PATH] of Char;
188i, FileCount: Integer;
189
190begin
191
192Result := nil;
193
194if h = 0 then exit;
195
196Result := TStringList.Create;
197
198
199FileCount := DragQueryFile(h, $FFFFFFFF, nil, 0);
200
201for i := 0 to FileCount - 1
202do
203begin
204DragQueryFile(h, i, FilePath, SizeOf(FilePath));
205Result.Add(FilePath);
206end;
207
208end;
209}
210
211
212end.
213