www.pudn.com > TMS.Component.Pack.v5.0.rar > adveddd.pas, change:2009-01-24,size:19437b


{*************************************************************************} 
{ Drag'n'drop interface support file                                      } 
{ for Delphi 5,6,7,2005,2006 & C++Builder 5,6,2006                        } 
{                                                                         } 
{ written by TMS Software                                                 } 
{            copyright © 1996-2003                                        } 
{            Email : info@tmssoftware.com                                 } 
{            Web : http://www.tmssoftware.com                             } 
{                                                                         } 
{ The source code is given as is. The author is not responsible           } 
{ for any possible damage done due to the use of this code.               } 
{ The component can be freely used in any application. The complete       } 
{ source code remains property of the author and may not be distributed,  } 
{ published, given or sold in any form as such. No parts of the source    } 
{ code can be included in any other component or application without      } 
{ written authorization of the author.                                    } 
{*************************************************************************} 
 
unit AdvEddd; 
 
{$H+} 
 
{$I TMSDEFS.INC} 
{$H+} 
 
{$IFDEF VER125} 
 {$HPPEMIT '#include <oleidl.h>'} 
{$ENDIF} 
 
{$IFDEF VER130} 
 {$HPPEMIT '#include <oleidl.h>'} 
{$ENDIF} 
 
{$IFDEF VER140} 
  {$IFDEF BCB} 
  {$HPPEMIT '#include <oleidl.h>'} 
  {$ENDIF} 
{$ENDIF} 
 
{$IFDEF VER180} 
  {$HPPEMIT '#include <oleidl.h>'} 
{$ENDIF} 
 
interface 
 
{$IFNDEF TMSDOTNET} 
uses 
  Windows, Messages, ActiveX, StdCtrls, Classes, 
  Controls, SysUtils, Forms, ShlObj; 
 
const 
  deNone   = DROPEFFECT_NONE; 
  deMove   = DROPEFFECT_MOVE; 
  deCopy   = DROPEFFECT_COPY; 
  deLink   = DROPEFFECT_LINK; 
  deScroll = DROPEFFECT_SCROLL; 
  ddGet = DATADIR_GET; 
  ddSet = DATADIR_SET; 
 
  tsGlobal       = TYMED_HGLOBAL;   // handle to global memory clock 
  tsFile         = TYMED_FILE;      // file 
  tsStream       = TYMED_ISTREAM;   // stream interface 
  tsStorage      = TYMED_ISTORAGE;  // storage interface 
  tsGDI          = TYMED_GDI;       // gdi object 
  tsMetafilePict = TYMED_MFPICT;    // metafilepict structure 
  tsEnhMetafile  = TYMED_ENHMF;     // enhanced metafile 
  tsNull         = TYMED_NULL;      // no storage 
 
 
type 
  TEnumFormats = class 
  private 
    FDataObject : IDataObject; 
    FEnumerator : IEnumFormatEtc; 
    FFormatEtc  : TFormatEtc; 
    FValid      : boolean; 
    FCount      : integer; 
    FFiles      : TStringList; 
    procedure SetDataObject (Value : IDataObject); 
    function SomeText (Format : TClipFormat) : string; 
    function SomeFiles(var Files:TStringList):boolean; 
    function GetAspect:integer; 
    procedure SetAspect(value:integer); 
    function GetcfFormat:TClipFormat; 
    procedure SetcfFormat(value:TClipFormat); 
    function GetlIndex:integer; 
    procedure SetlIndex(value:integer); 
    function GetTymed:integer; 
    procedure SetTymed(value:integer); 
  public 
    constructor Create (DataObject : IDataObject); 
    destructor Destroy; override; 
    function Reset : boolean; 
    function Next : boolean; 
    function HasFormat (ClipFormat : TClipFormat) : boolean; 
    function Handle (Tymed : integer): hGlobal; 
    function GlobalHandle : hGlobal; 
    function HasText : boolean; 
    function HasFile : boolean; 
    function HasRTF : boolean; 
    function Text : string; 
    function RTF : string; 
    property Count : integer read FCount; 
    property DataObject : IDataObject read FDataObject write SetDataObject; 
    property Valid : boolean read FValid; 
    property FormatEtc : TFormatEtc read FFormatEtc; 
    property Aspect : integer read GetAspect write SetAspect; 
    property Format : TClipFormat read GetcfFormat write SetcfFormat; 
    property Index : integer read GetlIndex write SetlIndex; 
    property Medium : integer read GetTymed write SetTymed; 
  end; 
 
  TAEDropTarget = class (TInterfacedObject, IDropTarget) 
    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 DragLeave : HResult; stdcall; 
    function Drop (const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; 
  private 
    FOk : boolean; 
  public 
    constructor Create; 
    procedure DropText(pt:TPoint;s:string); virtual; 
    procedure DropRTF(pt:TPoint;s:string); virtual; 
    procedure DropFiles(pt:TPoint;Files:TStrings); virtual; 
    procedure DragMouseMove(pt:TPoint;var Allow:boolean); virtual; 
  end; 
 
  TAEDropSource = class (TInterfacedObject, IDropSource) 
  private 
    fNoAccept:boolean; 
  public 
    function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; stdcall; 
    function GiveFeedback(dwEffect: Longint): HResult; stdcall; 
  end; 
 
  TSourceDataObject = class (TInterfacedObject, IDataObject) 
  private 
    textdata:string; 
    rtfdata:string; 
  public 
    constructor Create(const stxt,srtf:string); 
  public 
    function GetData(const formatetc: TFormatEtc; out medium: TStgMedium): HResult; stdcall; 
    function GetDataHere (const formatetc: TFormatEtc; out medium: TStgMedium): HResult; stdcall; 
    function QueryGetData(const formatetc: TFormatEtc): HResult; stdcall; 
    function SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult; stdcall; 
    function GetCanonicalFormatEtc(const formatetcIn: TFormatEtc;   out formatetcOut: TFormatEtc): HResult; stdcall; 
    function EnumFormatEtc(dwDirection: Longint; out enumFormatEtc: IEnumFormatEtc): HResult; stdcall; 
    function DAdvise(const formatetc: TFormatEtc; advf: Longint; const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall; 
    function DUnadvise(dwConnection: Longint): HResult; stdcall; 
    function EnumDAdvise(out enumAdvise: IEnumStatData): HResult; stdcall; 
  end; 
 
  TSourceEnumFormatEtc = class (TInterfacedObject, IEnumFormatEtc) 
  protected 
    FIndex : integer; // Next FormatEtc to get 
  public 
    function Next (CountRequested: Longint; out FormatEtcArray; PCountFetched: PLongint): HResult; stdcall; 
    function Skip (count: Longint) : HResult; stdcall; 
    function Reset : HResult; stdcall; 
    function Clone (out enumFmt : IEnumFormatEtc) : HResult; stdcall; 
  end; 
 
  TFormatEtcArray = array[0..19] of TFormatEtc; 
  PFormatEtcArray = ^TFormatEtcArray; 
 
 
function StandardEffect (Keys : TShiftState) : integer; 
function StartTextDoDragDrop(stxt,srtf:string;dwOKEffects: Longint; var dwEffect: Longint): HResult; 
procedure SetRTFAware(value:boolean); 
 
{$ENDIF} 
implementation 
{$IFNDEF TMSDOTNET} 
var 
  CF_RTF : integer; 
  RTFAware:boolean; 
 
procedure SetRTFAware(value:boolean); 
begin 
 RTFAware:=value; 
end; 
 
function StandardEffect (Keys : TShiftState) : integer; 
begin 
  Result := deMove; 
  if ssCtrl in Keys then 
    Result := deCopy 
end; 
 
constructor TEnumFormats.Create (DataObject : IDataObject); 
begin 
  inherited Create; 
  SetDataObject (DataObject); 
  FFiles:=TStringList.Create; 
 
  if OpenClipBoard(0) then 
    begin 
     CF_RTF:=RegisterClipboardformat('Rich Text Format'); 
     CloseClipBoard; 
    end; 
end; 
 
destructor TEnumFormats.Destroy; 
begin 
  SetDataObject (nil); 
  FFiles.Free; 
  inherited Destroy 
end; 
 
function TEnumFormats.Next : boolean; 
var 
  Returned : integer; 
begin 
  inc (FCount); 
  FValid := FEnumerator.Next (1, FFormatEtc, @Returned) = S_OK; 
  Result := FValid 
end; 
 
function TEnumFormats.Reset : boolean; 
begin 
  FValid := false; 
  FCount := 0; 
  Result := Succeeded (FEnumerator.Reset) 
end; 
 
function TEnumFormats.HasFormat (ClipFormat : TClipFormat) : boolean; 
begin 
 Result:=false; 
 if Reset then 
   while (not Result) and Next do 
      Result:=(ClipFormat=Format); 
end; 
 
procedure TEnumFormats.SetDataObject (Value : IDataObject); 
var 
  Result : integer; 
begin 
  FDataObject := nil; 
  FDataObject := Value; 
  if Assigned (FDataObject) then 
  begin 
    Result := FDataObject.EnumFormatEtc (ddGet, FEnumerator); 
    Assert (Succeeded (Result), 'Cannot get the format enumerator'); 
    Reset 
  end 
end; 
 
function TEnumFormats.Handle (Tymed : integer): hGlobal; 
var 
  FormatEtc : TFormatEtc; 
  Medium : TStgMedium; 
begin 
  Result := 0; 
  if FValid and (FFormatEtc.tymed and Tymed = Tymed) then 
  begin 
    FormatEtc := FFormatEtc; 
    FormatEtc.tymed := FormatEtc.tymed and Tymed; // use only the requested type 
    if Succeeded (FDataObject.GetData (FormatEtc, Medium)) then 
      Result := Medium.hGlobal 
  end 
end; 
 
function TEnumFormats.GlobalHandle : hGlobal; 
begin 
  Result := Handle (tsGlobal) 
end; 
 
function TEnumFormats.SomeText (Format : TClipFormat) : string; 
var 
  H : hGlobal; 
  P : PChar; 
begin 
  Result := ''; 
  if HasFormat (Format) then 
  begin 
    H := GlobalHandle; 
    if H <> 0 then 
    begin 
      P := GlobalLock (H); 
      try 
        Result := P 
      finally 
        GlobalUnLock (H) 
      end 
    end 
  end 
end; 
 
function TEnumFormats.SomeFiles(var Files: TStringList): boolean; 
var 
  DropFiles:PDropFiles; 
  Filename:PChar; 
  s:string; 
  H:hGlobal; 
 
begin 
  FFiles.Clear; 
 
  H:= GlobalHandle; 
  if H<>0 then 
   begin 
    DropFiles := PDropFiles(GlobalLock(H)); 
    try 
     Filename := PChar(DropFiles) + DropFiles^.pFiles; 
     while (Filename^ <> #0) do 
     begin 
       if (DropFiles^.fWide) then // -> NT4 compatability 
       begin 
         s := WideCharToString(PWideChar(Filename)); 
          inc(Filename, (Length(s) + 1) * 2); 
        end else 
       begin 
         s := StrPas(Filename); 
          inc(Filename, Length(s) + 1); 
       end; 
        Files.Add(s); 
      end; 
   finally 
      GlobalUnlock(H); 
   end; 
  end; 
 
 if Files.count > 0 then 
 result := true else 
 result := false; 
end; 
 
function TEnumFormats.RTF : string; 
begin 
 Result := SomeText(CF_RTF); 
end; 
 
function TEnumFormats.Text : string; 
begin 
 Result := SomeText(CF_TEXT) 
end; 
 
function TEnumFormats.HasText : boolean; 
begin 
 Result := HasFormat(CF_TEXT) 
end; 
 
function TEnumFormats.HasRTF : boolean; 
begin 
 Result := HasFormat(CF_RTF); 
end; 
 
function TEnumFormats.HasFile : boolean; 
begin 
 Result := HasFormat(CF_HDROP) 
end; 
 
constructor TAEDropTarget.Create; 
begin 
 inherited Create; 
end; 
 
function TAEDropTarget.DragEnter (const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; 
begin 
  with TEnumFormats.Create (DataObj) do 
  try 
    FOk := HasText or HasFile or (HasRTF and RTFAware); 
  finally 
    Free 
  end; 
 
  if FOk then 
    dwEffect := StandardEffect (KeysToShiftState (grfKeyState)) 
  else 
    dwEffect := deNone; 
  Result := NOERROR; 
end; 
 
function TAEDropTarget.DragOver (grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; 
var 
 allow:boolean; 
begin 
  if FOk then 
    dwEffect := StandardEffect (KeysToShiftState (grfKeyState)) 
  else 
    dwEffect := deNone; 
 
  allow:=true;   
  DragMouseMove(pt,allow); 
  if not allow then dwEffect:=deNone; 
 
  Result := NOERROR; 
end; 
 
function TAEDropTarget.DragLeave: HResult; 
begin 
  Result := NOERROR 
end; 
 
function TAEDropTarget.Drop (const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; 
begin 
  if FOk then 
  begin 
    with TEnumFormats.Create(DataObj) do 
    try 
     if HasRTF and RTFAware then DropRTF(pt,RTF) 
     else 
     if HasText then DropText(pt,Text); 
     if HasFile then 
       begin 
        SomeFiles(fFiles); 
        DropFiles(pt,fFiles); 
       end; 
    finally 
      Free 
    end; 
 
    dwEffect := StandardEffect (KeysToShiftState (grfKeyState)) 
  end else 
    dwEffect := deNone; 
 
  Result := NOERROR 
end; 
 
procedure TAEDropTarget.DropText(pt:tpoint;s:string); 
begin 
end; 
 
procedure TAEDropTarget.DropRTF(pt:tpoint;s:string); 
begin 
end; 
 
procedure TAEDropTarget.DropFiles(pt:tpoint;files:tstrings); 
begin 
end; 
 
procedure TAEDropTarget.DragMouseMove(pt: TPoint; var Allow: boolean); 
begin 
 allow:=true; 
end; 
 
 
 
 
function TSourceEnumFormatEtc.Next (CountRequested: Longint; out FormatEtcArray; PCountFetched: PLongint): HResult; 
Var 
  N: integer; 
  FormatEtcArrayOut: TFormatEtcArray absolute FormatEtcArray; 
Label the_end; 
Begin 
  Result := S_FALSE; 
 
  N := 0; 
  while (N  CountRequested) and (N+FIndex  3) do 
  Begin 
    Case N+Findex of 
     0:Begin 
        formatetcArrayOut[0].cfFormat := CF_TEXT; 
        formatetcArrayOut[0].ptd      := nil; 
        formatetcArrayOut[0].dwAspect := DVASPECT_CONTENT; 
        formatetcArrayOut[0].lindex   := -1; 
        formatetcArrayOut[0].tymed    := TYMED_HGLOBAL; 
      end; 
    1:Begin 
        formatetcArrayOut[0].cfFormat := CF_UNICODETEXT; 
        formatetcArrayOut[0].ptd      := nil; 
        formatetcArrayOut[0].dwAspect := DVASPECT_CONTENT; 
        formatetcArrayOut[0].lindex   := -1; 
        formatetcArrayOut[0].tymed    := TYMED_HGLOBAL; 
      end; 
 
    2:Begin 
        formatetcArrayOut[0].cfFormat := CF_RTF; 
        formatetcArrayOut[0].ptd      := nil; 
        formatetcArrayOut[0].dwAspect := DVASPECT_CONTENT; 
        formatetcArrayOut[0].lindex   := -1; 
        formatetcArrayOut[0].tymed    := TYMED_HGLOBAL; 
      end; 
     end; 
    Inc(FIndex); 
    Inc(N); 
  end; 
  If PCountFetched <> nil then PCountFetched^ := N; 
  if N = CountRequested then Result := S_OK; 
 
end; 
 
function TSourceEnumFormatEtc.Skip (count: Longint) : HResult; 
Begin 
  FIndex := FIndex + count; 
  If FIndex > 3 then {changed from 2 to 3} 
    Begin 
      FIndex := 3; 
      Result := S_FALSE; 
    end 
  else Result := S_OK; 
end; 
 
function TSourceEnumFormatEtc.Reset : HResult; 
Begin 
  FIndex := 0; 
  Result := S_OK; 
end; 
 
function TSourceEnumFormatEtc.Clone (out enumFmt : IEnumFormatEtc) : HResult; stdcall; 
Var 
  MyFormatEtc: TSourceEnumFormatEtc; 
Begin 
  MyFormatEtc := TSourceEnumFormatEtc.Create; 
  enumFmt := MyFormatEtc; 
  Result := S_OK; 
end; 
 
constructor TSourceDataObject.Create(const stxt,srtf:string); 
begin 
 inherited Create; 
 textdata:=stxt; 
 rtfdata:=srtf; 
end; 
 
function TSourceDataObject.EnumFormatEtc(dwDirection: Longint; out enumFormatEtc: IEnumFormatEtc): HResult; 
Begin 
 if dwDirection <> DATADIR_GET then 
  Begin 
    enumFormatEtc := nil; 
    Result := E_NOTIMPL; 
    exit; 
  end; 
 enumFormatEtc := TSourceEnumFormatEtc.Create; 
 Result := S_OK; 
end; 
 
 
function TSourceDataObject.QueryGetData(const formatetc: TFormatEtc): HResult; 
Begin 
 Result := DV_E_FORMATETC; 
 if (formatetc.dwAspect = DVASPECT_CONTENT) and 
    ((formatetc.cfFormat = CF_TEXT) or (formatetc.cfFormat = CF_UNICODETEXT) or ((formatetc.cfFormat = CF_RTF) and RTFAware)) and 
    (formatetc.tymed = TYMED_HGLOBAL) then Result := S_OK; 
end; 
 
function TSourceDataObject.GetData(const formatetc: TFormatEtc; out medium: TStgMedium): HResult; 
Var 
  HGlobalData: HGlobal; 
  PGlobalData: PChar; 
  AllocLen: integer; 
  RTFLen : integer; 
  TXTLen : integer; 
Label the_end; 
Begin 
  Result:=DV_E_FORMATETC; 
  medium.tymed:=0; 
  medium.hGlobal:=0; 
  medium.unkForRelease:=nil; 
 
  If (QueryGetData(formatetc)<>S_OK) then goto the_end; 
 
  medium.tymed:=TYMED_HGLOBAL; 
 
  TXTLen:=Length(textdata); 
  RTFLen:=Length(rtfdata); 
 
  case formatetc.cfFormat of 
  CF_TEXT:AllocLen:=TXTLen+1; 
  CF_UNICODETEXT:AllocLen:=TXTLen*2+2; 
  else AllocLen:=0; 
  end; 
 
  if (formatetc.cfFormat=CF_RTF) then AllocLen:=RTFLen; 
 
  HGlobalData:=GlobalAlloc((GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT), AllocLen); 
  if (HGlobalData<>0) then 
  begin 
    PGlobalData := GlobalLock (HGlobalData); // lock while we are using it 
    case formatetc.cfFormat of 
    CF_TEXT:StrCopy(PGlobalData, PChar(textdata)); 
    CF_UNICODETEXT:StringToWideChar(textdata, PWideChar(PGlobalData), AllocLen+1); 
    end; 
 
    if (formatetc.cfFormat = CF_RTF) then StrCopy(PGlobalData, PChar(rtfdata)); 
 
    GlobalUnlock (HGlobalData); 
    medium.hGlobal := HGlobalData; 
    Result := S_OK; 
  end; 
the_end: 
 
end; 
 
function TSourceDataObject.GetDataHere (const formatetc: TFormatEtc; out medium: TStgMedium): HResult; 
Begin 
  Result := DV_E_FORMATETC; 
end; 
 
function TSourceDataObject.SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult; 
Begin 
  Result := DV_E_FORMATETC; 
end; 
 
function TSourceDataObject.GetCanonicalFormatEtc(const formatetcIn: TFormatEtc;   out formatetcOut: TFormatEtc): HResult; 
Begin 
  formatetcOut.ptd := nil; 
  Result := E_NOTIMPL; 
end; 
 
function TSourceDataObject.DAdvise(const formatetc: TFormatEtc; advf: Longint; const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall; 
Begin 
  Result := OLE_E_ADVISENOTSUPPORTED; 
end; 
 
function TSourceDataObject.DUnadvise(dwConnection: Longint): HResult; stdcall; 
Begin 
  Result := OLE_E_ADVISENOTSUPPORTED; 
end; 
 
function TSourceDataObject.EnumDAdvise(out enumAdvise: IEnumStatData): HResult; stdcall; 
Begin 
  Result := OLE_E_ADVISENOTSUPPORTED; 
end; 
 
function TAEDropSource.QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; 
//------------------------------------------------------- 
Begin 
  Result := S_OK; 
  If fEscapePressed then Result := DRAGDROP_S_CANCEL else 
    if ((grfKeyState and MK_LBUTTON) = 0) then // mouse-up 
      Result := DRAGDROP_S_DROP; 
end; 
 
function TAEDropSource.GiveFeedback(dwEffect: Longint): HResult; 
Begin 
  fNoAccept:=dwEffect=DROPEFFECT_NONE; 
  Result:=DRAGDROP_S_USEDEFAULTCURSORS; 
end; 
 
function StartTextDoDragDrop(stxt,srtf:string;dwOKEffects: Longint; var dwEffect: Longint): HResult; 
Var 
  DropSource   : TAEDropSource;     // Pascal versions for debugging purposes 
  DataObject   : TSourceDataObject; 
  MyIDropSource: IDropSource;     // Ixxx versions to generate references 
  MyIDataObject: IDataObject; 
 
Begin 
  DropSource     := TAEDropSource.Create; 
  MyIDropSource  := DropSource; 
 
  DataObject     := TSourceDataObject.Create(stxt,srtf); 
  MyIDataObject  := DataObject; 
 
  Result := activex.DoDragDrop(MyIDataObject, MyIDropSource, dwOKEffects, dwEffect); 
 
  if DropSource.fNoAccept then Result:=DRAGDROP_S_CANCEL; 
end; 
 
function TEnumFormats.GetAspect: integer; 
begin 
 result:=FFormatEtc.dwAspect; 
end; 
 
function TEnumFormats.GetcfFormat: TClipFormat; 
begin 
 result:=FFormatEtc.cfFormat; 
end; 
 
function TEnumFormats.GetlIndex: integer; 
begin 
 result:=FFormatEtc.lIndex; 
end; 
 
function TEnumFormats.GetTymed: integer; 
begin 
 result:=FFormatEtc.Tymed; 
end; 
 
procedure TEnumFormats.SetAspect(value: integer); 
begin 
 FFormatEtc.dwAspect:=value; 
end; 
 
procedure TEnumFormats.SetcfFormat(value: TClipFormat); 
begin 
 FFormatEtc.cfFormat:=value; 
end; 
 
procedure TEnumFormats.SetlIndex(value: integer); 
begin 
 FFormatEtc.lIndex:=value; 
end; 
 
procedure TEnumFormats.SetTymed(value: integer); 
begin 
 FFormatEtc.Tymed:=value; 
end; 
 
initialization 
 RTFAware:=false; 
 CF_RTF:=0; 
{$ENDIF} 
end.