You've already forked lazarus-ccr
Removed direct dependency of ActiveX and OleUtils
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@119 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -105,6 +105,9 @@ interface
|
|||||||
uses
|
uses
|
||||||
{$ifdef UseExternalDragManager}
|
{$ifdef UseExternalDragManager}
|
||||||
virtualdragmanager,
|
virtualdragmanager,
|
||||||
|
{$else}
|
||||||
|
ActiveX,
|
||||||
|
OleUtils,
|
||||||
{$endif}
|
{$endif}
|
||||||
Windows, DelphiCompat, vtlogger, LCLType, LResources, LCLIntf, LMessages, Types,
|
Windows, DelphiCompat, vtlogger, LCLType, LResources, LCLIntf, LMessages, Types,
|
||||||
SysUtils, Classes, Graphics, Controls, Forms, ImgList, StdCtrls, Menus, Printers,
|
SysUtils, Classes, Graphics, Controls, Forms, ImgList, StdCtrls, Menus, Printers,
|
||||||
@ -123,12 +126,7 @@ uses
|
|||||||
{$endif TntSupport}
|
{$endif TntSupport}
|
||||||
{$ifdef EnableAccessible}
|
{$ifdef EnableAccessible}
|
||||||
, oleacc // for MSAA IAccessible support
|
, oleacc // for MSAA IAccessible support
|
||||||
{$endif}
|
{$endif};
|
||||||
{$ifdef EnableOLE}
|
|
||||||
, ActiveX,
|
|
||||||
OleUtils
|
|
||||||
{$endif}
|
|
||||||
;
|
|
||||||
|
|
||||||
const
|
const
|
||||||
{$I lclconstants.inc}
|
{$I lclconstants.inc}
|
||||||
@ -689,7 +687,7 @@ type
|
|||||||
Medium: TStgMedium;
|
Medium: TStgMedium;
|
||||||
end;
|
end;
|
||||||
TInternalStgMediumArray = array of TInternalStgMedium;
|
TInternalStgMediumArray = array of TInternalStgMedium;
|
||||||
{$endif}
|
|
||||||
TEnumFormatEtc = class(TInterfacedObject, IEnumFormatEtc)
|
TEnumFormatEtc = class(TInterfacedObject, IEnumFormatEtc)
|
||||||
private
|
private
|
||||||
FTree: TBaseVirtualTree;
|
FTree: TBaseVirtualTree;
|
||||||
@ -704,8 +702,6 @@ type
|
|||||||
function Skip(celt: LongWord): HResult; stdcall;
|
function Skip(celt: LongWord): HResult; stdcall;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{$ifndef UseExternalDragManager}
|
|
||||||
// ----- OLE drag'n drop handling
|
// ----- OLE drag'n drop handling
|
||||||
|
|
||||||
{ 01.05.2006 Jim - Problem with BDS2006 C++ compiler and ambiguous defines}
|
{ 01.05.2006 Jim - Problem with BDS2006 C++ compiler and ambiguous defines}
|
||||||
@ -886,8 +882,6 @@ type
|
|||||||
disSystemSupport // Running on Windows 2000 or higher. System supports drag images natively.
|
disSystemSupport // Running on Windows 2000 or higher. System supports drag images natively.
|
||||||
);
|
);
|
||||||
|
|
||||||
{$ifdef EnableOLE}
|
|
||||||
|
|
||||||
// Class to manage header and tree drag image during a drag'n drop operation.
|
// Class to manage header and tree drag image during a drag'n drop operation.
|
||||||
TVTDragImage = class
|
TVTDragImage = class
|
||||||
private
|
private
|
||||||
@ -930,7 +924,7 @@ type
|
|||||||
property Transparency: TVTTransparency read FTransparency write FTransparency default 128;
|
property Transparency: TVTTransparency read FTransparency write FTransparency default 128;
|
||||||
property Visible: Boolean read GetVisible;
|
property Visible: Boolean read GetVisible;
|
||||||
end;
|
end;
|
||||||
{$endif}
|
|
||||||
// tree columns implementation
|
// tree columns implementation
|
||||||
TVirtualTreeColumns = class;
|
TVirtualTreeColumns = class;
|
||||||
TVTHeader = class;
|
TVTHeader = class;
|
||||||
@ -5738,6 +5732,7 @@ end;
|
|||||||
|
|
||||||
{$endif UseLocalMemoryManager}
|
{$endif UseLocalMemoryManager}
|
||||||
|
|
||||||
|
{$ifndef UseExternalDragManager}
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// OLE drag and drop support classes
|
// OLE drag and drop support classes
|
||||||
@ -5745,7 +5740,7 @@ end;
|
|||||||
// of DD'ing various kinds of virtual data and works also between applications.
|
// of DD'ing various kinds of virtual data and works also between applications.
|
||||||
|
|
||||||
//----------------- TEnumFormatEtc -------------------------------------------------------------------------------------
|
//----------------- TEnumFormatEtc -------------------------------------------------------------------------------------
|
||||||
{$ifdef EnableOLE}
|
|
||||||
constructor TEnumFormatEtc.Create(Tree: TBaseVirtualTree; AFormatEtcArray: TFormatEtcArray);
|
constructor TEnumFormatEtc.Create(Tree: TBaseVirtualTree; AFormatEtcArray: TFormatEtcArray);
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -5827,7 +5822,7 @@ begin
|
|||||||
Result := S_FALSE;
|
Result := S_FALSE;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$ifndef UseExternalDragManager}
|
|
||||||
|
|
||||||
//----------------- TVTDataObject --------------------------------------------------------------------------------------
|
//----------------- TVTDataObject --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -6457,7 +6452,7 @@ begin
|
|||||||
Result := S_OK;
|
Result := S_OK;
|
||||||
end;
|
end;
|
||||||
{$endif} //UseExternalDragManager
|
{$endif} //UseExternalDragManager
|
||||||
{$endif} //EnableOLE
|
|
||||||
//----------------- TVirtualTreeHintWindow -----------------------------------------------------------------------------
|
//----------------- TVirtualTreeHintWindow -----------------------------------------------------------------------------
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -18801,7 +18796,7 @@ begin
|
|||||||
DragEffect := DROPEFFECT_NONE;
|
DragEffect := DROPEFFECT_NONE;
|
||||||
AllowedEffects := GetDragOperations;
|
AllowedEffects := GetDragOperations;
|
||||||
try
|
try
|
||||||
VirtualTrees.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
|
virtualdragmanager.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
|
||||||
DragManager.ForceDragLeave;
|
DragManager.ForceDragLeave;
|
||||||
finally
|
finally
|
||||||
GetCursorPos(P);
|
GetCursorPos(P);
|
||||||
@ -22996,20 +22991,23 @@ function TBaseVirtualTree.RenderOLEData(const FormatEtcIn: TFormatEtc; out Mediu
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
//--------------- end local function ----------------------------------------
|
//--------------- end local function ----------------------------------------
|
||||||
|
{$ifndef UseExternalDragManager}
|
||||||
var
|
var
|
||||||
Data: PCardinal;
|
Data: PCardinal;
|
||||||
ResPointer: Pointer;
|
ResPointer: Pointer;
|
||||||
ResSize: Integer;
|
ResSize: Integer;
|
||||||
OLEStream: IStream;
|
OLEStream: IStream;
|
||||||
VCLStream: TStream;
|
VCLStream: TStream;
|
||||||
|
{$endif}
|
||||||
begin
|
begin
|
||||||
FillChar(Medium, SizeOf(Medium), 0);
|
FillChar(Medium, SizeOf(Medium), 0);
|
||||||
{$ifdef NeedWindows}
|
|
||||||
// We can render the native clipboard format in two different storage media.
|
// We can render the native clipboard format in two different storage media.
|
||||||
if (FormatEtcIn.cfFormat = CF_VIRTUALTREE) and (FormatEtcIn.tymed and (TYMED_HGLOBAL or TYMED_ISTREAM) <> 0) then
|
if (FormatEtcIn.cfFormat = CF_VIRTUALTREE) and (FormatEtcIn.tymed and (TYMED_HGLOBAL or TYMED_ISTREAM) <> 0) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef UseExternalDragManager}
|
||||||
|
//Separated function to help isolate OLE code
|
||||||
|
virtualdragmanager.RenderOLEData(Self,FormatEtcIn,Medium,ForClipboard);
|
||||||
|
{$else}
|
||||||
VCLStream := nil;
|
VCLStream := nil;
|
||||||
try
|
try
|
||||||
Medium.PunkForRelease := nil;
|
Medium.PunkForRelease := nil;
|
||||||
@ -23058,10 +23056,10 @@ begin
|
|||||||
// the OLEStream which exists independently.
|
// the OLEStream which exists independently.
|
||||||
VCLStream.Free;
|
VCLStream.Free;
|
||||||
end;
|
end;
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else // Ask application descendants to render self defined formats.
|
else // Ask application descendants to render self defined formats.
|
||||||
Result := DoRenderOLEData(FormatEtcIn, Medium, ForClipboard);
|
Result := DoRenderOLEData(FormatEtcIn, Medium, ForClipboard);
|
||||||
{$endif}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
@ -28446,7 +28444,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
{$ifndef UseExternalDragManager}
|
||||||
type
|
type
|
||||||
// needed to handle OLE global memory objects
|
// needed to handle OLE global memory objects
|
||||||
TOLEMemoryStream = class(TCustomMemoryStream)
|
TOLEMemoryStream = class(TCustomMemoryStream)
|
||||||
@ -28466,6 +28464,8 @@ begin
|
|||||||
{$endif COMPILER_5_UP}
|
{$endif COMPILER_5_UP}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$endif}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
function TBaseVirtualTree.ProcessOLEData(Source: TBaseVirtualTree; DataObject: IDataObject; TargetNode: PVirtualNode;
|
function TBaseVirtualTree.ProcessOLEData(Source: TBaseVirtualTree; DataObject: IDataObject; TargetNode: PVirtualNode;
|
||||||
@ -28483,7 +28483,9 @@ function TBaseVirtualTree.ProcessOLEData(Source: TBaseVirtualTree; DataObject: I
|
|||||||
var
|
var
|
||||||
Medium: TStgMedium;
|
Medium: TStgMedium;
|
||||||
Stream: TStream;
|
Stream: TStream;
|
||||||
|
{$ifndef UseExternalDragManager}
|
||||||
Data: Pointer;
|
Data: Pointer;
|
||||||
|
{$endif}
|
||||||
Node: PVirtualNode;
|
Node: PVirtualNode;
|
||||||
Nodes: TNodeArray;
|
Nodes: TNodeArray;
|
||||||
I: Integer;
|
I: Integer;
|
||||||
@ -28491,7 +28493,6 @@ var
|
|||||||
ChangeReason: TChangeReason;
|
ChangeReason: TChangeReason;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
{$ifdef NeedWindows}
|
|
||||||
Nodes := nil;
|
Nodes := nil;
|
||||||
// Check the data format available by the data object.
|
// Check the data format available by the data object.
|
||||||
with StandardOLEFormat do
|
with StandardOLEFormat do
|
||||||
@ -28553,6 +28554,9 @@ begin
|
|||||||
TYMED_ISTREAM, // IStream interface
|
TYMED_ISTREAM, // IStream interface
|
||||||
TYMED_HGLOBAL: // global memory block
|
TYMED_HGLOBAL: // global memory block
|
||||||
begin
|
begin
|
||||||
|
{$ifdef UseExternalDragManager}
|
||||||
|
Stream:=GetStreamFromMedium(Medium);
|
||||||
|
{$else}
|
||||||
Stream := nil;
|
Stream := nil;
|
||||||
if Medium.tymed = TYMED_ISTREAM then
|
if Medium.tymed = TYMED_ISTREAM then
|
||||||
Stream := TOLEStream.Create(IUnknown(Medium.Pstm) as IStream)
|
Stream := TOLEStream.Create(IUnknown(Medium.Pstm) as IStream)
|
||||||
@ -28568,7 +28572,7 @@ begin
|
|||||||
TOLEMemoryStream(Stream).SetPointer(Data, I);
|
TOLEMemoryStream(Stream).SetPointer(Data, I);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$endif}
|
||||||
if Assigned(Stream) then
|
if Assigned(Stream) then
|
||||||
try
|
try
|
||||||
while Stream.Position < Stream.Size do
|
while Stream.Position < Stream.Size do
|
||||||
@ -28593,8 +28597,12 @@ begin
|
|||||||
Result := True;
|
Result := True;
|
||||||
finally
|
finally
|
||||||
Stream.Free;
|
Stream.Free;
|
||||||
|
{$ifdef UseExternalDragManager}
|
||||||
|
UnlockMediumData(Medium);
|
||||||
|
{$else}
|
||||||
if Medium.tymed = TYMED_HGLOBAL then
|
if Medium.tymed = TYMED_HGLOBAL then
|
||||||
GlobalUnlock(Medium.hGlobal);
|
GlobalUnlock(Medium.hGlobal);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -28605,7 +28613,6 @@ begin
|
|||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$endif}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -254,6 +254,7 @@ end;
|
|||||||
|
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
{$ifndef UseExternalDragManager}
|
||||||
function RegisterDragDrop(hwnd:HWND; pDropTarget:IDropTarget):WINOLEAPI;stdcall;external 'ole32.dll' name 'RegisterDragDrop';
|
function RegisterDragDrop(hwnd:HWND; pDropTarget:IDropTarget):WINOLEAPI;stdcall;external 'ole32.dll' name 'RegisterDragDrop';
|
||||||
|
|
||||||
function RevokeDragDrop(hwnd:HWND):WINOLEAPI;stdcall;external 'ole32.dll' name 'RevokeDragDrop';
|
function RevokeDragDrop(hwnd:HWND):WINOLEAPI;stdcall;external 'ole32.dll' name 'RevokeDragDrop';
|
||||||
@ -274,4 +275,6 @@ function OleFlushClipboard:WINOLEAPI;stdcall;external 'ole32.dll' name 'OleFlush
|
|||||||
|
|
||||||
function OleIsCurrentClipboard(pDataObj:IDataObject):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleIsCurrentClipboard';
|
function OleIsCurrentClipboard(pDataObj:IDataObject):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleIsCurrentClipboard';
|
||||||
|
|
||||||
|
function CreateStreamOnHGlobal(hGlobal:HGLOBAL; fDeleteOnRelease:BOOL;out stm:IStream):WINOLEAPI;stdcall;external 'ole32.dll' name 'CreateStreamOnHGlobal';
|
||||||
|
|
||||||
|
{$endif}
|
||||||
|
@ -18,7 +18,32 @@ const
|
|||||||
SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}';
|
SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}';
|
||||||
SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}';
|
SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}';
|
||||||
|
|
||||||
|
//Bridge to ActiveX constants
|
||||||
|
|
||||||
|
TYMED_HGLOBAL = ActiveX.TYMED_HGLOBAL;
|
||||||
|
TYMED_ISTREAM = ActiveX.TYMED_ISTREAM;
|
||||||
|
DVASPECT_CONTENT = ActiveX.DVASPECT_CONTENT;
|
||||||
|
CLSCTX_INPROC_SERVER = ActiveX.CLSCTX_INPROC_SERVER;
|
||||||
|
DROPEFFECT_COPY = ActiveX.DROPEFFECT_COPY;
|
||||||
|
DROPEFFECT_LINK = ActiveX.DROPEFFECT_LINK;
|
||||||
|
DROPEFFECT_MOVE = ActiveX.DROPEFFECT_MOVE;
|
||||||
|
DROPEFFECT_NONE = ActiveX.DROPEFFECT_NONE;
|
||||||
|
DROPEFFECT_SCROLL = ActiveX.DROPEFFECT_SCROLL;
|
||||||
|
DATADIR_GET = ActiveX.DATADIR_GET;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
//Bridge to ActiveX Types
|
||||||
|
IDataObject = ActiveX.IDataObject;
|
||||||
|
IDropTarget = ActiveX.IDropTarget;
|
||||||
|
IDropSource = ActiveX.IDropSource;
|
||||||
|
IEnumFormatEtc = ActiveX.IEnumFORMATETC;
|
||||||
|
|
||||||
|
//WINOLEAPI = ActiveX.WINOLEAPI;
|
||||||
|
|
||||||
|
TFormatEtc = ActiveX.TFORMATETC;
|
||||||
|
TStgMedium = ActiveX.TStgMedium;
|
||||||
|
PDVTargetDevice = ActiveX.PDVTARGETDEVICE;
|
||||||
|
|
||||||
// OLE drag'n drop support
|
// OLE drag'n drop support
|
||||||
TFormatEtcArray = array of TFormatEtc;
|
TFormatEtcArray = array of TFormatEtc;
|
||||||
TFormatArray = array of Word;
|
TFormatArray = array of Word;
|
||||||
@ -30,6 +55,19 @@ type
|
|||||||
end;
|
end;
|
||||||
TInternalStgMediumArray = array of TInternalStgMedium;
|
TInternalStgMediumArray = array of TInternalStgMedium;
|
||||||
|
|
||||||
|
TEnumFormatEtc = class(TInterfacedObject, IEnumFormatEtc)
|
||||||
|
private
|
||||||
|
FTree: TObject;
|
||||||
|
FFormatEtcArray: TFormatEtcArray;
|
||||||
|
FCurrentIndex: Integer;
|
||||||
|
public
|
||||||
|
constructor Create(Tree: TObject; AFormatEtcArray: TFormatEtcArray);
|
||||||
|
|
||||||
|
function Clone(out Enum: IEnumFormatEtc): HResult; stdcall;
|
||||||
|
function Next(celt: LongWord; out elt: FormatEtc; out pceltFetched: LongWord): HResult; stdcall;
|
||||||
|
function Reset: HResult; stdcall;
|
||||||
|
function Skip(celt: LongWord): HResult; stdcall;
|
||||||
|
end;
|
||||||
|
|
||||||
IDropTargetHelper = interface(IUnknown)
|
IDropTargetHelper = interface(IUnknown)
|
||||||
[SID_IDropTargetHelper]
|
[SID_IDropTargetHelper]
|
||||||
@ -139,15 +177,272 @@ type
|
|||||||
function QueryContinueDrag(EscapePressed: BOOL; KeyState: Integer): HResult; stdcall;
|
function QueryContinueDrag(EscapePressed: BOOL; KeyState: Integer): HResult; stdcall;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//ActiveX functions that have wrong calling convention in fpc
|
||||||
|
|
||||||
|
function RegisterDragDrop(hwnd:HWND; pDropTarget:IDropTarget):WINOLEAPI;stdcall;external 'ole32.dll' name 'RegisterDragDrop';
|
||||||
|
|
||||||
|
function RevokeDragDrop(hwnd:HWND):WINOLEAPI;stdcall;external 'ole32.dll' name 'RevokeDragDrop';
|
||||||
|
|
||||||
|
function DoDragDrop(pDataObj:IDataObject; pDropSource:IDropSource; dwOKEffects:DWORD; pdwEffect:LPDWORD):WINOLEAPI;stdcall;external 'ole32.dll' name 'DoDragDrop';
|
||||||
|
|
||||||
|
function OleInitialize(pvReserved:LPVOID):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleInitialize';
|
||||||
|
|
||||||
|
procedure OleUninitialize;stdcall;external 'ole32.dll' name 'OleUninitialize';
|
||||||
|
|
||||||
|
procedure ReleaseStgMedium(_para1:LPSTGMEDIUM);stdcall;external 'ole32.dll' name 'ReleaseStgMedium';
|
||||||
|
|
||||||
|
function OleSetClipboard(pDataObj:IDataObject):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleSetClipboard';
|
||||||
|
|
||||||
|
function OleGetClipboard(out ppDataObj:IDataObject):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleGetClipboard';
|
||||||
|
|
||||||
|
function OleFlushClipboard:WINOLEAPI;stdcall;external 'ole32.dll' name 'OleFlushClipboard';
|
||||||
|
|
||||||
|
function OleIsCurrentClipboard(pDataObj:IDataObject):WINOLEAPI;stdcall;external 'ole32.dll' name 'OleIsCurrentClipboard';
|
||||||
|
|
||||||
|
function CreateStreamOnHGlobal(hGlobal:HGLOBAL; fDeleteOnRelease:BOOL;out stm:IStream):WINOLEAPI;stdcall;external 'ole32.dll' name 'CreateStreamOnHGlobal';
|
||||||
|
|
||||||
|
function CoCreateInstance(const _para1:TCLSID; _para2:IUnknown; _para3:DWORD;const _para4:TIID;out _para5):HRESULT;stdcall; external 'ole32.dll' name 'CoCreateInstance';
|
||||||
|
|
||||||
|
//helper functions to isolate windows/OLE specific code
|
||||||
|
|
||||||
|
function RenderOLEData(Tree: TObject; const FormatEtcIn: TFormatEtc; out Medium: TStgMedium;
|
||||||
|
ForClipboard: Boolean): HResult;
|
||||||
|
|
||||||
|
function GetStreamFromMedium(Medium:TStgMedium):TStream;
|
||||||
|
|
||||||
|
procedure UnlockMediumData(Medium:TStgMedium);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
VirtualTrees, Controls;
|
VirtualTrees, Controls, oleutils;
|
||||||
|
|
||||||
type
|
type
|
||||||
TVirtualTreeAccess = class (TBaseVirtualTree)
|
TVirtualTreeAccess = class (TBaseVirtualTree)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function RenderOLEData(Tree: TObject; const FormatEtcIn: TFormatEtc; out
|
||||||
|
Medium: TStgMedium; ForClipboard: Boolean): HResult;
|
||||||
|
|
||||||
|
//--------------- local function --------------------------------------------
|
||||||
|
|
||||||
|
procedure WriteNodes(Stream: TStream);
|
||||||
|
|
||||||
|
var
|
||||||
|
Selection: TNodeArray;
|
||||||
|
I: Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
with TVirtualTreeAccess(Tree) do
|
||||||
|
begin
|
||||||
|
if ForClipboard then
|
||||||
|
Selection := GetSortedCutCopySet(True)
|
||||||
|
else
|
||||||
|
Selection := GetSortedSelection(True);
|
||||||
|
for I := 0 to High(Selection) do
|
||||||
|
WriteNode(Stream, Selection[I]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//--------------- end local function ----------------------------------------
|
||||||
|
|
||||||
|
var
|
||||||
|
Data: PCardinal;
|
||||||
|
ResPointer: Pointer;
|
||||||
|
ResSize: Integer;
|
||||||
|
OLEStream: IStream;
|
||||||
|
VCLStream: TStream;
|
||||||
|
|
||||||
|
begin
|
||||||
|
VCLStream := nil;
|
||||||
|
try
|
||||||
|
Medium.PunkForRelease := nil;
|
||||||
|
// Return data in one of the supported storage formats, prefer IStream.
|
||||||
|
if FormatEtcIn.tymed and TYMED_ISTREAM <> 0 then
|
||||||
|
begin
|
||||||
|
// Create an IStream on a memory handle (here it is 0 which indicates to implicitely allocated a handle).
|
||||||
|
// Do not use TStreamAdapter as it is not compatible with OLE (when flushing the clipboard OLE wants the HGlobal
|
||||||
|
// back which is not supported by TStreamAdapater).
|
||||||
|
CreateStreamOnHGlobal(0, True, OLEStream);
|
||||||
|
|
||||||
|
VCLStream := TOLEStream.Create(OLEStream);
|
||||||
|
WriteNodes(VCLStream);
|
||||||
|
// Rewind stream.
|
||||||
|
VCLStream.Position := 0;
|
||||||
|
Medium.tymed := TYMED_ISTREAM;
|
||||||
|
IUnknown(Medium.Pstm) := OLEStream;
|
||||||
|
Result := S_OK;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
VCLStream := TMemoryStream.Create;
|
||||||
|
WriteNodes(VCLStream);
|
||||||
|
ResPointer := TMemoryStream(VCLStream).Memory;
|
||||||
|
ResSize := VCLStream.Position;
|
||||||
|
|
||||||
|
// Allocate memory to hold the string.
|
||||||
|
if ResSize > 0 then
|
||||||
|
begin
|
||||||
|
Medium.hGlobal := GlobalAlloc(GHND or GMEM_SHARE, ResSize + SizeOf(Cardinal));
|
||||||
|
Data := GlobalLock(Medium.hGlobal);
|
||||||
|
// Store the size of the data too, for easy retrival.
|
||||||
|
Data^ := ResSize;
|
||||||
|
Inc(Data);
|
||||||
|
Move(ResPointer^, Data^, ResSize);
|
||||||
|
GlobalUnlock(Medium.hGlobal);
|
||||||
|
Medium.tymed := TYMED_HGLOBAL;
|
||||||
|
|
||||||
|
Result := S_OK;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := E_FAIL;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
// We can free the VCL stream here since it was either a pure memory stream or only a wrapper around
|
||||||
|
// the OLEStream which exists independently.
|
||||||
|
VCLStream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
// needed to handle OLE global memory objects
|
||||||
|
TOLEMemoryStream = class(TCustomMemoryStream)
|
||||||
|
public
|
||||||
|
function Write(const Buffer; Count: Integer): Longint; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TOLEMemoryStream.Write(const Buffer; Count: Integer): Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{$ifdef COMPILER_5_UP}
|
||||||
|
raise EStreamError.CreateRes(PResStringRec(@SCantWriteResourceStreamError));
|
||||||
|
{$else}
|
||||||
|
raise EStreamError.Create(SCantWriteResourceStreamError);
|
||||||
|
{$endif COMPILER_5_UP}
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function GetStreamFromMedium(Medium: TStgMedium): TStream;
|
||||||
|
var
|
||||||
|
Data: Pointer;
|
||||||
|
I: Integer;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if Medium.tymed = TYMED_ISTREAM then
|
||||||
|
Result := TOLEStream.Create(IUnknown(Medium.Pstm) as IStream)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Data := GlobalLock(Medium.hGlobal);
|
||||||
|
if Assigned(Data) then
|
||||||
|
begin
|
||||||
|
// Get the total size of data to retrieve.
|
||||||
|
I := PCardinal(Data)^;
|
||||||
|
Inc(PCardinal(Data));
|
||||||
|
Result := TOLEMemoryStream.Create;
|
||||||
|
TOLEMemoryStream(Result).SetPointer(Data, I);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure UnlockMediumData(Medium: TStgMedium);
|
||||||
|
begin
|
||||||
|
if Medium.tymed = TYMED_HGLOBAL then
|
||||||
|
GlobalUnlock(Medium.hGlobal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// OLE drag and drop support classes
|
||||||
|
// This is quite heavy stuff (compared with the VCL implementation) but is much better suited to fit the needs
|
||||||
|
// of DD'ing various kinds of virtual data and works also between applications.
|
||||||
|
|
||||||
|
//----------------- TEnumFormatEtc -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
constructor TEnumFormatEtc.Create(Tree: TObject; AFormatEtcArray: TFormatEtcArray);
|
||||||
|
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
|
||||||
|
FTree := Tree;
|
||||||
|
// Make a local copy of the format data.
|
||||||
|
SetLength(FFormatEtcArray, Length(AFormatEtcArray));
|
||||||
|
for I := 0 to High(AFormatEtcArray) do
|
||||||
|
FFormatEtcArray[I] := AFormatEtcArray[I];
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TEnumFormatEtc.Clone(out Enum: IEnumFormatEtc): HResult;
|
||||||
|
|
||||||
|
var
|
||||||
|
AClone: TEnumFormatEtc;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := S_OK;
|
||||||
|
try
|
||||||
|
AClone := TEnumFormatEtc.Create(nil, FFormatEtcArray);
|
||||||
|
AClone.FCurrentIndex := FCurrentIndex;
|
||||||
|
Enum := AClone as IEnumFormatEtc;
|
||||||
|
except
|
||||||
|
Result := E_FAIL;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TEnumFormatEtc.Next(celt: LongWord; out elt: FormatEtc; out pceltFetched: LongWord): HResult;
|
||||||
|
|
||||||
|
var
|
||||||
|
CopyCount: LongWord;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := S_FALSE;
|
||||||
|
CopyCount := Length(FFormatEtcArray) - FCurrentIndex;
|
||||||
|
if celt < CopyCount then
|
||||||
|
CopyCount := celt;
|
||||||
|
if CopyCount > 0 then
|
||||||
|
begin
|
||||||
|
Move(FFormatEtcArray[FCurrentIndex], elt, CopyCount * SizeOf(TFormatEtc));
|
||||||
|
Inc(FCurrentIndex, CopyCount);
|
||||||
|
Result := S_OK;
|
||||||
|
end;
|
||||||
|
//todo_lcl_check Delphi treats pceltFetched an PInteger. Implemented like in fpc.activex. What heappens with
|
||||||
|
// a C Program call with a NULL in pCeltFetcjed??
|
||||||
|
//Answer: Yes. Is necessary a check here
|
||||||
|
if @pceltFetched <> nil then
|
||||||
|
pceltFetched := CopyCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TEnumFormatEtc.Reset: HResult;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FCurrentIndex := 0;
|
||||||
|
Result := S_OK;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TEnumFormatEtc.Skip(celt: LongWord): HResult;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if FCurrentIndex + celt < High(FFormatEtcArray) then
|
||||||
|
begin
|
||||||
|
Inc(FCurrentIndex, celt);
|
||||||
|
Result := S_Ok;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := S_FALSE;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
//----------------- TVTDataObject --------------------------------------------------------------------------------------
|
//----------------- TVTDataObject --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
constructor TVTDataObject.Create(AOwner: TObject; ForClipboard: Boolean);
|
constructor TVTDataObject.Create(AOwner: TObject; ForClipboard: Boolean);
|
||||||
|
Reference in New Issue
Block a user