unit1.pas
来自「Drag files and Drop to delphi forms 0402」· PAS 代码 · 共 580 行 · 第 1/2 页
PAS
580 行
// items before we show the drag image again.
DropPIDLTarget1.ShowImage := True;
end;
end;
// Only allow a drop into current folder if we ourself are not the source,
// and the destination folder isn't virtual...
if (FIsDragging) or (PathCombobox.IsVirtualPath) then
Effect := DROPEFFECT_NONE;
end else
if (Listview1.DropTarget = NewTargetListItem) then
//Effect := Effect //ie: don't fiddle with Effect
else
if (TLVItemData(NewTargetListItem.data).sortstr[1] = '1') then
begin
// only allow file system folders to be targets...
// Hide the drag image...
DropPIDLTarget1.ShowImage := false;
try
// Cancel current droptarget folder as droptarget...
Listview1.DropTarget := nil;
// set the new droptarget folder...
Listview1.DropTarget := NewTargetListItem;
Listview1.Update;
finally
// windows must have time to repaint the invalidated listview
// items before we show the drag image again.
DropPIDLTarget1.ShowImage := True;
end;
end else
Effect := DROPEFFECT_NONE;
end;
//---------------------------------------------------------------------
procedure TForm1.DropPIDLTarget1Drop(Sender: TObject;
ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
var
i: integer;
fos: TShFileOpStruct;
strFrom, strTo, DestPath: string;
Operation: integer;
begin
//first, where are we dropping TO...
strTo := '';
if (Listview1.DropTarget <> nil) then
//dropping into a subfolder...
with TLVItemData(Listview1.DropTarget.data) do
begin
if sortstr[1] = '1' then
strTo := copy(sortstr,2,MAX_PATH)+#0#0
else
Effect := DROPEFFECT_NONE; //subfolder must be a system folder!
end
else if PathComboBox.path <> '' then
//OK, dropping into current folder...
strTo := PathComboBox.path +#0#0
else
Effect := DROPEFFECT_NONE; //current folder must be a system folder!
Operation := 0;
case Effect of
DROPEFFECT_COPY: Operation := FO_COPY;
DROPEFFECT_MOVE: Operation := FO_MOVE;
else
Effect := DROPEFFECT_NONE;
end;
// Only allow a Copy or Move operation...
// otherwise stop and signal to source that no drop occured.
if Effect = DROPEFFECT_NONE then
exit;
// now, where are we dropping FROM...
strFrom := '';
with DropPIDLTarget1 do
begin
for i := 0 to Filenames.count-1 do
if Filenames[i] = '' then
exit
else // quit if 'virtual'
strFrom := strFrom + Filenames[i]+#0;
end;
if strFrom = '' then
begin
//signal to source something wrong...
Effect := DROPEFFECT_NONE;
exit;
end;
with fos do
begin
wnd := self.handle;
wFunc := Operation;
pFrom := PChar(strFrom);
pTo := PChar(strTo);
fFlags := FOF_ALLOWUNDO;
hNameMappings:= nil;
end;
try
// Copy or move the files
SHFileOperation(fos);
except
// Avoid that an exception interrupts the drag/drop prematurely.
on E: Exception do
begin
Application.ShowException(E);
Effect := DROPEFFECT_NONE;
exit;
end;
end;
//if dropped files need to be renamed -
//(eg if they have been dragged from the recycle bin) ...
with DropPIDLTarget1 do
if MappedNames.count > 0 then
begin
if PathComboBox.path[length(PathComboBox.path)] <> '\' then
DestPath := PathComboBox.path + '\' else
DestPath := PathComboBox.path;
for i := 0 to MappedNames.count-1 do
begin
if fileexists(DestPath+ extractfilename(filenames[i])) then
renamefile(DestPath+ extractfilename(filenames[i]),
DestPath+MappedNames[i]);
end;
end;
RefreshListNames;
end;
//---------------------------------------------------------------------
procedure TForm1.SetCurrentFolder;
var
sfi: tshfileinfo;
begin
if PathComboBox.Pidl <> nil then
begin
//Get CurrentShellFolder...
//nb: DesktopShellFolder is a Global Variable declared in PathComboBox.
if PathComboBox.itemindex = 0 then //Desktop folder
CurrentShellFolder := DesktopShellFolder else
DesktopShellFolder.BindToObject(PathComboBox.Pidl,
nil, IID_IShellFolder, pointer(CurrentShellFolder));
//Get CurrentFolder's ImageIndex...
shgetfileinfo(pChar(PathComboBox.Pidl),
0,sfi,sizeof(tshfileinfo), SHGFI_PIDL or SHGFI_ICON);
CurrentFolderImageIndex := sfi.iIcon;
RefreshListNames;
end;
// Don't allow a drop onto a virtual folder...
if PathComboBox.path <> '' then
DropPIDLTarget1.DragTypes := [dtCopy,dtMove]
else
DropPIDLTarget1.DragTypes := [];
sbUpLevel.Enabled := (PathComboBox.ItemIndex <> 0);
end;
//---------------------------------------------------------------------
procedure TForm1.RefreshListNames;
var
i: integer;
begin
with Listview1.items do
begin
beginupdate;
for i := 0 to Count-1 do
TLVItemData(Item[i].data).free;
clear;
screen.cursor := crHourglass;
PopulateListview;
screen.cursor := crDefault;
endupdate;
end;
end;
//---------------------------------------------------------------------
procedure TForm1.PopulateListview;
var
EnumIdList: IEnumIdList;
tmpPIDL: pItemIDList;
NewItem: TListItem;
ItemData: TLVItemData;
sfi: TShFileInfo;
Flags, dummy: DWORD;
begin
if CurrentShellFolder = nil then
exit;
with Listview1.items do
begin
//get files and folders...
Flags := SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN;
if FAILED(CurrentShellFolder.EnumObjects(0,Flags,EnumIdList)) then exit;
while (EnumIdList.Next(1,tmpPIDL,dummy) = NOERROR) do
begin
NewItem := Add;
NewItem.caption := GetPIDLDisplayName(CurrentShellFolder,tmpPIDL);
ItemData := TLVItemData.create;
NewItem.data := ItemData;
ItemData.RelativePIDL := tmpPIDL;
ItemData.AbsolutePIDL := ILCombine(PathComboBox.Pidl,tmpPIDL);
shgetfileinfo(pChar(ItemData.AbsolutePIDL),
0,sfi,sizeof(tshfileinfo), SHGFI_PIDL or SHGFI_ICON or SHGFI_ATTRIBUTES);
NewItem.ImageIndex := sfi.iIcon;
//get sort order...
if (sfi.dwAttributes and SFGAO_FOLDER)<>0 then
begin
if (sfi.dwAttributes and SFGAO_FILESYSTEM)<>0 then
//file system folder
ItemData.SortStr := '1'+ GetPathName(CurrentShellFolder,tmpPIDL)
else
//virtual folder
ItemData.SortStr := '2'+ GetPathName(CurrentShellFolder,tmpPIDL);
end
else
//files
ItemData.SortStr := '9'+ GetPathName(CurrentShellFolder,tmpPIDL);
end;
end;
ListView1.CustomSort(TLVCompare(@ListviewSort), 0);
if Listview1.items.count > 0 then
Listview1.items[0].focused := true;
end;
//---------------------------------------------------------------------
procedure TForm1.PathComboBoxChange(Sender: TObject);
begin
SetCurrentFolder;
caption := PathComboBox.path;
end;
//---------------------------------------------------------------------
//If a folder double-clicked - open that folder...
procedure TForm1.ListView1DblClick(Sender: TObject);
var
SelItem: TListItem;
begin
SelItem := Listview1.Selected;
if SelItem = nil then exit;
with TLVItemData(SelItem.data) do
if (sortstr[1] < '9') then //if a folder...
PathComboBox.Pidl := AbsolutePIDL;
end;
//---------------------------------------------------------------------
//If a folder selected - open that folder...
procedure TForm1.ListView1KeyPress(Sender: TObject; var Key: Char);
var
SelItem: TListItem;
begin
SelItem := Listview1.Selected;
if (SelItem = nil) or (ord(Key) <> VK_RETURN) then exit;
with TLVItemData(SelItem.data) do
if (sortstr[1] < '9') then //if a folder...
PathComboBox.Pidl := AbsolutePIDL;
end;
//---------------------------------------------------------------------
procedure TForm1.sbUpLevelClick(Sender: TObject);
var
tmpPidl: pItemIdList;
begin
if PathComboBox.ItemIndex > 0 then
begin
tmpPidl := ILClone(PathComboBox.Pidl);
ILRemoveLastID(tmpPidl);
PathComboBox.Pidl := tmpPidl;
ShellMalloc.Free(tmpPidl);
end;
end;
//---------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?