mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
FIX: Clipboard and drag&drop with unicode filenames.
This commit is contained in:
parent
eeb620b547
commit
cc93a10ff6
4 changed files with 749 additions and 724 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -120,6 +120,12 @@ type
|
|||
function Drop(const dataObj: IDataObject; grfKeyState: LongWord;
|
||||
pt: TPoint; var dwEffect: LongWord): HResult; stdcall;
|
||||
|
||||
{en
|
||||
Retrieves the filenames from the HDROP format
|
||||
as a list of UTF-8 strings.
|
||||
@returns(List of filenames or nil in case of an error.)
|
||||
}
|
||||
class function GetDropFilenames(hDropData: HDROP): TStringList;
|
||||
end;
|
||||
|
||||
{ TFileDropSource - èñòî÷íèê
|
||||
|
|
@ -229,7 +235,7 @@ type
|
|||
implementation
|
||||
|
||||
uses
|
||||
SysUtils, ShellAPI, ShlObj, LCLIntf, Win32Proc, uClipboard;
|
||||
SysUtils, ShellAPI, ShlObj, LCLIntf, Win32Proc, uClipboard, uLng;
|
||||
|
||||
var
|
||||
// Supported formats by the source.
|
||||
|
|
@ -944,20 +950,16 @@ var
|
|||
|
||||
Format: TFormatETC;
|
||||
|
||||
NumFiles: Integer;
|
||||
|
||||
i: Integer;
|
||||
|
||||
DropInfo: TDragDropInfo;
|
||||
|
||||
szFilename: array [0..MAX_PATH] of char;
|
||||
FileNames: TStringList;
|
||||
|
||||
InClient: boolean;
|
||||
|
||||
DropPoint: TPoint;
|
||||
|
||||
bWideStrings: boolean;
|
||||
|
||||
DropEffect: TDropEffect;
|
||||
|
||||
begin
|
||||
|
|
@ -1020,45 +1022,30 @@ begin
|
|||
|
||||
begin
|
||||
|
||||
{ Ïîëó÷àåì êîëè÷åñòâî ôàéëîâ è
|
||||
|
||||
ïðî÷èå ñâåäåíèÿ }
|
||||
|
||||
NumFiles := DragQueryFile(Medium.hGlobal, $FFFFFFFF, nil, 0);
|
||||
|
||||
InClient := DragQueryPoint(Medium.hGlobal, @DropPoint);
|
||||
|
||||
if (DropPoint.X = 0) and (DropPoint.Y = 0) then
|
||||
DropPoint := pt;
|
||||
|
||||
bWideStrings := DragQueryWide( Medium.hGlobal );
|
||||
|
||||
|
||||
{ Ñîçäàåì îáúåêò TDragDropInfo }
|
||||
|
||||
DropInfo := TDragDropInfo.Create(DropPoint, InClient, dwEffect);
|
||||
|
||||
|
||||
{ Retrieve file names }
|
||||
|
||||
{ Çàíîñèì âñå ôàéëû â ñïèñîê }
|
||||
FileNames := GetDropFilenames(Medium.hGlobal);
|
||||
|
||||
for i := 0 to NumFiles - 1 do
|
||||
if Assigned(FileNames) then
|
||||
|
||||
begin
|
||||
for i := 0 to FileNames.Count - 1 do
|
||||
|
||||
DragQueryFile(Medium.hGlobal, i,
|
||||
begin
|
||||
|
||||
szFilename,
|
||||
DropInfo.Add(FileNames[i]);
|
||||
|
||||
sizeof(szFilename));
|
||||
end;
|
||||
|
||||
// If Wide strings, then do Wide to UTF-8 transform
|
||||
if( bWideStrings ) then
|
||||
DropInfo.Add( UTF8Encode( szFileName ) )
|
||||
else
|
||||
DropInfo.Add( AnsiToUtf8( szFilename ) );
|
||||
|
||||
end;
|
||||
|
||||
{ Åñëè óêàçàí îáðàáîò÷èê, âûçûâàåì åãî }
|
||||
|
||||
|
|
@ -1107,6 +1094,65 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
class function TFileDropTarget.GetDropFilenames(hDropData: HDROP): TStringList;
|
||||
|
||||
var
|
||||
NumFiles: Integer;
|
||||
i: Integer;
|
||||
wszFilename: PWideChar;
|
||||
FileName: WideString;
|
||||
RequiredSize: Cardinal;
|
||||
|
||||
begin
|
||||
|
||||
Result := nil;
|
||||
|
||||
if hDropData <> 0 then
|
||||
begin
|
||||
|
||||
Result := TStringList.Create;
|
||||
|
||||
try
|
||||
|
||||
NumFiles := DragQueryFileW(hDropData, $FFFFFFFF, nil, 0);
|
||||
|
||||
for i := 0 to NumFiles - 1 do
|
||||
begin
|
||||
RequiredSize := DragQueryFileW(hDropData, i, nil, 0) + 1; // + 1 = terminating zero
|
||||
|
||||
wszFilename := GetMem(RequiredSize * SizeOf(WideChar));
|
||||
if Assigned(wszFilename) then
|
||||
try
|
||||
if DragQueryFileW(hDropData, i, wszFilename, RequiredSize) > 0 then
|
||||
begin
|
||||
FileName := wszFilename;
|
||||
|
||||
// Windows inserts '?' character where Wide->Ansi conversion
|
||||
// of a character was not possible, in which case filename is invalid.
|
||||
// This may happen if a non-Unicode application was the source.
|
||||
if Pos('?', FileName) = 0 then
|
||||
Result.Add(UTF8Encode(FileName))
|
||||
else
|
||||
raise Exception.Create(rsMsgInvalidFilename + ': ' + LineEnding +
|
||||
UTF8Encode(FileName));
|
||||
end;
|
||||
|
||||
finally
|
||||
FreeMem(wszFilename);
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
except
|
||||
FreeAndNil(Result);
|
||||
raise;
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
{ TFileDropSource }
|
||||
|
||||
|
|
|
|||
|
|
@ -1890,11 +1890,10 @@ begin
|
|||
with frmMain do
|
||||
begin
|
||||
if PasteFromClipboard(ClipboardOp, filenamesList) = True then
|
||||
begin
|
||||
try
|
||||
// fill file list with files
|
||||
FileList:= TFileList.Create;
|
||||
FileList.LoadFromFileNames(fileNamesList);
|
||||
FreeAndNil(fileNamesList);
|
||||
|
||||
{ If panel is in Archive of VFS mode - show dialog for the user to confirm. }
|
||||
{ Otherwise just start the operation thread. }
|
||||
|
|
@ -1919,6 +1918,9 @@ begin
|
|||
else
|
||||
FreeAndNil(FileList);
|
||||
end;
|
||||
|
||||
finally
|
||||
FreeAndNil(fileNamesList);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ resourcestring
|
|||
rsMsgTooManyFilesSelected = 'Too many files selected.';
|
||||
rsMsgInvalidSelection = 'Invalid selection.';
|
||||
rsMsgNotImplemented = 'Not implemented.';
|
||||
rsMsgInvalidFilename = 'Invalid filename';
|
||||
// for context menu
|
||||
rsMnuActions = 'Actions';
|
||||
rsMnuMount = 'Mount';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue