2019-04-04 10:26:44 +02:00
|
|
|
unit uCEFOLEDragAndDrop;
|
2017-07-18 17:50:28 +02:00
|
|
|
|
2018-05-12 14:50:54 +02:00
|
|
|
{$IFDEF FPC}
|
|
|
|
{$MODE OBJFPC}{$H+}
|
|
|
|
{$ENDIF}
|
|
|
|
|
2017-07-18 17:50:28 +02:00
|
|
|
{$I cef.inc}
|
|
|
|
|
2021-01-05 12:44:41 +02:00
|
|
|
{$IFNDEF FPC}{$IFNDEF DELPHI12_UP}
|
|
|
|
// Workaround for "Internal error" in old Delphi versions caused by uint64 handling
|
|
|
|
{$R-}
|
|
|
|
{$ENDIF}{$ENDIF}
|
|
|
|
|
2017-07-18 17:50:28 +02:00
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
{$IFDEF DELPHI16_UP}
|
2024-03-23 19:21:32 +02:00
|
|
|
{$IFDEF MSWINDOWS}WinApi.Windows, WinApi.ShlObj, WinApi.ActiveX,{$ENDIF} System.Classes, System.Math,
|
2017-07-18 17:50:28 +02:00
|
|
|
{$ELSE}
|
2024-03-23 19:21:32 +02:00
|
|
|
{$IFDEF MSWINDOWS}Windows, ShlObj, ActiveX,{$ENDIF} Classes, Math,
|
2017-07-18 17:50:28 +02:00
|
|
|
{$ENDIF}
|
2024-03-23 19:21:32 +02:00
|
|
|
uCEFTypes;
|
2017-07-18 17:50:28 +02:00
|
|
|
|
|
|
|
const
|
|
|
|
CUSTOM_ARRAY_LENGTH = 25;
|
|
|
|
|
|
|
|
type
|
|
|
|
TOLEMediumArray = array [0..pred(CUSTOM_ARRAY_LENGTH)] of TStgMedium;
|
|
|
|
TOLEFormatArray = array [0..pred(CUSTOM_ARRAY_LENGTH)] of TFormatEtc;
|
|
|
|
|
|
|
|
TOLEDragAndDropMgr = class
|
|
|
|
protected
|
|
|
|
function GetStorageForBytes(var aMedium : TStgMedium; const aData : pointer; aLength : NativeUInt) : boolean;
|
|
|
|
function GetStorageForString(var aMedium : TStgMedium; const aData : WideString) : boolean; overload;
|
|
|
|
function GetStorageForString(var aMedium : TStgMedium; const aData : AnsiString) : boolean; overload;
|
|
|
|
function GetStorageForFileDescriptor(var aMedium : TStgMedium; const aFileName : string) : boolean;
|
|
|
|
|
|
|
|
public
|
|
|
|
function DragEnter(const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; virtual;
|
|
|
|
function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; virtual;
|
|
|
|
function DragLeave: HRESULT; virtual;
|
|
|
|
function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; virtual;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TOLEEnumFormatEtc = class(TInterfacedObject, IEnumFormatEtc)
|
|
|
|
protected
|
|
|
|
FIndex : integer;
|
|
|
|
FNumFormats : integer;
|
|
|
|
FFormatArray : TOLEFormatArray;
|
|
|
|
|
|
|
|
procedure CopyFromFormatArray(const aSrcFormatArray : TOLEFormatArray);
|
|
|
|
procedure CopyFormatEtc(var aDstFormatEtc : TFormatEtc; const aSrcFormatEtc : TFormatEtc);
|
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create; overload;
|
|
|
|
constructor Create(const aFormatArray : TOLEFormatArray; aNumFormats : integer; aIndex : integer = 0); overload;
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
// IEnumFormatEtc
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
|
|
|
function Next(Celt: LongInt; out Rgelt; pCeltFetched: pLongInt): HRESULT; stdcall;
|
2017-07-18 17:50:28 +02:00
|
|
|
function Skip(Celt: Longint): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
function Next(Celt: ULONG; out Rgelt: FormatEtc; pceltFetched: PULONG = nil): HRESULT; stdcall;
|
|
|
|
function Skip(Celt: ULONG): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
function Reset: HRESULT; stdcall;
|
|
|
|
function Clone(out Enum: IEnumFormatEtc): HRESULT; stdcall;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TOLEDropSource = class(TInterfacedObject, IDropSource)
|
|
|
|
public
|
|
|
|
// IDropSource
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
function QueryContinueDrag(fEscapePressed: bool; grfKeyState: LongInt): HRESULT; stdcall;
|
|
|
|
function GiveFeedback(dwEffect: LongInt): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: DWORD): HRESULT; stdcall;
|
|
|
|
function GiveFeedback(dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TOLEDataObject = class(TInterfacedObject, IDataObject)
|
|
|
|
protected
|
|
|
|
FNumFormats : integer;
|
|
|
|
FFormatArray : TOLEFormatArray;
|
|
|
|
FMediumArray : TOLEMediumArray;
|
|
|
|
FAsync : boolean;
|
|
|
|
FInOperation : boolean;
|
|
|
|
|
|
|
|
function LookupFormatEtc(const aFormatEtc : TFormatEtc) : integer;
|
|
|
|
function DupGlobalMem(hMem : HGLOBAL) : HGLOBAL;
|
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(const aFormatArray : TOLEFormatArray; const aMediumArray : TOLEMediumArray; aNumFormats : integer); reintroduce;
|
|
|
|
|
|
|
|
// IDataObject
|
|
|
|
function GetData(const FormatEtcIn: TFormatEtc; out Medium: TStgMedium):HRESULT; stdcall;
|
|
|
|
function GetDataHere(const FormatEtc: TFormatEtc; out Medium: TStgMedium):HRESULT; stdcall;
|
|
|
|
function QueryGetData(const FormatEtc: TFormatEtc): HRESULT; stdcall;
|
|
|
|
function GetCanonicalFormatEtc(const FormatEtc: TFormatEtc; out FormatEtcout: TFormatEtc): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
function SetData(const FormatEtc: TFormatEtc; var Medium: TStgMedium; fRelease: Bool): HRESULT; stdcall;
|
|
|
|
function EnumFormatEtc(dwDirection: LongInt; out aEnumFormatEtc: IEnumFormatEtc): HRESULT; stdcall;
|
|
|
|
function dAdvise(const FormatEtc: TFormatEtc; advf: LongInt; const advsink: IAdviseSink; out dwConnection: LongInt): HRESULT; stdcall;
|
|
|
|
function dUnadvise(dwConnection: LongInt): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
2020-06-29 11:07:22 +02:00
|
|
|
function SetData(const pformatetc: FORMATETC; {$IFDEF FPC_VER_320}var{$ELSE}const{$ENDIF} medium: STGMEDIUM; FRelease: BOOL): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
function EnumFormatEtc(dwDirection: DWORD; out aEnumFormatEtc: IENUMFORMATETC): HRESULT; stdcall;
|
|
|
|
function DAdvise(const formatetc: FORMATETC; advf: DWORD; const AdvSink: IAdviseSink; out dwConnection: DWORD): HRESULT; stdcall;
|
|
|
|
function DUnadvise(dwconnection: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
function EnumdAdvise(out EnumAdvise: IEnumStatData): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TOLEDropTarget = class(TInterfacedObject, IDropTarget)
|
|
|
|
protected
|
|
|
|
FManager : TOLEDragAndDropMgr;
|
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(const aManager : TOLEDragAndDropMgr); reintroduce;
|
|
|
|
|
|
|
|
// IDropTarget
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
function DragEnter(const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
|
|
|
function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
|
|
|
function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
function DragEnter(const dataObj: IDataObject; grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
function DragOver(grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
function Drop(const dataObj: IDataObject; grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
|
|
|
function DragLeave: HRESULT; stdcall;
|
|
|
|
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
// *****************************************************
|
|
|
|
// *************** TOLEDragAndDropMgr ******************
|
|
|
|
// *****************************************************
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.GetStorageForBytes(var aMedium : TStgMedium; const aData : pointer; aLength : NativeUInt) : boolean;
|
|
|
|
var
|
|
|
|
TempHandle : HGLOBAL;
|
|
|
|
TempPointer : pointer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
if (aData <> nil) then
|
|
|
|
begin
|
|
|
|
TempHandle := GlobalAlloc(GHND, aLength);
|
|
|
|
|
|
|
|
if (TempHandle <> 0) then
|
|
|
|
begin
|
|
|
|
TempPointer := GlobalLock(TempHandle);
|
|
|
|
|
|
|
|
if (TempPointer <> nil) then
|
|
|
|
begin
|
|
|
|
Move(aData^, TempPointer^, aLength);
|
|
|
|
|
|
|
|
aMedium.hGlobal := TempHandle;
|
|
|
|
aMedium.tymed := TYMED_HGLOBAL;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
aMedium.unkForRelease := nil;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
aMedium.PUnkForRelease := nil;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
|
|
|
|
GlobalUnlock(TempHandle);
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
GlobalFree(TempHandle);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.GetStorageForString(var aMedium : TStgMedium; const aData : WideString) : boolean;
|
|
|
|
var
|
|
|
|
TempPointer : pointer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
if (length(aData) > 0) then
|
|
|
|
begin
|
|
|
|
TempPointer := @aData[1];
|
|
|
|
Result := GetStorageForBytes(aMedium, TempPointer, length(aData) * SizeOf(WideChar));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.GetStorageForString(var aMedium : TStgMedium; const aData : AnsiString) : boolean;
|
|
|
|
var
|
|
|
|
TempPointer : pointer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
if (length(aData) > 0) then
|
|
|
|
begin
|
|
|
|
TempPointer := @aData[1];
|
|
|
|
Result := GetStorageForBytes(aMedium, TempPointer, length(aData) * SizeOf(AnsiChar));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.GetStorageForFileDescriptor(var aMedium : TStgMedium; const aFileName : string) : boolean;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFDEF FPC}
|
|
|
|
const
|
|
|
|
FD_LINKUI = $8000;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
var
|
|
|
|
TempHandle : HGLOBAL;
|
|
|
|
TempDescriptor : TFileGroupDescriptor;
|
|
|
|
TempPointer : pointer;
|
|
|
|
i, j : integer;
|
|
|
|
TempString : string;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
if (length(aFileName) > 0) then
|
|
|
|
begin
|
|
|
|
TempHandle := GlobalAlloc(GHND, sizeof(TFileGroupDescriptor));
|
|
|
|
|
|
|
|
if (TempHandle <> 0) then
|
|
|
|
begin
|
|
|
|
TempPointer := GlobalLock(TempHandle);
|
|
|
|
|
|
|
|
if (TempPointer <> nil) then
|
|
|
|
begin
|
|
|
|
TempDescriptor := TFileGroupDescriptor(TempPointer^);
|
|
|
|
TempDescriptor.cItems := 1;
|
|
|
|
TempDescriptor.fgd[0].dwFlags := FD_LINKUI;
|
|
|
|
|
|
|
|
TempString := aFileName + #0;
|
|
|
|
|
|
|
|
i := 1;
|
|
|
|
j := length(TempString);
|
|
|
|
|
|
|
|
while (i <= j) do
|
|
|
|
begin
|
|
|
|
TempDescriptor.fgd[0].cFileName[pred(i)] := TempString[i];
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
|
|
|
|
aMedium.tymed := TYMED_HGLOBAL;
|
|
|
|
aMedium.hGlobal := TempHandle;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
aMedium.unkForRelease := nil;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
aMedium.PUnkForRelease := nil;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
|
|
|
|
GlobalUnlock(TempHandle);
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
GlobalFree(TempHandle);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.DragEnter(const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT;
|
|
|
|
begin
|
|
|
|
Result := S_OK;
|
|
|
|
dwEffect := DROPEFFECT_NONE;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT;
|
|
|
|
begin
|
|
|
|
Result := S_OK;
|
|
|
|
dwEffect := DROPEFFECT_NONE;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.DragLeave: HRESULT;
|
|
|
|
begin
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDragAndDropMgr.Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT;
|
|
|
|
begin
|
|
|
|
Result := S_OK;
|
|
|
|
dwEffect := DROPEFFECT_NONE;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************
|
|
|
|
// **************** TOLEEnumFormatEtc ******************
|
|
|
|
// *****************************************************
|
|
|
|
|
|
|
|
constructor TOLEEnumFormatEtc.Create;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
|
|
|
|
FIndex := 0;
|
|
|
|
FNumFormats := 0;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TOLEEnumFormatEtc.Create(const aFormatArray : TOLEFormatArray; aNumFormats, aIndex : integer);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
|
|
|
|
FIndex := aIndex;
|
|
|
|
FNumFormats := min(aNumFormats, CUSTOM_ARRAY_LENGTH);
|
|
|
|
|
|
|
|
CopyFromFormatArray(aFormatArray);
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TOLEEnumFormatEtc.Destroy;
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
|
|
|
|
while (i < FNumFormats) do
|
|
|
|
begin
|
|
|
|
if (FFormatArray[i].ptd <> nil) then CoTaskMemFree(FFormatArray[i].ptd);
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TOLEEnumFormatEtc.CopyFromFormatArray(const aSrcFormatArray : TOLEFormatArray);
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
|
|
|
|
while (i < FNumFormats) do
|
|
|
|
begin
|
|
|
|
CopyFormatEtc(FFormatArray[i], aSrcFormatArray[i]);
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TOLEEnumFormatEtc.CopyFormatEtc(var aDstFormatEtc : TFormatEtc; const aSrcFormatEtc : TFormatEtc);
|
2019-11-10 19:23:39 +02:00
|
|
|
var
|
|
|
|
Size: Integer;
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
aDstFormatEtc.cfFormat := aSrcFormatEtc.cfFormat;
|
|
|
|
aDstFormatEtc.dwAspect := aSrcFormatEtc.dwAspect;
|
|
|
|
aDstFormatEtc.lindex := aSrcFormatEtc.lindex;
|
|
|
|
aDstFormatEtc.tymed := aSrcFormatEtc.tymed;
|
|
|
|
|
|
|
|
if (aSrcFormatEtc.ptd = nil) then
|
|
|
|
aDstFormatEtc.ptd := nil
|
|
|
|
else
|
|
|
|
begin
|
2019-11-10 19:23:39 +02:00
|
|
|
Size := Max(aSrcFormatEtc.ptd^.tdSize, SizeOf(DVTARGETDEVICE));
|
|
|
|
aDstFormatEtc.ptd := CoTaskMemAlloc(Size);
|
|
|
|
Move(aSrcFormatEtc.ptd^, aDstFormatEtc.ptd^, Size);
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEEnumFormatEtc.Next
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(Celt: LongInt; out Rgelt; pCeltFetched: pLongInt): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(Celt: ULONG; out Rgelt: FormatEtc; pceltFetched: PULONG): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
var
|
|
|
|
i : integer;
|
2019-11-10 19:23:39 +02:00
|
|
|
TempArray : ^TOLEFormatArray;
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
i := 0;
|
2019-11-10 19:23:39 +02:00
|
|
|
TempArray := @Rgelt;
|
2017-07-18 17:50:28 +02:00
|
|
|
|
|
|
|
while (i < Celt) and (FIndex < FNumFormats) do
|
|
|
|
begin
|
2019-11-10 19:23:39 +02:00
|
|
|
CopyFormatEtc(TempArray^[i], FFormatArray[FIndex]);
|
2017-07-18 17:50:28 +02:00
|
|
|
inc(i);
|
|
|
|
inc(FIndex);
|
|
|
|
end;
|
|
|
|
|
|
|
|
if (pCeltFetched <> nil) then pCeltFetched^ := i;
|
|
|
|
|
|
|
|
if (i = Celt) then
|
|
|
|
Result := S_OK
|
|
|
|
else
|
|
|
|
Result := S_FALSE;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEEnumFormatEtc.Skip
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(Celt: Longint): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(Celt: ULONG): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
FIndex := FIndex + Celt;
|
|
|
|
|
|
|
|
if (FIndex <= FNumFormats) then
|
|
|
|
Result := S_OK
|
|
|
|
else
|
|
|
|
Result := S_FALSE;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEEnumFormatEtc.Reset: HRESULT; stdcall;
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
FIndex := 0;
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEEnumFormatEtc.Clone(out Enum: IEnumFormatEtc): HRESULT; stdcall;
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
Enum := TOLEEnumFormatEtc.Create(FFormatArray, FNumFormats, FIndex);
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************
|
|
|
|
// ****************** TOLEDropTarget *******************
|
|
|
|
// *****************************************************
|
|
|
|
|
|
|
|
constructor TOLEDropTarget.Create(const aManager : TOLEDragAndDropMgr);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
|
|
|
|
FManager := aManager;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDropTarget.DragEnter
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(const dataObj: IDataObject; grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
2019-11-10 19:23:39 +02:00
|
|
|
Result := FManager.DragEnter(DataObj, grfKeyState, pt, Longint(dwEffect));
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDropTarget.DragOver
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
2019-11-10 19:23:39 +02:00
|
|
|
Result := FManager.DragOver(grfKeyState, pt, Longint(dwEffect));
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDropTarget.DragLeave: HRESULT; stdcall;
|
|
|
|
begin
|
|
|
|
Result := FManager.DragLeave;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDropTarget.Drop
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(const dataObj: IDataObject; grfKeyState: DWORD; pt: TPoint; var dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
2019-11-10 19:23:39 +02:00
|
|
|
Result := FManager.Drop(dataObj, grfKeyState, pt, Longint(dwEffect));
|
2017-07-18 17:50:28 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************
|
|
|
|
// ****************** TOLEDropSource *******************
|
|
|
|
// *****************************************************
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDropSource.QueryContinueDrag
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(fEscapePressed: bool; grfKeyState: LongInt): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(fEscapePressed: BOOL; grfKeyState: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
if fEscapePressed then
|
|
|
|
Result := DRAGDROP_S_CANCEL
|
|
|
|
else
|
|
|
|
if ((grfKeyState and MK_LBUTTON) = 0) then
|
|
|
|
Result := DRAGDROP_S_DROP
|
|
|
|
else
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDropSource.GiveFeedback
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(dwEffect: LongInt): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(dwEffect: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
Result := DRAGDROP_S_USEDEFAULTCURSORS;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************
|
|
|
|
// ****************** TOLEDataObject *******************
|
|
|
|
// *****************************************************
|
|
|
|
|
|
|
|
constructor TOLEDataObject.Create(const aFormatArray : TOLEFormatArray;
|
|
|
|
const aMediumArray : TOLEMediumArray;
|
|
|
|
aNumFormats : integer);
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
|
|
|
|
FAsync := False;
|
|
|
|
FInOperation := False;
|
|
|
|
FNumFormats := min(aNumFormats, CUSTOM_ARRAY_LENGTH);
|
|
|
|
|
|
|
|
i := 0;
|
|
|
|
|
|
|
|
while (i < FNumFormats) do
|
|
|
|
begin
|
|
|
|
FFormatArray[i].cfFormat := aFormatArray[i].cfFormat;
|
|
|
|
FFormatArray[i].ptd := aFormatArray[i].ptd;
|
|
|
|
FFormatArray[i].dwAspect := aFormatArray[i].dwAspect;
|
|
|
|
FFormatArray[i].lindex := aFormatArray[i].lindex;
|
|
|
|
FFormatArray[i].tymed := aFormatArray[i].tymed;
|
|
|
|
|
|
|
|
FMediumArray[i] := aMediumArray[i];
|
|
|
|
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.LookupFormatEtc(const aFormatEtc : TFormatEtc) : integer;
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
Result := -1;
|
|
|
|
i := 0;
|
|
|
|
|
|
|
|
while (i < FNumFormats) do
|
|
|
|
if ((FFormatArray[i].tymed and aFormatEtc.tymed) <> 0) and
|
|
|
|
(FFormatArray[i].cfFormat = aFormatEtc.cfFormat) and
|
|
|
|
(FFormatArray[i].dwAspect = aFormatEtc.dwAspect) then
|
|
|
|
begin
|
|
|
|
Result := i;
|
|
|
|
exit;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.DupGlobalMem(hMem : HGLOBAL) : HGLOBAL;
|
|
|
|
var
|
|
|
|
TempLen : cardinal;
|
|
|
|
TempHandle : HGLOBAL;
|
|
|
|
TempSrc : Pointer;
|
|
|
|
TempDst : Pointer;
|
|
|
|
begin
|
|
|
|
Result := 0;
|
|
|
|
TempSrc := GlobalLock(hMem);
|
|
|
|
|
|
|
|
if (TempSrc <> nil) then
|
|
|
|
begin
|
|
|
|
TempLen := GlobalSize(hMem);
|
|
|
|
TempHandle := GlobalAlloc(GHND, TempLen);
|
|
|
|
|
|
|
|
if (TempHandle <> 0) then
|
|
|
|
begin
|
|
|
|
TempDst := GlobalLock(TempHandle);
|
|
|
|
|
|
|
|
if (TempDst <> nil) then
|
|
|
|
begin
|
|
|
|
Move(TempSrc^, TempDst^, TempLen);
|
|
|
|
Result := TempHandle;
|
|
|
|
GlobalUnlock(TempHandle);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
GlobalFree(TempHandle);
|
|
|
|
end;
|
|
|
|
|
|
|
|
GlobalUnlock(hMem);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.GetData(const FormatEtcIn: TFormatEtc; out Medium: TStgMedium):HRESULT; stdcall;
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
i := LookupFormatEtc(FormatEtcIn);
|
|
|
|
|
|
|
|
if (i < 0) or ((FFormatArray[i].tymed and TYMED_HGLOBAL) = 0) then
|
|
|
|
begin
|
|
|
|
Medium.tymed := TYMED_NULL;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
Medium.unkForRelease := nil;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
Medium.PUnkForRelease := nil;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
Medium.hGlobal := 0;
|
|
|
|
Result := DV_E_FORMATETC;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Medium.tymed := FFormatArray[i].tymed;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$IFNDEF FPC}
|
2017-07-18 17:50:28 +02:00
|
|
|
Medium.unkForRelease := nil;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ELSE}
|
|
|
|
Medium.PUnkForRelease := nil;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
Medium.hGlobal := DupGlobalMem(FMediumArray[i].hGlobal);
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.GetDataHere(const FormatEtc: TFormatEtc; out Medium: TStgMedium):HRESULT; stdcall;
|
|
|
|
begin
|
|
|
|
Result := DV_E_FORMATETC;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.QueryGetData(const FormatEtc: TFormatEtc): HRESULT; stdcall;
|
|
|
|
begin
|
|
|
|
if (LookupFormatEtc(FormatEtc) < 0) then
|
|
|
|
Result := DV_E_FORMATETC
|
|
|
|
else
|
|
|
|
Result := S_OK;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.GetCanonicalFormatEtc(const FormatEtc: TFormatEtc; out FormatEtcout: TFormatEtc): HRESULT; stdcall;
|
|
|
|
begin
|
|
|
|
FormatEtcout.cfFormat := 0;
|
|
|
|
FormatEtcout.dwAspect := DVASPECT_CONTENT;
|
|
|
|
FormatEtcout.lindex := -1;
|
|
|
|
FormatEtcout.tymed := TYMED_NULL;
|
|
|
|
FormatEtcout.ptd := nil;
|
|
|
|
|
|
|
|
Result := E_NOTIMPL;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDataObject.SetData
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(const FormatEtc: TFormatEtc; var Medium: TStgMedium; fRelease: Bool): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
2020-06-29 11:07:22 +02:00
|
|
|
(const pformatetc: FORMATETC; {$IFDEF FPC_VER_320}var{$ELSE}const{$ENDIF} medium: STGMEDIUM; FRelease: BOOL): HRESULT; stdcall;
|
2019-11-10 19:23:39 +02:00
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
Result := E_NOTIMPL;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDataObject.EnumFormatEtc
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(dwDirection: LongInt; out aEnumFormatEtc: IEnumFormatEtc): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(dwDirection: DWORD; out aEnumFormatEtc: IENUMFORMATETC): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
if (dwDirection = DATADIR_GET) then
|
|
|
|
begin
|
|
|
|
aEnumFormatEtc := TOLEEnumFormatEtc.Create(FFormatArray, FNumFormats);
|
|
|
|
Result := S_OK;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
aEnumFormatEtc := nil;
|
|
|
|
|
|
|
|
if (dwDirection = DATADIR_SET) then
|
|
|
|
Result := E_NOTIMPL
|
|
|
|
else
|
|
|
|
Result := E_INVALIDARG;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDataObject.dAdvise
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(const FormatEtc: TFormatEtc; advf: LongInt; const advsink: IAdviseSink; out dwConnection: LongInt): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(const formatetc: FORMATETC; advf: DWORD; const AdvSink: IAdviseSink; out dwConnection: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
Result := OLE_E_ADVISENOTSUPPORTED;
|
|
|
|
end;
|
|
|
|
|
2019-11-10 19:23:39 +02:00
|
|
|
function TOLEDataObject.dUnadvise
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
(dwConnection: LongInt): HRESULT; stdcall;
|
|
|
|
{$ELSE}
|
|
|
|
(dwconnection: DWORD): HRESULT; stdcall;
|
|
|
|
{$ENDIF}
|
2017-07-18 17:50:28 +02:00
|
|
|
begin
|
|
|
|
Result := OLE_E_ADVISENOTSUPPORTED;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TOLEDataObject.EnumdAdvise(out EnumAdvise: IEnumStatData): HRESULT; stdcall;
|
|
|
|
begin
|
|
|
|
Result := OLE_E_ADVISENOTSUPPORTED;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|