1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Issue 2400 – Pasting cut files from the clipboard into a local panel copies them instead of moving them

https://winscp.net/tracker/2400

Source commit: 1611bbe26e4d713795c2b07e1f17146a31f4461b
This commit is contained in:
Martin Prikryl
2025-11-03 20:26:50 +00:00
parent f22f2758e4
commit 316475d1fe
5 changed files with 52 additions and 77 deletions

View File

@@ -467,18 +467,19 @@ bool __fastcall TUnixDirView::PasteFromClipBoard(UnicodeString TargetPath)
{
DragDropFilesEx->FileList->Clear();
bool Result = false;
int Effect;
if (CanPasteFromClipBoard() &&
DragDropFilesEx->GetFromClipboard())
DragDropFilesEx->GetFromClipboard(Effect))
{
if (TargetPath.IsEmpty())
{
TargetPath = PathName;
}
PerformItemDragDropOperation(NULL, DROPEFFECT_COPY, true);
PerformItemDragDropOperation(NULL, Effect, true);
if (OnDDExecuted != NULL)
{
OnDDExecuted(this, DROPEFFECT_COPY);
OnDDExecuted(this, Effect);
}
Result = true;
}

View File

@@ -192,6 +192,7 @@ type
procedure SuggestDropEffect(grfKeyState: LongInt; var dwEffect: LongInt); virtual;
procedure AcceptDataObject(DataObj: IDataObject; var Accept:Boolean); virtual;
procedure RenderDropped(DataObj: IDataObject; grfKeyState: LongInt; pt: TPoint; var dwEffect: LongInt); virtual;
function GetPreferredDropEffect(const DataObj: IDataObject): LongInt;
public
constructor Create(AOwner: TDragDrop);
destructor Destroy; override;
@@ -338,7 +339,7 @@ type
function ExecuteOperation(DataObject: TDataObject): TDragResult;
function Execute: TDragResult;
function CopyToClipboard: Boolean; virtual;
function GetFromClipboard: Boolean; virtual;
function GetFromClipboard(var dwEffect: LongInt): Boolean; virtual;
procedure StartDnDDetection(Button: TMouseButton); virtual;
property OwnerIsSource:Boolean read FOwnerIsSource;
property Registered: Boolean read FRegistered default False;
@@ -1200,25 +1201,13 @@ begin
Accept := True;
end;
function TDropTarget.DragEnter(
const dataObj: IDataObject; grfKeyState: LongInt; pt: TPoint; var dwEffect: LongInt): HResult;
// Is called if the d&d-mouse cursor moves ON (one call only) the TargeTWinControl. Here,
// you influence if a drop can be accepted and the drop's effect if accepted.
function TDropTarget.GetPreferredDropEffect(const DataObj: IDataObject): LongInt;
var
FormatEtc: TFormatEtc;
StgMedium: TStgMedium;
Ptr: Pointer;
begin
TDragDrop(FOwner).FInternalSource := GInternalSource;
FOwner.FAvailableDropEffects := dwEffect;
FOwner.FContextMenu := grfKeyState and MK_RBUTTON <> 0;
if (FOwner.RenderDataOn = rdoEnter) or (FOwner.RenderDataOn = rdoEnterAndDropSync) or
(FOwner.RenderDataOn = rdoEnterAndDropAsync) then
begin
RenderDropped(DataObj, grfKeyState, pt, dwEffect);
end;
FPreferredEffect := 0;
Result := 0;
with FormatEtc do
begin
cfFormat := CF_PREFERREDDROPEFFECT;
@@ -1227,14 +1216,14 @@ begin
lindex := -1;
tymed := TYMED_HGLOBAL;
end;
if dataObj.GetData(FormatEtc, StgMedium) = S_OK then
if DataObj.GetData(FormatEtc, StgMedium) = S_OK then
begin
try
if GlobalSize(StgMedium.HGlobal) = SizeOf(FPreferredEffect) then
if GlobalSize(StgMedium.HGlobal) = SizeOf(Result) then
begin
Ptr := GlobalLock(StgMedium.HGlobal);
try
FPreferredEffect := PLongInt(Ptr)^;
Result := PLongInt(Ptr)^;
finally
GlobalUnLock(StgMedium.HGlobal);
end;
@@ -1243,6 +1232,24 @@ begin
ReleaseStgMedium(StgMedium);
end;
end;
end;
function TDropTarget.DragEnter(
const dataObj: IDataObject; grfKeyState: LongInt; pt: TPoint; var dwEffect: LongInt): HResult;
// Is called if the d&d-mouse cursor moves ON (one call only) the TargeTWinControl. Here,
// you influence if a drop can be accepted and the drop's effect if accepted.
begin
TDragDrop(FOwner).FInternalSource := GInternalSource;
FOwner.FAvailableDropEffects := dwEffect;
FOwner.FContextMenu := grfKeyState and MK_RBUTTON <> 0;
if (FOwner.RenderDataOn = rdoEnter) or (FOwner.RenderDataOn = rdoEnterAndDropSync) or
(FOwner.RenderDataOn = rdoEnterAndDropAsync) then
begin
var dwEffectDummy: LongInt;
RenderDropped(DataObj, grfKeyState, pt, dwEffectDummy);
end;
FPreferredEffect := GetPreferredDropEffect(dataObj);
SuggestDropEffect(grfKeyState, dwEffect);
AcceptDataObject(DataObj, FAccept);
@@ -1434,7 +1441,8 @@ begin
mcursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
try
RenderDropped(DataObj, KeyState, pt, dwEffect);
var dwEffectDummy: LongInt;
RenderDropped(DataObj, KeyState, pt, dwEffectDummy);
finally
// Set old cursor
Screen.Cursor := mcursor;
@@ -1635,7 +1643,8 @@ begin
mcursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
try
FDropTarget.RenderDropped(FDataObj, FgrfKeyState, Fpt, FdwEffect);
var dwEffectDummy: LongInt;
FDropTarget.RenderDropped(FDataObj, FgrfKeyState, Fpt, dwEffectDummy);
FDataObj._Release;
finally
// Set old cursor
@@ -2025,11 +2034,10 @@ begin
end;
end;
function TDragDrop.GetFromClipboard: Boolean;
function TDragDrop.GetFromClipboard(var dwEffect: LongInt): Boolean;
var
DataObject: IDataObject;
pt: TPoint;
dwEffect: LongInt;
begin
Result := (OLEGetClipBoard(DataObject) = S_OK);
if Result then

View File

@@ -863,6 +863,10 @@ begin
ReleaseStgMedium(StgMedium);
end;
end;
var Effect := GetPreferredDropEffect(DataObj);
if Effect <> 0 then
dwEffect := Effect;
end;
// TShellExtension ---------------------------------------------------

View File

@@ -386,9 +386,6 @@ function DropFiles(
out SourcePath: string; out SourceIsDirectory: Boolean): Boolean;
procedure CheckCanOpenDirectory(Path: string);
var
LastClipBoardOperation: TClipBoardOperation;
implementation
uses
@@ -2190,7 +2187,6 @@ begin
if Verb = shcCut then
begin
ClearCutState;
LastClipBoardOperation := cboCut;
{Set property cut to TRUE for all selected items:}
Item := GetNextItem(nil, sdAll, [isSelected]);
while Assigned(Item) do
@@ -2205,7 +2201,6 @@ begin
if Verb = shcCopy then
begin
ClearCutState;
LastClipBoardOperation := cboCopy;
end
else
{----------- Paste ----------}
@@ -2244,7 +2239,6 @@ begin
if Verb = shcCut then
begin
ClearCutState;
LastClipBoardOperation := cboCut;
ItemFocused.Cut := True;
FAnyCut := True;
end
@@ -2253,7 +2247,6 @@ begin
if Verb = shcCopy then
begin
ClearCutState;
LastClipBoardOperation := cboCopy;
end
else
{----------- Paste ----------}
@@ -3285,7 +3278,6 @@ begin
end;
FAnyCut := False;
end;
LastClipBoardOperation := cboNone;
if Assigned(FDriveView) and
(TDriveView(FDriveView).LastPathCut <> '') then // prevent recursion
begin
@@ -3332,7 +3324,6 @@ begin
end;
Result := DragDropFilesEx.CopyToClipBoard;
LastClipBoardOperation := Operation;
end;
finally
Screen.Cursor := SaveCursor;
@@ -3350,33 +3341,17 @@ begin
end;
function TDirView.PasteFromClipBoard(TargetPath: string): Boolean;
var
Effect: LongInt;
begin
DragDropFilesEx.FileList.Clear;
Result := False;
if CanPasteFromClipBoard and {MP}DragDropFilesEx.GetFromClipBoard{/MP}
then
Result := CanPasteFromClipBoard and DragDropFilesEx.GetFromClipBoard(Effect);
if Result then
begin
if TargetPath = '' then
TargetPath := PathName;
case LastClipBoardOperation of
cboNone:
begin
PerformDragDropFileOperation(TargetPath, DROPEFFECT_COPY);
if Assigned(OnDDExecuted) then OnDDExecuted(Self, DROPEFFECT_COPY);
end;
cboCopy:
begin
PerformDragDropFileOperation(TargetPath, DROPEFFECT_COPY);
if Assigned(OnDDExecuted) then OnDDExecuted(Self, DROPEFFECT_COPY);
end;
cboCut:
begin
PerformDragDropFileOperation(TargetPath, DROPEFFECT_MOVE);
if Assigned(OnDDExecuted) then OnDDExecuted(Self, DROPEFFECT_MOVE);
EmptyClipBoard;
end;
end;
Result := True;
PerformDragDropFileOperation(TargetPath, Effect);
if Assigned(OnDDExecuted) then OnDDExecuted(Self, Effect);
end;
end; {PasteFromClipBoard}
@@ -3421,6 +3396,5 @@ end;
{=================================================================}
initialization
LastClipBoardOperation := cboNone;
DaylightHack := (not IsWin7);
end.

View File

@@ -2669,7 +2669,6 @@ begin
if Verb = shcCut then
begin
ClearCutState;
LastClipBoardOperation := cboCut;
FLastPathCut := NodePathName(Node);
Node.Cut := True;
end
@@ -2677,7 +2676,6 @@ begin
if Verb = shcCopy then
begin
ClearCutState;
LastClipBoardOperation := cboCopy;
end
else
if Verb = shcPaste then
@@ -2915,7 +2913,6 @@ begin
end;
FLastPathCut := '';
end;
LastClipBoardOperation := cboNone;
if Assigned(FDirView) and
FDirView.AnyCut then // prevent recursion
begin
@@ -2944,26 +2941,17 @@ begin
end; {CanPasteFromClipBoard}
procedure TDriveView.PasteFromClipBoard(Node: TTreeNode);
var
Effect: LongInt;
begin
ClearDragFileList(FDragDropFilesEx.FileList);
if CanPasteFromClipBoard and FDragDropFilesEx.GetFromClipBoard then
if CanPasteFromClipBoard and FDragDropFilesEx.GetFromClipBoard(Effect) then
begin
case LastClipBoardOperation of
cboCopy,
cboNone:
begin
PerformDragDropFileOperation(Node, DROPEFFECT_COPY);
if Assigned(FOnDDExecuted) then
FOnDDExecuted(Self, DROPEFFECT_COPY);
end;
cboCut:
begin
PerformDragDropFileOperation(Node, DROPEFFECT_MOVE);
if Assigned(FOnDDExecuted) then
FOnDDExecuted(Self, DROPEFFECT_MOVE);
EmptyClipBoard;
end;
end;
PerformDragDropFileOperation(Node, Effect);
if Assigned(FOnDDExecuted) then
FOnDDExecuted(Self, Effect);
if Effect = DROPEFFECT_MOVE then
EmptyClipBoard;
end;
end; {PasteFromClipBoard}