DragDrop.pas 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038
  1. unit DragDrop;
  2. {
  3. Description
  4. ===========
  5. TDragDrop is a component for OLE drag-and-drop operations. The component
  6. is able to make successor components of TWinControl to the source AND
  7. target of drag-and-drop operations.
  8. Disclaimer
  9. ==========
  10. The author disclaims all warranties, expressed or implied, including,
  11. without limitation, the warranties of merchantability and of fitness
  12. for any purpose. The author assumes no liability for damages, direct or
  13. consequential, which may result from the use of this component/unit.
  14. Restrictions on Using the Unit / Component
  15. ==========================================
  16. This unit/component is copyright 1998 by Dieter Steinwedel. ALL RIGHTS
  17. ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it freely
  18. subject to the following restrictions:
  19. • You are not allowed delete or alter the author's name and
  20. copyright in any manner
  21. • You are not allowed to publish a copy, modified version or
  22. compilation neither for payment in any kind nor freely
  23. • You are allowed to create a link to the download in the WWW
  24. • These restrictions and terms apply to you as long as until
  25. I alter them. Changes can found on my homepage
  26. Contact
  27. =======
  28. homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm
  29. }
  30. {$ALIGN ON}
  31. {$ASSERTIONS OFF}
  32. {$BOOLEVAL OFF}
  33. {$DENYPACKAGEUNIT OFF}
  34. {$EXTENDEDSYNTAX ON}
  35. {$HINTS ON}
  36. {$IMPORTEDDATA ON}
  37. {$LONGSTRINGS ON}
  38. {$OPTIMIZATION ON}
  39. {$TYPEDADDRESS OFF}
  40. {$TYPEINFO OFF}
  41. {$WARNINGS ON}
  42. {$WARN SYMBOL_DEPRECATED OFF}
  43. interface
  44. uses
  45. SysUtils, Windows, Classes, Controls, Forms, ShellApi,
  46. Menus, Messages, Graphics, ActiveX, ExtCtrls, Grids;
  47. {MP}(*$HPPEMIT '#include <oleidl.h>'*)
  48. // Available drop effects by the system:
  49. // (redefined, so need not to type "ActiveX" in the uses clause of your units )
  50. const DROPEFFECT_None=ActiveX.DROPEFFECT_None;
  51. DROPEFFECT_Copy=ActiveX.DROPEFFECT_Copy;
  52. DROPEFFECT_Move=ActiveX.DROPEFFECT_Move;
  53. DROPEFFECT_Link=ActiveX.DROPEFFECT_Link;
  54. DROPEFFECT_Scroll=ActiveX.DROPEFFECT_Scroll;
  55. TYMED_HGLOBAL=ActiveX.TYMED_HGLOBAL;
  56. TYMED_FILE=ActiveX.TYMED_FILE;
  57. TYMED_ISTREAM=ActiveX.TYMED_ISTREAM;
  58. TYMED_ISTORAGE=ActiveX.TYMED_ISTORAGE;
  59. TYMED_GDI=ActiveX.TYMED_GDI;
  60. TYMED_MFPICT=ActiveX.TYMED_MFPICT;
  61. TYMED_ENHMF=ActiveX.TYMED_ENHMF;
  62. TYMED_NULL=ActiveX.TYMED_NULL;
  63. DefaultCursor=0;
  64. type
  65. IEnumFormatEtc = ActiveX.IEnumFormatEtc;
  66. IDataObject = ActiveX.IDataObject;
  67. TFormatEtc = ActiveX.TFormatEtc;
  68. TStgMedium = ActiveX.TStgMedium;
  69. TDropEffect=(deCopy, deMove, deLink);
  70. TDragResult=(drInvalid, drCancelled, drCopy, drMove, drLink);
  71. TDropEffectSet = set of TDropEffect;
  72. TDragDetectStatus = (ddsNone, ddsLeft, ddsRight, ddsCancelled, ddsDrag);
  73. TRenderDataOn = (rdoEnter, rdoEnterAndDropSync, rdoEnterAndDropAsync, rdoDropSync, rdoDropAsync, rdoNever);
  74. TSrcCompatibilityCheck = (CheckLindex, CheckdwAspect);
  75. TSrcCompatibilityCheckSet = set of TSrcCompatibilityCheck;
  76. TScrollInterval=1..10000;
  77. TScrollDirection=(sdUp, sdDown, sdLeft, sdRight);
  78. // event handlers ...
  79. TOnDragEnter = procedure(DataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  80. var dwEffect: longint; var Accept:boolean) of object;
  81. TOnDragLeave = procedure of object;
  82. TOnDragOver = procedure(grfKeyState: Longint; pt: TPoint;
  83. var dwEffect: longint) of object;
  84. TOnDrop = procedure(DataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  85. var dwEffect: longint) of object;
  86. TOnQueryContinueDrag = procedure(fEscapePressed: BOOL; grfKeyState: Longint; var Result: HResult) of object;
  87. TOnGiveFeedback = procedure(dwEffect: Longint; var Result: HResult) of object;
  88. TOnDragDetect = procedure(grfKeyState: Longint; DetectStart, pt: TPoint; DragDetectStatus:TDragDetectStatus) of object;
  89. TOnProcessDropped = procedure(Sender: TObject; grfKeyState: Longint; pt: TPoint; dwEffect: Longint) of object;
  90. TOnBeforeScrolling = procedure(Sender: TObject; pt: TPoint; var Interval: TScrollInterval;
  91. ScrollDirection: TScrollDirection; var ScrollPage:boolean) of object;
  92. TOnMenuPopup = procedure(Sender: TObject; AMenu: HMenu; DataObj:IDataObject;
  93. AMinCustCmd:integer; grfKeyState: Longint; pt: TPoint) of object;
  94. TOnMenuExecCmd = procedure(Sender: TObject; AMenu: HMenu; DataObj:IDataObject;
  95. Command:integer; var dwEffect: longint; var Succeeded:boolean) of object;
  96. TOnMenuDestroy = procedure(Sender: TObject; AMenu: HMenu) of object;
  97. TFormatEtcArray = array of TFormatEtc;
  98. TDetectRec = record
  99. end;
  100. // list classes ...
  101. TFormatEtcList = class
  102. private
  103. FCount:integer;
  104. FList:TFormatEtcArray;
  105. function Get(Index: Integer): TFormatEtc;
  106. procedure Put(Index: Integer; Item: TFormatEtc);
  107. public
  108. constructor Create;
  109. destructor Destroy; override;
  110. function Add(Item: TFormatEtc):integer;
  111. procedure Clear;
  112. procedure Delete(Index: Integer);
  113. function Clone:TFormatEtcList;
  114. property Count:integer read FCount;
  115. property Items[Index:integer]:TFormatEtc read get write put;
  116. end;
  117. // inherited classes ...
  118. TDDInterfacedObject = class(TInterfacedObject)
  119. public
  120. function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  121. function _AddRef: Integer; stdcall;
  122. function _Release: Integer; stdcall;
  123. end;
  124. TEnumFormatEtc = class(TDDInterfacedObject, IEnumFormatEtc)
  125. protected
  126. FFormatEtcList:TFormatEtcList;
  127. FIndex: integer;
  128. public
  129. constructor Create(FormatEtcList:TFormatEtcList);
  130. destructor Destroy; override;
  131. function Next(celt: Longint; out elt;
  132. pceltFetched: PLongint): HResult; stdcall;
  133. function Skip(celt: Longint): HResult; stdcall;
  134. function Reset: HResult; stdcall;
  135. function Clone(out Enum: IEnumFormatEtc): HResult; stdcall;
  136. end;
  137. TDataObject = class(TDDInterfacedObject, IDataObject)
  138. protected
  139. FFormatEtcList:TFormatEtcList;
  140. FCheckLindex:boolean;
  141. FCheckdwAspect:boolean;
  142. public
  143. constructor Create;
  144. destructor Destroy; override;
  145. function GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium):
  146. HResult; stdcall;
  147. function GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium):
  148. HResult; stdcall;
  149. function QueryGetData(const formatetc: TFormatEtc): HResult;
  150. stdcall;
  151. function GetCanonicalFormatEtc(const formatetc: TFormatEtc;
  152. out formatetcOut: TFormatEtc): HResult; stdcall;
  153. function SetData(const formatetc: TFormatEtc; var medium: TStgMedium;
  154. fRelease: BOOL): HResult; stdcall;
  155. function EnumFormatEtc(dwDirection: Longint; out enumFormatEtc:
  156. IEnumFormatEtc): HResult; stdcall;
  157. function DAdvise(const formatetc: TFormatEtc; advf: Longint;
  158. const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall;
  159. function DUnadvise(dwConnection: Longint): HResult; stdcall;
  160. function EnumDAdvise(out enumAdvise: IEnumStatData): HResult;
  161. stdcall;
  162. function RenderData(FormatEtc:TFormatEtc;
  163. var StgMedium: TStgMedium): HResult; virtual; abstract;
  164. protected
  165. function AllowData(FormatEtc: TFormatEtc): Boolean; virtual;
  166. end;
  167. // forward declaration, because TDropSource and TDropTarget uses this class ...
  168. TDragDrop = class;
  169. TDropSource = class(TDDInterfacedObject, IDropSource)
  170. private
  171. FOwner: TDragDrop;
  172. public
  173. constructor Create(AOwner: TDragDrop);
  174. destructor Destroy; override;
  175. function QueryContinueDrag(fEscapePressed: BOOL;
  176. grfKeyState: Longint): HResult; stdcall;
  177. function GiveFeedback(dwEffect: Longint): HResult; stdcall;
  178. end;
  179. TDropTarget = class(TDDInterfacedObject, IDropTarget)
  180. private
  181. FAccept:boolean;
  182. HorzStartTimer:TTimer;
  183. HorzScrollTimer:TTimer;
  184. VertStartTimer:TTimer;
  185. VertScrollTimer:TTimer;
  186. FVScrollCode:integer;
  187. FHScrollCode:integer;
  188. procedure InitScroll(VerticalScroll:boolean; ScrollCode:integer);
  189. procedure TermScroll(VerticalScroll:boolean);
  190. procedure DetermineScrollDir(VertScrolling:boolean; var ScrollCode:integer);
  191. procedure OnStartTimer(Sender: TObject);
  192. procedure OnScrollTimer(Sender: TObject);
  193. protected
  194. FOwner: TDragDrop;
  195. procedure SuggestDropEffect(grfKeyState: Longint; var dwEffect: longint); virtual;
  196. procedure AcceptDataObject(DataObj: IDataObject; var Accept:boolean); virtual;
  197. procedure RenderDropped(DataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  198. var dwEffect: longint); virtual;
  199. public
  200. constructor Create(AOwner: TDragDrop);
  201. destructor Destroy; override;
  202. function DragEnter(const dataObj: IDataObject; grfKeyState: Longint;
  203. pt: TPoint; var dwEffect: Longint): HResult; stdcall;
  204. function DragOver(grfKeyState: Longint; pt: TPoint;
  205. var dwEffect: Longint): HResult; stdcall;
  206. function DragLeave: HResult; stdcall;
  207. function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  208. var dwEffect: Longint): HResult; stdcall;
  209. end;
  210. // custom properties
  211. TScrollDetectArea = class(TPersistent)
  212. private
  213. FControl: TPersistent;
  214. FMargin: word;
  215. FRange: word;
  216. FOnChange: TNotifyEvent;
  217. procedure SetValue(Index: Integer; Value: word);
  218. protected
  219. procedure Change; dynamic;
  220. procedure AssignTo(Dest: TPersistent); override;
  221. property Control: TPersistent read FControl;
  222. public
  223. constructor Create(Control: TPersistent);
  224. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  225. published
  226. property Margin: word index 0 read FMargin write SetValue default 0;
  227. property Range: word index 1 read FRange write SetValue default 10;
  228. end;
  229. TScrollDetectOptions = class(TPersistent)
  230. private
  231. FControl: TDragDrop;
  232. FScrollDelay: TScrollInterval;
  233. FStartDelay: TScrollInterval;
  234. FLeft: TScrollDetectArea;
  235. FTop: TScrollDetectArea;
  236. FRight: TScrollDetectArea;
  237. FBottom: TScrollDetectArea;
  238. FOnChange: TNotifyEvent;
  239. FHorzScrolling:boolean;
  240. FVertScrolling:boolean;
  241. FHorzPageScroll:boolean;
  242. FVertPageScroll:boolean;
  243. procedure SetValue(index:integer; Value: TScrollInterval);
  244. protected
  245. procedure Change; dynamic;
  246. procedure AssignTo(Dest: TPersistent); override;
  247. property Control: TDragDrop read FControl;
  248. public
  249. constructor Create(Control: TDragDrop);
  250. destructor Destroy; override;
  251. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  252. published
  253. property ScrollDelay: TScrollInterval index 0 read FScrollDelay write SetValue default 100;
  254. property StartDelay: TScrollInterval index 1 read FStartDelay write SetValue default 750;
  255. property AreaLeft: TScrollDetectArea read FLeft write FLeft;
  256. property AreaTop: TScrollDetectArea read FTop write FTop;
  257. property AreaRight: TScrollDetectArea read FRight write FRight;
  258. property AreaBottom: TScrollDetectArea read FBottom write FBottom;
  259. property HorzScrolling:boolean read FHorzScrolling write FHorzScrolling default false;
  260. property VertScrolling:boolean read FVertScrolling write FVertScrolling default false;
  261. property HorzPageScroll:boolean read FHorzPageScroll write FHorzPageScroll default false;
  262. property VertPageScroll:boolean read FVertPageScroll write FVertPageScroll default false;
  263. end;
  264. // *THE* pseudo-visual Component
  265. TDragDrop = class(TComponent)
  266. private
  267. FAutoDetectDnD:boolean;
  268. FDragDetectDelta:byte;
  269. FAcceptOwnDnD:boolean;
  270. FBTF:Boolean;
  271. FContextMenu: boolean;
  272. FDragDropControl: TWinControl;
  273. FRegistered: Boolean;
  274. FOwnerIsSource:boolean;
  275. FShowPopUpMenu: boolean;
  276. FTargetEffectsSet: TDropEffectSet;
  277. FTargetEffects: longint;
  278. FOnQueryContinueDrag: TOnQueryContinueDrag;
  279. FOnGiveFeedback: TOnGiveFeedback;
  280. FOnDragEnter: TOnDragEnter;
  281. FOnDragLeave: TOnDragLeave;
  282. FOnDragOver: TOnDragOver;
  283. FOnDrop: TOnDrop;
  284. FSourceEffectsSet: TDropEffectSet;
  285. FSourceEffects: longint;
  286. FOnProcessDropped: TOnProcessDropped;
  287. OldWndProc:Pointer;
  288. WndProcPtr:Pointer;
  289. FOnDragDetect:TOnDragDetect;
  290. FDragDetectStatus:TDragDetectStatus;
  291. FDragDetectStart:TPoint;
  292. FRenderDataOn: TRenderDataOn;
  293. FDataObj:IDataObject;
  294. FgrfKeyState: Longint;
  295. Fpt: TPoint;
  296. FdwEffect: Longint;
  297. FCHCopy: HCursor;
  298. FCHMove: HCursor;
  299. FCHLink: HCursor;
  300. FCHScrollCopy: HCursor;
  301. FCHScrollMove: HCursor;
  302. FCHScrollLink: HCursor;
  303. FMessageHooked:boolean;
  304. FAvailableDropEffects:Longint;
  305. FTargetScrolling:integer;
  306. FSrcCompatibilityCheck:TSrcCompatibilityCheckSet;
  307. FScrollDetectOptions: TScrollDetectOptions;
  308. FOnBeforeScrolling: TOnBeforeScrolling;
  309. FOnAfterScrolling: TNotifyEvent;
  310. FPressedButton:integer;
  311. FInternalSource:TDragDrop;
  312. FOnMenuPopup:TOnMenuPopup;
  313. FOnMenuExecCmd:TOnMenuExecCmd;
  314. FOnMenuDestroy:TOnMenuDestroy;
  315. FOnMenuSucceeded:TOnProcessDropped;
  316. FOnDropHandlerSucceeded:TOnProcessDropped;
  317. procedure WndMethod(var Msg: TMessage);
  318. procedure SetDragDropControl(WinControl: TWinControl);
  319. procedure SetSourceEffects(Values:TDropEffectSet);
  320. procedure SetTargetEffects(Values:TDropEffectSet);
  321. protected
  322. FDropTarget: TDropTarget;
  323. procedure Loaded; override;
  324. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  325. function CreateDataObject:TDataObject; virtual; abstract;
  326. procedure DoMenuPopup(Sender: TObject; AMenu: HMenu; DataObj: IDataObject;
  327. AMinCustCmd:integer; grfKeyState: Longint; pt: TPoint); virtual;
  328. function DoMenuExecCmd(Sender: TObject; AMenu: HMenu; DataObj:IDataObject;
  329. Command:integer; var dwEffect: longint):boolean; virtual;
  330. procedure DoMenuDestroy(Sender:TObject; AMenu: HMenu); virtual;
  331. function DropHandler(const dataObj: IDataObject; grfKeyState: Longint;
  332. pt: TPoint; var dwEffect: Longint): boolean; virtual;
  333. property OnDropHandlerSucceeded:TOnProcessDropped read FOnDropHandlerSucceeded
  334. write FOnDropHandlerSucceeded;
  335. public
  336. constructor Create(AOwner: TComponent); override;
  337. destructor Destroy; override;
  338. function RegisterTarget: Boolean;
  339. function UnRegisterTarget: Boolean;
  340. procedure HookMessageHandler;
  341. procedure UnhookMessageHandler(ForceUnhook:boolean);
  342. function ExecuteOperation(DataObject:TDataObject): TDragResult;
  343. function Execute: TDragResult;
  344. function CopyToClipboard:boolean; virtual;
  345. function GetFromClipboard:boolean; virtual;
  346. procedure StartDnDDetection(Button: TMouseButton); virtual;
  347. property OwnerIsSource:boolean read FOwnerIsSource;
  348. property Registered: Boolean read FRegistered default False;
  349. property CHCopy: HCursor read FCHCopy write FCHCopy default DefaultCursor;
  350. property CHMove: HCursor read FCHMove write FCHMove default DefaultCursor;
  351. property CHLink: HCursor read FCHLink write FCHLink default DefaultCursor;
  352. property CHScrollCopy: HCursor read FCHScrollCopy write FCHScrollCopy default DefaultCursor;
  353. property CHScrollMove: HCursor read FCHScrollMove write FCHScrollMove default DefaultCursor;
  354. property CHScrollLink: HCursor read FCHScrollLink write FCHScrollLink default DefaultCursor;
  355. property DragDetectStatus: TDragDetectStatus read FDragDetectStatus;
  356. property AvailableDropEffects: Longint read FAvailableDropEffects;
  357. property InternalSource:TDragDrop read FInternalSource;
  358. published
  359. property AcceptOwnDnD:boolean read FAcceptOwnDnD write FAcceptOwnDnD;
  360. property AutoDetectDnD:boolean read FAutoDetectDnD write FAutoDetectDnD;
  361. property BringToFront:Boolean read FBTF write FBTF;
  362. property DragDetectDelta:byte read FDragDetectDelta write FDragDetectDelta default 10;
  363. property DragDropControl: TWinControl read FDragDropControl write SetDragDropControl;
  364. property RenderDataOn: TRenderDataOn read FRenderDataOn write FRenderDataOn default rdoDropSync;
  365. property ScrollDetectOptions: TScrollDetectOptions read FScrollDetectOptions
  366. write FScrollDetectOptions;
  367. property SourceCompatibility:TSrcCompatibilityCheckSet read FSrcCompatibilityCheck
  368. write FSrcCompatibilityCheck;
  369. property SourceEffects: TDropEffectSet read FSourceEffectsSet write SetSourceEffects;
  370. property TargetPopupMenu: boolean read FShowPopUpMenu write FShowPopUpMenu;
  371. property TargetEffects: TDropEffectSet read FTargetEffectsSet write SetTargetEffects;
  372. property OnAfterScrolling: TNotifyEvent read FOnAfterScrolling write FOnAfterScrolling;
  373. property OnBeforeScrolling: TOnBeforeScrolling read FOnBeforeScrolling write FOnBeforeScrolling;
  374. property OnDragDetect: TOnDragDetect read FOnDragDetect write FOnDragDetect;
  375. property OnDragEnter: TOnDragEnter read FOnDragEnter write FOnDragEnter;
  376. property OnDragLeave: TOnDragLeave read FOnDragLeave write FOnDragLeave;
  377. property OnDragOver: TOnDragOver read FOnDragOver write FOnDragOver;
  378. property OnDrop: TOnDrop read FOnDrop write FOnDrop;
  379. property OnQueryContinueDrag: TOnQueryContinueDrag read FOnQueryContinueDrag
  380. write FOnQueryContinueDrag;
  381. property OnGiveFeedback: TOnGiveFeedback read FOnGiveFeedback
  382. write FOnGiveFeedback;
  383. property OnProcessDropped: TOnProcessDropped read FOnProcessDropped write FOnProcessDropped;
  384. property OnMenuPopup:TOnMenuPopup read FOnMenuPopup write FOnMenuPopup;
  385. property OnMenuExecCmd:TOnMenuExecCmd read FOnMenuExecCmd write FOnMenuExecCmd;
  386. property OnMenuDestroy:TOnMenuDestroy read FOnMenuDestroy write FOnMenuDestroy;
  387. property OnMenuSucceeded:TOnProcessDropped read FOnMenuSucceeded write FOnMenuSucceeded;
  388. end;
  389. procedure Register;
  390. resourcestring
  391. MICopyStr = '&Copy Here';
  392. MIMoveStr = '&Move Here';
  393. MILinkStr = '&Shortcut(s) Create Here';
  394. MIAbortStr = '&Abort';
  395. implementation
  396. const CmdAbort = 0;
  397. CmdMove = 1;
  398. CmdCopy = 2;
  399. CmdLink = 3;
  400. CmdSeparator = 4;
  401. MinCustCmd = 10;
  402. var DDM_ProcessDropped:DWord; // Never change its value!!!
  403. MouseHookHandle:HHook;
  404. MouseHookDragDrop:TDragDrop;
  405. GInternalSource:TDragDrop;
  406. function MouseHookProc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT; stdcall;
  407. var MouseHookStruct:TMouseHookStruct;
  408. grfKeyState:Longint;
  409. begin
  410. Result:=CallNextHookEx(MouseHookHandle,Code,wParam,lParam);
  411. if assigned(MouseHookDragDrop)=false then
  412. begin
  413. UnHookWindowsHookEx(MouseHookHandle);
  414. MouseHookHandle:=0;
  415. exit;
  416. end;
  417. with MouseHookDragDrop do
  418. begin
  419. MouseHookStruct:=TMouseHookStruct(pointer(lparam)^);
  420. if ((FDragDetectStatus=ddsRight) and (wParam=WM_LBUTTONDOWN)) or
  421. ((FDragDetectStatus=ddsLeft) and (wParam=WM_RBUTTONDOWN)) then
  422. begin
  423. FPressedButton:=2;
  424. FDragDetectStatus:=ddsCancelled;
  425. if assigned(FOnDragDetect) then
  426. begin
  427. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then
  428. grfKeyState:=MK_SHIFT
  429. else grfKeyState:=0;
  430. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  431. grfKeyState:=grfKeyState or MK_CONTROL;
  432. FOnDragDetect(grfKeyState,
  433. FDragDropControl.ScreenToClient(FDragDetectStart),
  434. FDragDropControl.ScreenToClient(MouseHookStruct.pt),
  435. FDragDetectStatus);
  436. end;
  437. exit;
  438. end;
  439. if ((wParam=WM_LBUTTONDOWN) or (wParam=WM_RBUTTONDOWN)) and
  440. (FDragDetectStatus=ddsCancelled) then
  441. begin
  442. FPressedButton:=2;
  443. exit;
  444. end;
  445. if (FDragDetectStatus=ddsCancelled) and
  446. ((wParam=WM_LBUTTONUP) or (wParam=WM_RBUTTONUP)) then
  447. begin
  448. dec(FPressedButton);
  449. if FPressedButton<=0 then
  450. begin
  451. UnHookWindowsHookEx(MouseHookHandle);
  452. MouseHookHandle:=0;
  453. FDragDetectStatus:=ddsNone;
  454. if assigned(FOnDragDetect) then
  455. begin
  456. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then
  457. grfKeyState:=MK_SHIFT
  458. else grfKeyState:=0;
  459. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  460. grfKeyState:=grfKeyState or MK_CONTROL;
  461. FOnDragDetect(grfKeyState,
  462. FDragDropControl.ScreenToClient(FDragDetectStart),
  463. FDragDropControl.ScreenToClient(MouseHookStruct.pt),
  464. FDragDetectStatus);
  465. end;
  466. end;
  467. exit;
  468. end;
  469. if ((FDragDetectStatus=ddsRight) and (wParam=WM_RBUTTONUP)) or
  470. ((FDragDetectStatus=ddsLeft) and (wParam=WM_LBUTTONUP)) then
  471. begin
  472. UnHookWindowsHookEx(MouseHookHandle);
  473. MouseHookHandle:=0;
  474. FDragDetectStatus:=ddsNone;
  475. if assigned(FOnDragDetect) then
  476. begin
  477. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then
  478. grfKeyState:=MK_SHIFT
  479. else grfKeyState:=0;
  480. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  481. grfKeyState:=grfKeyState or MK_CONTROL;
  482. FOnDragDetect(grfKeyState,
  483. FDragDropControl.ScreenToClient(FDragDetectStart),
  484. FDragDropControl.ScreenToClient(MouseHookStruct.pt),
  485. FDragDetectStatus);
  486. end;
  487. exit;
  488. end;
  489. if ((abs(FDragDetectStart.X-MouseHookStruct.pt.x)>DragDetectDelta) or
  490. (abs(FDragDetectStart.Y-MouseHookStruct.pt.y)>DragDetectDelta)) and
  491. ((FDragDetectStatus=ddsRight) or (FDragDetectStatus=ddsLeft)) then
  492. begin
  493. FDragDetectStatus:=ddsDrag;
  494. UnHookWindowsHookEx(MouseHookHandle);
  495. MouseHookHandle:=0;
  496. if assigned(FOnDragDetect) then
  497. begin
  498. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then
  499. grfKeyState:=MK_SHIFT
  500. else grfKeyState:=0;
  501. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  502. grfKeyState:=grfKeyState or MK_CONTROL;
  503. FOnDragDetect(grfKeyState,
  504. FDragDropControl.ScreenToClient(FDragDetectStart),
  505. FDragDropControl.ScreenToClient(MouseHookStruct.pt),
  506. FDragDetectStatus);
  507. end;
  508. if (FDragDetectStatus<>ddsNone) then
  509. begin
  510. FDragDetectStatus:=ddsNone;
  511. if assigned(FOnDragDetect) then
  512. begin
  513. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then
  514. grfKeyState:=MK_SHIFT
  515. else grfKeyState:=0;
  516. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  517. grfKeyState:=grfKeyState or MK_CONTROL;
  518. FOnDragDetect(grfKeyState,
  519. FDragDropControl.ScreenToClient(FDragDetectStart),
  520. FDragDropControl.ScreenToClient(MouseHookStruct.pt),
  521. FDragDetectStatus);
  522. end;
  523. end;
  524. end;
  525. end;
  526. end;
  527. // TFormatEtcList --------------------------------------------------------------
  528. constructor TFormatEtcList.Create;
  529. begin
  530. inherited Create;
  531. FCount:=0;
  532. SetLength(FList, 0);
  533. end;
  534. destructor TFormatEtcList.Destroy;
  535. begin
  536. if (FCount>0) and (FList<>nil) then SetLength(FList, 0);
  537. inherited Destroy;
  538. end;
  539. function TFormatEtcList.Get(Index: Integer): TFormatEtc;
  540. begin
  541. if (Index>=FCount) or (FList=nil) then
  542. raise EListError.Create('Invalid item index')
  543. else Result:=FList[Index];
  544. end;
  545. procedure TFormatEtcList.Put(Index: Integer; Item: TFormatEtc);
  546. begin
  547. if (Index>=FCount) or (FList=nil) then
  548. raise EListError.Create('Invalid item index')
  549. else FList[Index]:=Item;
  550. end;
  551. function TFormatEtcList.Add(Item: TFormatEtc):integer;
  552. begin
  553. SetLength(FList, Succ(FCount));
  554. FList[FCount]:=Item;
  555. Result:=FCount;
  556. inc(FCount);
  557. end;
  558. procedure TFormatEtcList.Clear;
  559. begin
  560. SetLength(Flist, 0);
  561. FCount:=0;
  562. end;
  563. function TFormatEtcList.Clone:TFormatEtcList;
  564. var FEL:TFormatEtcList;
  565. begin
  566. FEL:=TFormatEtcList.Create;
  567. if FList<>nil then
  568. begin
  569. SetLength(FEL.FList, FCount);
  570. CopyMemory(FEL.FList,FList,FCount*SizeOf(TFormatEtc));
  571. FEL.FCount:=FCount;
  572. end;
  573. Result:=FEL;
  574. end;
  575. procedure TFormatEtcList.Delete(Index: Integer);
  576. var movecount:integer;
  577. begin
  578. if (Index>=FCount) or (FList=nil) then
  579. raise EListError.Create('Invalid item index')
  580. else
  581. begin
  582. movecount:=FCount-Index-1;
  583. System.move(FList[Index+1],FList[Index],movecount*sizeof(TFormatEtc));
  584. dec(FCount);
  585. SetLength(FList, FCount);
  586. end;
  587. end;
  588. // TDDInterfacedObject ---------------------------------------------------------
  589. function TDDInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
  590. begin
  591. Result:=inherited QueryInterface(IID,Obj);
  592. end;
  593. function TDDInterfacedObject._AddRef: Integer;
  594. begin
  595. Result:=inherited _AddRef;
  596. end;
  597. function TDDInterfacedObject._Release: Integer;
  598. begin
  599. Result:=inherited _Release;
  600. end;
  601. // TEnumFormatEtc --------------------------------------------------------------
  602. constructor TEnumFormatEtc.Create(FormatEtcList:TFormatEtcList);
  603. begin
  604. inherited Create;
  605. _AddRef;
  606. FFormatEtcList:=FormatEtcList;
  607. end;
  608. destructor TEnumFormatEtc.Destroy;
  609. begin
  610. if Assigned(FFormatEtcList) then FFormatEtcList.Free;
  611. inherited Destroy;
  612. end;
  613. function TEnumFormatEtc.Next(celt: Longint; out elt;
  614. pceltFetched: PLongint): HResult;
  615. var copycount:integer;
  616. begin
  617. Result:=S_False;
  618. if pceltFetched<>nil then pceltFetched^:=0;
  619. if (celt<=0) or (FFormatEtcList.Count=0) or (FIndex>=FFormatEtcList.Count) or
  620. ((pceltFetched=nil) and (celt<>1)) then exit;
  621. copycount:=FFormatEtcList.Count-FIndex;
  622. if celt<copycount then copycount:=celt;
  623. if pceltFetched<>nil then pceltFetched^:=copycount;
  624. CopyMemory(@TFormatEtc(elt),@TFormatEtc(FFormatEtcList.FList[FIndex]),
  625. copycount*sizeof(TFormatEtc));
  626. inc(FIndex,copycount);
  627. Result:=S_OK;
  628. end;
  629. function TEnumFormatEtc.Skip(celt: Longint): HResult;
  630. begin
  631. if (FIndex+celt<=FFormatEtcList.Count) then
  632. begin
  633. inc(FIndex,celt);
  634. Result:=S_Ok;
  635. end
  636. else Result:=S_False;
  637. end;
  638. function TEnumFormatEtc.Reset: HResult;
  639. begin
  640. FIndex:=0;
  641. Result:=S_OK;
  642. end;
  643. function TEnumFormatEtc.Clone(out Enum: IEnumFormatEtc): HResult;
  644. begin
  645. Result:=S_OK;
  646. try
  647. Enum:=TEnumFormatEtc.Create(FFormatEtcList);
  648. TEnumFormatEtc(Enum).FIndex := FIndex;
  649. except
  650. Result:=E_Fail;
  651. end;
  652. end;
  653. // TDataObject -----------------------------------------------------------------
  654. constructor TDataObject.Create;
  655. begin
  656. inherited Create;
  657. _AddRef;
  658. FFormatEtcList:=TFormatEtcList.Create;
  659. end;
  660. destructor TDataObject.Destroy;
  661. begin
  662. FFormatEtcList.Free;
  663. inherited Destroy;
  664. end;
  665. function TDataObject.GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium):
  666. HResult;
  667. var i:integer;
  668. Cursor:TCursor;
  669. begin
  670. try
  671. if FFormatEtcList.Count>0 then
  672. for i:=0 to FFormatEtcList.Count-1 do
  673. if (formatetcIn.tymed and FFormatEtcList.Items[i].tymed<>0) and
  674. ((FCheckLindex=false) or (FCheckLindex and
  675. (formatetcIn.lindex=FFormatEtcList.Items[i].lindex))) and
  676. ((FCheckdwAspect=false) or (FCheckdwAspect and
  677. (formatetcIn.dwAspect=FFormatEtcList.Items[i].dwAspect))) and
  678. (formatetcIn.cfFormat=FFormatEtcList.Items[i].cfFormat) then
  679. begin
  680. Cursor:=Screen.Cursor;
  681. try
  682. Screen.Cursor:=crHourglass;
  683. Result:=RenderData(formatetcIn,medium);
  684. finally
  685. Screen.Cursor:=Cursor;
  686. end;
  687. exit;
  688. end;
  689. Result:=DV_E_FormatEtc;
  690. except
  691. medium.HGlobal:=0;
  692. Result:=E_Fail;
  693. end;
  694. end;
  695. function TDataObject.GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium):
  696. HResult;
  697. begin
  698. Result:=E_NOTIMPL;
  699. end;
  700. function TDataObject.GetCanonicalFormatEtc(const formatetc: TFormatEtc;
  701. out formatetcOut: TFormatEtc): HResult;
  702. begin
  703. Result:=E_NOTIMPL;
  704. end;
  705. function TDataObject.QueryGetData(const formatetc: TFormatEtc): HResult;
  706. const DVError:array[0..3] of HResult=(DV_E_FORMATETC,DV_E_TYMED,DV_E_DVASPECT,DV_E_LINDEX);
  707. var i,j:integer;
  708. begin
  709. j:=0;
  710. if (FFormatEtcList.Count>0) and AllowData(FormatEtc) then
  711. for i:=0 to FFormatEtcList.Count-1 do
  712. if FormatEtc.cfFormat=FFormatEtcList.Items[i].cfFormat then
  713. begin
  714. if FormatEtc.tymed and FFormatEtcList.Items[i].tymed<>0 then
  715. begin
  716. if FormatEtc.dwAspect=FFormatEtcList.Items[i].dwAspect then
  717. begin
  718. if FormatEtc.lindex=FFormatEtcList.Items[i].lindex then
  719. begin
  720. Result:=S_OK;
  721. exit;
  722. end
  723. else if j<3 then j:=3;
  724. end
  725. else if j<2 then j:=2;
  726. end
  727. else if j<1 then j:=1;
  728. end;
  729. Result:=DVError[j];
  730. end;
  731. function TDataObject.AllowData(FormatEtc: TFormatEtc): Boolean;
  732. begin
  733. Result := True;
  734. end;
  735. function TDataObject.EnumFormatEtc(dwDirection: Longint; out enumFormatEtc:
  736. IEnumFormatEtc): HResult;
  737. begin
  738. Result:=E_Fail;
  739. if dwDirection=DATADIR_GET then
  740. begin
  741. EnumFormatEtc:=TEnumFormatEtc.Create(FFormatEtcList.Clone);
  742. Result:=S_OK;
  743. end
  744. else EnumFormatEtc:=nil;
  745. if EnumFormatEtc=nil then Result:=OLE_S_USEREG;
  746. end;
  747. function TDataObject.SetData(const formatetc: TFormatEtc; var medium: TStgMedium;
  748. fRelease: BOOL): HResult;
  749. var i:integer;
  750. AddData:boolean;
  751. begin
  752. Result:=E_Fail;
  753. if FRelease then exit;
  754. AddData:=true;
  755. if FFormatEtcList.Count>0 then
  756. for i:=0 to FFormatEtcList.Count-1 do
  757. if FFormatEtcList.Items[i].cfFormat=FormatEtc.cfFormat then
  758. begin
  759. AddData:=false;
  760. FFormatEtcList.Items[i]:=FormatEtc;
  761. end;
  762. if AddData then
  763. FFormatEtcList.Add(FormatEtc);
  764. end;
  765. function TDataObject.DAdvise(const formatetc: TFormatEtc; advf: Longint;
  766. const advSink: IAdviseSink; out dwConnection: Longint): HResult;
  767. begin
  768. Result:=E_NOTIMPL;
  769. end;
  770. function TDataObject.DUnadvise(dwConnection: longint): HResult; stdcall;
  771. begin
  772. Result:=E_NOTIMPL;
  773. end;
  774. function TDataObject.EnumDAdvise(out enumAdvise: IEnumStatData): HResult;
  775. begin
  776. Result:=OLE_E_AdviseNotSupported;
  777. end;
  778. // TDropSource methods ---------------------------------------------------------
  779. constructor TDropSource.Create(AOwner: TDragDrop);
  780. begin
  781. inherited Create;
  782. _AddRef;
  783. FOwner:=AOwner;
  784. end;
  785. destructor TDropSource.Destroy;
  786. begin
  787. inherited Destroy;
  788. end;
  789. function TDropSource.QueryContinueDrag(fEscapePressed: BOOL;
  790. grfKeyState: Longint): HResult; stdcall;
  791. // Determines whether a drag-and-drop operation should be continued, cancelled,
  792. // or completed. You do not call this method directly. The OLE DoDragDrop function
  793. // calls this method during a drag-and-drop operation.
  794. begin
  795. // Abort drag-and-drop?
  796. if (((grfKeyState and MK_LBUTTON)<>0) and
  797. ((grfKeyState and MK_RBUTTON)<>0)) or fEscapePressed then
  798. begin
  799. Result:=DRAGDROP_S_CANCEL;
  800. FOwner.FOwnerIsSource:=false;
  801. end
  802. // Finish drag-and-drop?
  803. else if (((grfKeyState and MK_LBUTTON)=0) and
  804. ((grfKeyState and MK_RBUTTON)=0)) then Result:=DRAGDROP_S_DROP
  805. else Result:=S_OK;
  806. if assigned(FOwner.FOnQueryContinueDrag) then
  807. FOwner.FOnQueryContinueDrag(fEscapePressed,grfKeyState,Result);
  808. end;
  809. function TDropSource.GiveFeedback(dwEffect: Longint): HResult; stdcall;
  810. // Enables a source application to give visual feedback to its end user
  811. // during a drag-and-drop operation by providing the DoDragDrop function
  812. // with an enumeration value specifying the visual effect.
  813. var HC: HCursor;
  814. begin
  815. if Assigned(FOwner.FOnGiveFeedback) then FOwner.FOnGiveFeedback(dwEffect,Result);
  816. if dwEffect and DROPEFFECT_SCROLL<>0 then
  817. begin
  818. if dwEffect and DROPEFFECT_LINK<>0 then HC:=FOwner.FCHScrollLink
  819. else if dwEffect and DROPEFFECT_Move<>0 then HC:=FOwner.FCHScrollMove
  820. else if dwEffect and DROPEFFECT_COPY<>0 then HC:=FOwner.FCHScrollCopy
  821. else HC:=DefaultCursor;
  822. end
  823. else if dwEffect and DROPEFFECT_LINK<>0 then HC:=FOwner.FCHLink
  824. else if dwEffect and DROPEFFECT_Move<>0 then HC:=FOwner.FCHMove
  825. else if dwEffect and DROPEFFECT_COPY<>0 then HC:=FOwner.FCHCopy
  826. else HC:=DefaultCursor;
  827. if HC=DefaultCursor then Result:=DRAGDROP_S_USEDEFAULTCURSORS
  828. else
  829. begin
  830. Result:=S_Ok;
  831. Windows.SetCursor(HC);
  832. end;
  833. end;
  834. // TDropTarget interface -------------------------------------------------------
  835. constructor TDropTarget.Create(AOwner: TDragDrop);
  836. begin
  837. inherited Create;
  838. FOwner:=AOwner;
  839. _AddRef;
  840. HorzStartTimer:=TTimer.Create(FOwner);
  841. HorzStartTimer.Enabled:=false;
  842. HorzStartTimer.OnTimer:=OnStartTimer;
  843. HorzScrollTimer:=TTimer.Create(FOwner);
  844. HorzScrollTimer.Enabled:=false;
  845. HorzScrollTimer.OnTimer:=OnScrollTimer;
  846. VertStartTimer:=TTimer.Create(FOwner);
  847. VertStartTimer.Enabled:=false;
  848. VertStartTimer.OnTimer:=OnStartTimer;
  849. VertScrollTimer:=TTimer.Create(FOwner);
  850. VertScrollTimer.Enabled:=false;
  851. VertScrollTimer.OnTimer:=OnScrollTimer;
  852. FVScrollCode:=0;
  853. FHScrollCode:=0;
  854. end;
  855. destructor TDropTarget.Destroy;
  856. begin
  857. HorzStartTimer.Free;
  858. HorzScrollTimer.Free;
  859. VertStartTimer.Free;
  860. VertScrollTimer.Free;
  861. inherited Destroy;
  862. end;
  863. procedure TDropTarget.InitScroll(VerticalScroll:boolean; ScrollCode:integer);
  864. begin
  865. TermScroll(VerticalScroll);
  866. if VerticalScroll then
  867. begin
  868. VertStartTimer.Interval:=FOwner.FScrollDetectOptions.FStartDelay;
  869. VertStartTimer.Enabled:=true;
  870. FVScrollCode:=ScrollCode;
  871. end
  872. else
  873. begin
  874. HorzStartTimer.Interval:=FOwner.FScrollDetectOptions.FStartDelay;
  875. HorzStartTimer.Enabled:=true;
  876. FHScrollCode:=ScrollCode;
  877. end;
  878. end;
  879. procedure TDropTarget.TermScroll(VerticalScroll:boolean);
  880. begin
  881. if VerticalScroll then
  882. begin
  883. VertStartTimer.Enabled:=false;
  884. if VertScrollTimer.Enabled then
  885. sendmessage(FOwner.DragDropControl.handle,WM_VScroll,SB_ENDSCROLL,0);
  886. VertScrollTimer.Enabled:=false;
  887. FVScrollCode:=0;
  888. end
  889. else
  890. begin
  891. HorzStartTimer.Enabled:=false;
  892. if HorzScrollTimer.Enabled then
  893. sendmessage(FOwner.DragDropControl.handle,WM_HScroll,SB_ENDSCROLL,0);
  894. HorzScrollTimer.Enabled:=false;
  895. FHScrollCode:=0;
  896. end;
  897. end;
  898. procedure TDropTarget.DetermineScrollDir(VertScrolling:boolean;
  899. var ScrollCode:integer);
  900. var p1m,p1r,p2m,p2r:integer;
  901. ptmc:TPoint;
  902. SCROLLINFO:TSCROLLINFO;
  903. begin
  904. GetCursorPos(ptmc);
  905. ptmc:=FOwner.DragDropControl.ScreenToClient(ptmc);
  906. if VertScrolling then
  907. begin
  908. // Checking vertical scroll areas ...
  909. // If the vertical scroll areas intersect, we don't allow scrolling
  910. p1m:=FOwner.FScrollDetectOptions.AreaTop.Margin;
  911. p1r:=p1m+FOwner.ScrollDetectOptions.AreaTop.Range;
  912. p2m:=FOwner.DragDropControl.ClientHeight-1-
  913. FOwner.ScrollDetectOptions.AreaBottom.Margin;
  914. p2r:=p2m-FOwner.ScrollDetectOptions.AreaBottom.Range;
  915. if (p1r<p2r) then
  916. begin
  917. if (p1m<=ptmc.y) and (p1r>=ptmc.y) then ScrollCode:=1
  918. else if (p2m>=ptmc.y) and (p2r<=ptmc.y) then ScrollCode:=2
  919. else ScrollCode:=0;
  920. if ScrollCode>0 then
  921. begin
  922. ScrollInfo.cbSize := Sizeof(ScrollInfo);
  923. ScrollInfo.FMask:=SIF_PAGE or SIF_POS or SIF_RANGE;
  924. if GetScrollInfo(FOwner.DragDropControl.Handle,SB_VERT,
  925. ScrollInfo) then
  926. begin
  927. if ScrollInfo.nPage>0 then dec(ScrollInfo.nPage);
  928. if ((ScrollCode=1) and (ScrollInfo.nPos<=ScrollInfo.nMin)) or
  929. ((ScrollCode=2) and
  930. (ScrollInfo.nPos>=ScrollInfo.nMax-integer(ScrollInfo.nPage))) then
  931. ScrollCode:=0;
  932. end
  933. else ScrollCode:=0;
  934. end;
  935. end
  936. else ScrollCode:=0;
  937. end
  938. else
  939. begin
  940. // Checking horizontal scroll areas ...
  941. // If the horizontal scroll areas intersect, we don't allow scrolling
  942. p1m:=FOwner.FScrollDetectOptions.AreaLeft.Margin;
  943. p1r:=p1m+FOwner.ScrollDetectOptions.AreaLeft.Range;
  944. p2m:=FOwner.DragDropControl.ClientWidth-1-
  945. FOwner.ScrollDetectOptions.AreaRight.Margin;
  946. p2r:=p2m-FOwner.ScrollDetectOptions.AreaRight.Range;
  947. if (p1r<p2r) then
  948. begin
  949. if (p1m<=ptmc.x) and (p1r>=ptmc.x) then ScrollCode:=1
  950. else if (p2m>=ptmc.x) and (p2r<=ptmc.x) then ScrollCode:=2
  951. else ScrollCode:=0;
  952. if ScrollCode>0 then
  953. begin
  954. ScrollInfo.cbSize := Sizeof(ScrollInfo);
  955. ScrollInfo.FMask:=SIF_PAGE or SIF_POS or SIF_RANGE;
  956. if GetScrollInfo(FOwner.DragDropControl.Handle,SB_Horz,
  957. ScrollInfo) then
  958. begin
  959. if ScrollInfo.nPage>0 then dec(ScrollInfo.nPage);
  960. if ((ScrollCode=1) and (ScrollInfo.nPos<=ScrollInfo.nMin)) or
  961. ((ScrollCode=2) and
  962. (ScrollInfo.nPos>=ScrollInfo.nMax-integer(ScrollInfo.nPage))) then
  963. ScrollCode:=0;
  964. end
  965. else ScrollCode:=0;
  966. end;
  967. end
  968. else ScrollCode:=0;
  969. end;
  970. end;
  971. procedure TDropTarget.OnStartTimer(Sender: TObject);
  972. begin
  973. if Sender=HorzStartTimer then
  974. begin
  975. HorzStartTimer.Enabled:=false;
  976. HorzScrollTimer.Interval:=FOwner.FScrollDetectOptions.FScrollDelay;
  977. OnScrollTimer(HorzScrollTimer);
  978. HorzScrollTimer.Enabled:=true;
  979. end
  980. else
  981. begin
  982. VertStartTimer.Enabled:=false;
  983. VertScrollTimer.Interval:=FOwner.FScrollDetectOptions.FScrollDelay;
  984. OnScrollTimer(VertScrollTimer);
  985. VertScrollTimer.Enabled:=true;
  986. end;
  987. end;
  988. procedure TDropTarget.OnScrollTimer(Sender: TObject);
  989. var ScrollPage:boolean;
  990. pt:TPoint;
  991. Interval:TScrollInterval;
  992. ScrollCode,SCWParam:integer;
  993. begin
  994. Interval:=FOwner.FScrollDetectOptions.FScrollDelay;
  995. if Sender=VertScrollTimer then
  996. begin
  997. if FOwner.FScrollDetectOptions.FVertScrolling then
  998. begin
  999. DetermineScrollDir(true,ScrollCode);
  1000. if ScrollCode>0 then
  1001. begin
  1002. if ((VertStartTimer.Enabled=false) and (VertScrollTimer.Enabled=false)) or
  1003. (FVScrollCode<>ScrollCode) then InitScroll(true,ScrollCode)
  1004. else
  1005. begin
  1006. ScrollPage:=FOwner.FScrollDetectOptions.FVertPageScroll;
  1007. if assigned(FOwner.FOnBeforeScrolling) then
  1008. begin
  1009. GetCursorPos(pt);
  1010. pt:=FOwner.DragDropControl.ScreenToClient(pt);
  1011. if FVScrollCode=1 then FOwner.FOnBeforeScrolling(FOwner, pt,
  1012. Interval, sdUp, ScrollPage)
  1013. else FOwner.FOnBeforeScrolling(FOwner, pt, Interval, sdDown,
  1014. ScrollPage);
  1015. end;
  1016. if ScrollPage then
  1017. begin
  1018. if FVScrollCode=1 then SCWParam:=SB_PAGEUP
  1019. else SCWParam:=SB_PAGEDOWN;
  1020. end
  1021. else
  1022. begin
  1023. if FVScrollCode=1 then SCWParam:=SB_LINEUP
  1024. else SCWParam:=SB_LINEDOWN;
  1025. end;
  1026. sendmessage(FOwner.DragDropControl.handle,WM_VScroll,SCWParam,0);
  1027. if assigned(FOwner.FOnAfterScrolling) then
  1028. FOwner.FOnAfterScrolling(FOwner);
  1029. VertScrollTimer.Interval:=Interval;
  1030. end;
  1031. end
  1032. else if FVScrollCode<>0 then TermScroll(true);
  1033. end
  1034. else if FVScrollCode<>0 then TermScroll(true);
  1035. end
  1036. else
  1037. begin
  1038. if FOwner.FScrollDetectOptions.FHorzScrolling then
  1039. begin
  1040. DetermineScrollDir(false,ScrollCode);
  1041. if ScrollCode>0 then
  1042. begin
  1043. if ((HorzStartTimer.Enabled=false) and (HorzScrollTimer.Enabled=false)) or
  1044. (FHScrollCode<>ScrollCode) then InitScroll(false,ScrollCode)
  1045. else
  1046. begin
  1047. ScrollPage:=FOwner.FScrollDetectOptions.FHorzPageScroll;
  1048. if assigned(FOwner.FOnBeforeScrolling) then
  1049. begin
  1050. GetCursorPos(pt);
  1051. pt:=FOwner.DragDropControl.ScreenToClient(pt);
  1052. if FHScrollCode=1 then FOwner.FOnBeforeScrolling(FOwner, pt,
  1053. Interval, sdLeft, ScrollPage)
  1054. else FOwner.FOnBeforeScrolling(FOwner, pt, Interval, sdRight,
  1055. ScrollPage);
  1056. end;
  1057. if ScrollPage then
  1058. begin
  1059. if FHScrollCode=1 then SCWParam:=SB_PAGELEFT
  1060. else SCWParam:=SB_PAGERIGHT;
  1061. end
  1062. else
  1063. begin
  1064. if FHScrollCode=1 then SCWParam:=SB_LINELEFT
  1065. else SCWParam:=SB_LINERIGHT;
  1066. end;
  1067. sendmessage(FOwner.DragDropControl.handle,WM_HScroll,SCWParam,0);
  1068. HorzScrollTimer.Interval:=Interval;
  1069. end;
  1070. end
  1071. else if FHScrollCode<>0 then TermScroll(false);
  1072. end
  1073. else if FHScrollCode<>0 then TermScroll(false);
  1074. end;
  1075. end;
  1076. procedure TDropTarget.SuggestDropEffect(grfKeyState: Longint; var dwEffect: longint);
  1077. begin
  1078. if (FOwner.FAcceptOwnDnD=false) and
  1079. (FOwner.FOwnerIsSource) then dwEffect:=DropEffect_None
  1080. else if (grfKeyState and MK_CONTROL=0) and (grfKeyState and MK_SHIFT<>0) and
  1081. (FOwner.FTargetEffects and DropEffect_Move<>0) then
  1082. dwEffect:=DropEffect_Move
  1083. else if (grfKeyState and MK_CONTROL<>0) and
  1084. (grfKeyState and MK_SHIFT<>0) and
  1085. (FOwner.FTargetEffects and DropEffect_Link<>0) then
  1086. dwEffect:=DropEffect_Link
  1087. else if (deCopy in FOwner.FTargetEffectsSet) and
  1088. (dwEffect and DropEffect_Copy<>0) then
  1089. dwEffect:=DropEffect_Copy
  1090. else if (deMove in FOwner.FTargetEffectsSet) and
  1091. (dwEffect and DropEffect_Move<>0) then
  1092. dwEffect:=DropEffect_Move
  1093. else if (deLink in FOwner.FTargetEffectsSet) and
  1094. (dwEffect and DropEffect_Link<>0) then
  1095. dwEffect:=DropEffect_Link
  1096. else dwEffect:=DropEffect_None;
  1097. if FOwner.FTargetScrolling<>0 then dwEffect:=dwEffect or integer(DropEffect_Scroll);
  1098. end;
  1099. procedure TDropTarget.AcceptDataObject(DataObj: IDataObject; var Accept:boolean);
  1100. begin
  1101. Accept:=true;
  1102. end;
  1103. function TDropTarget.DragEnter(const dataObj: IDataObject; grfKeyState: Longint;
  1104. pt: TPoint; var dwEffect: Longint): HResult;
  1105. // Is called if the d&d-mouse cursor moves ON (one call only) the TargeTWinControl. Here,
  1106. // you influence if a drop can be accepted and the drop's effect if accepted.
  1107. begin
  1108. TDragDrop(FOwner).FInternalSource:=GInternalSource;
  1109. FOwner.FAvailableDropEffects:=dwEffect;
  1110. FOwner.FContextMenu:=grfKeyState and mk_rbutton<>0;
  1111. if (FOwner.RenderDataOn=rdoEnter) or (FOwner.RenderDataOn=rdoEnterAndDropSync) or
  1112. (FOwner.RenderDataOn=rdoEnterAndDropAsync) then
  1113. RenderDropped(DataObj, grfKeyState, pt, dwEffect);
  1114. SuggestDropEffect(grfKeyState,dwEffect);
  1115. AcceptDataObject(DataObj, FAccept);
  1116. if Assigned(FOwner.OnDragEnter) then
  1117. FOwner.OnDragEnter(DataObj, grfKeyState,
  1118. FOwner.FDragDropControl.ScreenToClient(pt), dwEffect, FAccept);
  1119. if ((FOwner.FAcceptOwnDnD=false) and (FOwner.FOwnerIsSource)) or
  1120. (FAccept=false) then dwEffect:=DropEffect_None;
  1121. Result:= NOERROR;
  1122. end;
  1123. function TDropTarget.DragOver(grfKeyState: Longint; pt: TPoint;
  1124. var dwEffect: Longint): HResult;
  1125. // Is called if the mouse cursor moves OVER (called on every mouse move) the
  1126. // TargeTWinControl. Even here may you influence if a drop can be accepted and the
  1127. // drop's effect if accepted. Because this function is very often called YOUR
  1128. // function should be very efficient programmed.
  1129. var ScrollCode:integer;
  1130. begin
  1131. if FOwner.FScrollDetectOptions.FVertScrolling then
  1132. begin
  1133. DetermineScrollDir(true,ScrollCode);
  1134. if ScrollCode>0 then
  1135. begin
  1136. if ((VertStartTimer.Enabled=false) and (VertScrollTimer.Enabled=false)) or
  1137. (FVScrollCode<>ScrollCode) then InitScroll(true,ScrollCode);
  1138. end
  1139. else if FVScrollCode<>0 then TermScroll(true);
  1140. end
  1141. else if FVScrollCode<>0 then TermScroll(true);
  1142. if FOwner.FScrollDetectOptions.FHorzScrolling then
  1143. begin
  1144. DetermineScrollDir(false,ScrollCode);
  1145. if ScrollCode>0 then
  1146. begin
  1147. if ((HorzStartTimer.Enabled=false) and (HorzScrollTimer.Enabled=false)) or
  1148. (FHScrollCode<>ScrollCode) then InitScroll(false,ScrollCode);
  1149. end
  1150. else if FHScrollCode<>0 then TermScroll(false);
  1151. end
  1152. else if FHScrollCode<>0 then TermScroll(false);
  1153. if FAccept=false then dwEffect:=DropEffect_None;
  1154. SuggestDropEffect(grfKeyState,dwEffect);
  1155. if Assigned(FOwner.OnDragOver) then
  1156. FOwner.OnDragOver(grfKeyState, FOwner.FDragDropControl.ScreenToClient(pt),
  1157. dwEffect);
  1158. if ((FOwner.FAcceptOwnDnD=false) and (FOwner.FOwnerIsSource)) or
  1159. (FAccept=false) then dwEffect:=DropEffect_None;
  1160. Result:=NOERROR;
  1161. end;
  1162. function TDropTarget.DragLeave: HResult;
  1163. // Removes target feedback and releases the data object.
  1164. begin
  1165. TDragDrop(FOwner).FInternalSource:=nil;
  1166. if Assigned(FOwner.OnDragLeave) then FOwner.OnDragLeave;
  1167. FOwner.FAvailableDropEffects:=0;
  1168. Result:=NOERROR;
  1169. TermScroll(true);
  1170. TermScroll(false);
  1171. end;
  1172. function TDropTarget.Drop(const DataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  1173. var dwEffect: Longint): HResult;
  1174. // Instructs drop target to handle the datas which are dropped on it.
  1175. var Menu:HMenu;
  1176. Cmd:Cardinal;
  1177. mcursor:TCursor;
  1178. KeyState:integer;
  1179. function BuildMenuItemInfo(ACaption:string; ShowDefault:boolean;
  1180. ACommand:UInt; ASeparator:boolean):TMenuItemInfo;
  1181. begin
  1182. with Result do
  1183. begin
  1184. // cbSize:=SizeOf(MenuItemInfo);
  1185. cbSize:=44; //Required for Windows95
  1186. fMask:=MIIM_ID or MIIM_STATE or MIIM_TYPE;
  1187. if ASeparator then fType:=MFT_SEPARATOR
  1188. else fType:=MFT_STRING;
  1189. if ShowDefault then fState:=MFS_ENABLED or MFS_Default
  1190. else fState:=MFS_ENABLED;
  1191. wID:=ACommand;
  1192. hSubMenu:=0;
  1193. hbmpChecked:=0;
  1194. hbmpUnchecked:=0;
  1195. dwTypeData:=PChar(ACaption);
  1196. end;
  1197. end;
  1198. begin
  1199. Result:=E_Fail;
  1200. if FOwner.FContextMenu then KeyState:=grfKeyState or MK_RButton
  1201. else KeyState:=grfKeyState or MK_LButton;
  1202. if FAccept then SuggestDropEffect(KeyState,dwEffect)
  1203. else dwEffect:=DropEffect_None;
  1204. if assigned(FOwner.OnDragOver) then
  1205. FOwner.OnDragOver(KeyState, FOwner.FDragDropControl.ScreenToClient(pt),
  1206. dwEffect);
  1207. if ((FOwner.FAcceptOwnDnD=false) and (FOwner.FOwnerIsSource)) or
  1208. (FAccept=false) then dwEffect:=DropEffect_None;
  1209. TermScroll(true);
  1210. TermScroll(false);
  1211. if (FOwner.DropHandler(DataObj, KeyState, pt, dwEffect)=false) then
  1212. begin
  1213. // Show popup menu?
  1214. if FOwner.FContextMenu and FOwner.FShowPopupMenu and (dwEffect<>DropEffect_None) then
  1215. begin
  1216. Menu:=CreatePopupMenu;
  1217. if (deMove in FOwner.FTargetEffectsSet) and
  1218. (FOwner.FAvailableDropEffects and DropEffect_Move<>0) then
  1219. InsertMenuItem(Menu, DWORD(-1), true,
  1220. BuildMenuItemInfo(MIMoveStr, dwEffect and DropEffect_Move<>0,
  1221. CmdMove, false));
  1222. if (deCopy in FOwner.FTargetEffectsSet) and
  1223. (FOwner.FAvailableDropEffects and DropEffect_Copy<>0) then
  1224. InsertMenuItem(Menu, DWORD(-1), true,
  1225. BuildMenuItemInfo(MICopyStr, dwEffect and DropEffect_Copy<>0,
  1226. CmdCopy, false));
  1227. if (deLink in FOwner.FTargetEffectsSet) and
  1228. (FOwner.FAvailableDropEffects and DropEffect_Link<>0) then
  1229. InsertMenuItem(Menu, DWORD(-1), true,
  1230. BuildMenuItemInfo(MILinkStr, dwEffect and DropEffect_Link<>0,
  1231. CmdLink, false));
  1232. InsertMenuItem(Menu, DWORD(-1), true,
  1233. BuildMenuItemInfo('-', false, CmdSeparator, true));
  1234. InsertMenuItem(Menu, DWORD(-1), true,
  1235. BuildMenuItemInfo(MIAbortStr, false, CmdAbort, false));
  1236. // Add custom-menuitems ...
  1237. FOwner.DoMenuPopup(self, Menu, DataObj, MinCustCmd, KeyState, pt);
  1238. dwEffect:=DROPEFFECT_None;
  1239. Cmd:=Cardinal(TrackPopupMenuEx(Menu, TPM_LEFTALIGN or TPM_RIGHTBUTTON or TPM_RETURNCMD,
  1240. pt.x, pt.y, FOwner.DragDropControl.Handle, nil));
  1241. case Cmd of
  1242. CmdMove: dwEffect:=DROPEFFECT_Move;
  1243. CmdCopy: dwEffect:=DROPEFFECT_Copy;
  1244. CmdLink: dwEffect:=DROPEFFECT_Link;
  1245. CmdSeparator, CmdAbort:
  1246. dwEffect:=DROPEFFECT_None;
  1247. else // custom-menuitem was selected ...
  1248. begin
  1249. dwEffect:=DROPEFFECT_None;
  1250. if FOwner.DoMenuExecCmd(self, Menu, DataObj, Cmd, dwEffect) and
  1251. assigned(FOwner.FOnMenuSucceeded) then
  1252. FOwner.FOnMenuSucceeded(self, KeyState,
  1253. FOwner.FDragDropControl.ScreenToClient(pt), dwEffect);
  1254. end;
  1255. end;
  1256. FOwner.DoMenuDestroy(Self, Menu);
  1257. DestroyMenu(Menu);
  1258. end;
  1259. if assigned(FOwner.OnDrop) then
  1260. FOwner.OnDrop(DataObj, KeyState,
  1261. FOwner.FDragDropControl.ScreenToClient(pt), dwEffect);
  1262. if dwEffect<>DROPEFFECT_None then
  1263. begin
  1264. if FOwner.FBTF Then
  1265. SetForegroundWindow((FOwner.Owner As TWinControl).Handle);
  1266. TDragDrop(FOwner).FdwEffect:=dwEffect;
  1267. TDragDrop(FOwner).FgrfKeyState:=KeyState;
  1268. TDragDrop(FOwner).Fpt:=pt;
  1269. if (FOwner.RenderDataOn=rdoDropAsync) or
  1270. (FOwner.RenderDataOn=rdoEnterAndDropAsync) then
  1271. begin
  1272. TDragDrop(FOwner).FDataObj:=DataObj;
  1273. DataObj._AddRef;
  1274. end
  1275. else if (FOwner.RenderDataOn=rdoDropSync) or
  1276. (FOwner.RenderDataOn=rdoEnterAndDropSync) then
  1277. begin
  1278. // Set hourglass-cursor
  1279. mcursor:=Screen.Cursor;
  1280. Screen.Cursor:=crHourGlass;
  1281. try
  1282. RenderDropped(DataObj, KeyState, pt, dwEffect);
  1283. finally
  1284. // Set old cursor
  1285. Screen.Cursor:=mcursor;
  1286. end;
  1287. end;
  1288. PostMessage(FOwner.DragDropControl.Handle,DDM_ProcessDropped,0,0);
  1289. Result:=NOERROR;
  1290. end
  1291. else TDragDrop(FOwner).FInternalSource:=nil;
  1292. end
  1293. else
  1294. begin
  1295. TDragDrop(FOwner).FInternalSource:=nil;
  1296. if assigned(FOwner.FOnDropHandlerSucceeded) then
  1297. FOwner.FOnDropHandlerSucceeded(self, KeyState,
  1298. FOwner.FDragDropControl.ScreenToClient(pt), dwEffect);
  1299. end;
  1300. end;
  1301. procedure TDropTarget.RenderDropped(DataObj: IDataObject; grfKeyState: Longint;
  1302. pt: TPoint; var dwEffect: longint);
  1303. begin
  1304. // override, if you need ...
  1305. end;
  1306. // TScrollDetectArea methods ---------------------------------------------------
  1307. constructor TScrollDetectArea.Create(Control: TPersistent);
  1308. begin
  1309. inherited Create;
  1310. FControl:=Control;
  1311. end;
  1312. procedure TScrollDetectArea.AssignTo(Dest: TPersistent);
  1313. begin
  1314. if Dest is TScrollDetectArea then
  1315. with TScrollDetectArea(Dest) do
  1316. begin
  1317. FMargin:=Self.FMargin;
  1318. FRange:=Self.FRange;
  1319. Change;
  1320. end
  1321. else inherited AssignTo(Dest);
  1322. end;
  1323. procedure TScrollDetectArea.SetValue(Index: Integer;
  1324. Value: word);
  1325. begin
  1326. case Index of
  1327. 0: if Value<>FMargin then
  1328. begin
  1329. FMargin:=Value;
  1330. Change;
  1331. end;
  1332. 1: if Value<>FRange then
  1333. begin
  1334. FRange:=Value;
  1335. Change;
  1336. end;
  1337. end;
  1338. end;
  1339. procedure TScrollDetectArea.Change;
  1340. begin
  1341. if Assigned(FOnChange) then FOnChange(Self);
  1342. end;
  1343. // TScrollDetectOptions methods -------------------------------------------------
  1344. constructor TScrollDetectOptions.Create(Control: TDragDrop);
  1345. begin
  1346. inherited Create;
  1347. FControl:=Control;
  1348. FScrollDelay:=100;
  1349. FStartDelay:=750;
  1350. FLeft:=TScrollDetectArea.Create(self);
  1351. FLeft.Margin:=0;
  1352. FLeft.Range:=10;
  1353. FLeft.OnChange:=FOnChange;
  1354. FTop:=TScrollDetectArea.Create(self);
  1355. FTop.Margin:=0;
  1356. FTop.Range:=10;
  1357. FTop.OnChange:=FOnChange;
  1358. FRight:=TScrollDetectArea.Create(self);
  1359. FRight.Margin:=0;
  1360. FRight.Range:=10;
  1361. FRight.OnChange:=FOnChange;
  1362. FBottom:=TScrollDetectArea.Create(self);
  1363. FBottom.Margin:=0;
  1364. FBottom.Range:=10;
  1365. FBottom.OnChange:=FOnChange;
  1366. FHorzScrolling:=false;
  1367. FVertScrolling:=false;
  1368. FHorzPageScroll:=false;
  1369. FVertPageScroll:=false;
  1370. end;
  1371. destructor TScrollDetectOptions.Destroy;
  1372. begin
  1373. FLeft.Free;
  1374. FTop.Free;
  1375. FRight.Free;
  1376. FBottom.Free;
  1377. inherited Destroy;
  1378. end;
  1379. procedure TScrollDetectOptions.AssignTo(Dest: TPersistent);
  1380. begin
  1381. if Dest is TScrollDetectOptions then
  1382. with TScrollDetectOptions(Dest) do
  1383. begin
  1384. FScrollDelay:=Self.FScrollDelay;
  1385. FStartDelay:=Self.FStartDelay;
  1386. FLeft.AssignTo(Self.FLeft);
  1387. FTop.AssignTo(Self.FTop);
  1388. FRight.AssignTo(Self.FRight);
  1389. FBottom.AssignTo(Self.FBottom);
  1390. Change;
  1391. end
  1392. else inherited AssignTo(Dest);
  1393. end;
  1394. procedure TScrollDetectOptions.SetValue(index:integer; Value: TScrollInterval);
  1395. begin
  1396. if (Index=0) and (Value<>FScrollDelay) then
  1397. begin
  1398. FScrollDelay:=Value;
  1399. Change;
  1400. end;
  1401. if (Index=1) and (Value<>FStartDelay) then
  1402. begin
  1403. FStartDelay:=Value;
  1404. Change;
  1405. end;
  1406. end;
  1407. procedure TScrollDetectOptions.Change;
  1408. begin
  1409. if Assigned(FOnChange) then FOnChange(Self);
  1410. end;
  1411. // TDragDrop control ------------------------------------------------------
  1412. constructor TDragDrop.Create(AOwner: TComponent);
  1413. begin
  1414. inherited Create(AOwner);
  1415. FDropTarget:=TDropTarget.Create(Self);
  1416. FRegistered:=False;
  1417. FDragDropControl:=nil;
  1418. FBTF:=False;
  1419. FAcceptOwnDnD:=false;
  1420. FShowPopupMenu:=true;
  1421. FDragDetectDelta:=10;
  1422. FDragDetectStatus:=ddsNone;
  1423. FRenderDataOn:=rdoDropSync;
  1424. FCHCopy:=DefaultCursor;
  1425. FCHMove:=DefaultCursor;
  1426. FCHLink:=DefaultCursor;
  1427. FCHScrollCopy:=DefaultCursor;
  1428. FCHScrollMove:=DefaultCursor;
  1429. FCHScrollLink:=DefaultCursor;
  1430. FMessageHooked:=false;
  1431. FAvailableDropEffects:=0;
  1432. FTargetScrolling:=0;
  1433. FSrcCompatibilityCheck:=[CheckLindex, CheckdwAspect];
  1434. FScrollDetectOptions:=TScrollDetectOptions.Create(Self);
  1435. FInternalSource:=nil;
  1436. end;
  1437. destructor TDragDrop.Destroy;
  1438. begin
  1439. UnregisterTarget;
  1440. UnhookMessageHandler(true);
  1441. FDropTarget._Release;
  1442. FDropTarget:=nil;
  1443. FDragDropControl:=nil;
  1444. FScrollDetectOptions.Free;
  1445. inherited Destroy;
  1446. end;
  1447. procedure TDragDrop.WndMethod(var Msg: TMessage); // message-hook to receive DDM_ProcessDropped
  1448. var mcursor:TCursor;
  1449. begin
  1450. with Msg do
  1451. begin
  1452. Result:=CallWindowProc(OldWndProc, DragDropControl.Handle, Msg, wParam, LParam);
  1453. if (Msg=DDM_ProcessDropped) then
  1454. begin
  1455. if (RenderDataOn=rdoDropAsync) or (RenderDataOn=rdoEnterAndDropAsync) then
  1456. begin
  1457. // Set hourglass-cursor
  1458. mcursor:=Screen.Cursor;
  1459. Screen.Cursor:=crHourGlass;
  1460. try
  1461. FDropTarget.RenderDropped(FDataObj, FgrfKeyState, Fpt, FdwEffect);
  1462. FDataObj._Release;
  1463. finally
  1464. // Set old cursor
  1465. Screen.Cursor:=mcursor;
  1466. end;
  1467. end;
  1468. if assigned(FOnProcessDropped) then
  1469. FOnProcessDropped(self, FgrfKeyState,
  1470. FDragDropControl.ScreenToClient(Fpt), FdwEffect);
  1471. FAvailableDropEffects:=0;
  1472. FInternalSource:=nil;
  1473. end;
  1474. case Msg of
  1475. WM_Destroy:
  1476. begin
  1477. if FRegistered then
  1478. begin
  1479. CoLockObjectExternal(FDropTarget, false, false);
  1480. if (FDragDropControl.HandleAllocated=false) or
  1481. (FDragDropControl.HandleAllocated and
  1482. (RevokeDragDrop(FDragDropControl.Handle)=S_OK)) then
  1483. FRegistered:=false;
  1484. end;
  1485. FMessageHooked:=false;
  1486. end;
  1487. WM_LBUTTONDOWN, WM_RBUTTONDOWN:
  1488. begin
  1489. if FAutoDetectDnD and (FDragDetectStatus=ddsNone) and
  1490. (FSourceEffects<>0) then
  1491. begin
  1492. if Msg=WM_LBUTTONDOWN then FDragDetectStatus:=ddsLeft
  1493. else FDragDetectStatus:=ddsRight;
  1494. GetCursorPos(FDragDetectStart);
  1495. if assigned(FOnDragDetect) then
  1496. FOnDragDetect(wparam,
  1497. FDragDropControl.ScreenToClient(FDragDetectStart),
  1498. FDragDropControl.ScreenToClient(FDragDetectStart),
  1499. FDragDetectStatus);
  1500. if (MouseHookHandle<>0) then
  1501. begin // MouseHookProc is used by another component ...
  1502. UnHookWindowsHookEx(MouseHookHandle);
  1503. MouseHookHandle:=0;
  1504. if assigned(MouseHookDragDrop) then
  1505. begin
  1506. MouseHookDragDrop.FDragDetectStatus:=ddsNone;
  1507. if assigned(MouseHookDragDrop.FOnDragDetect) then
  1508. MouseHookDragDrop.FOnDragDetect(wparam,
  1509. MouseHookDragDrop.FDragDropControl.ScreenToClient(
  1510. MouseHookDragDrop.FDragDetectStart),
  1511. MouseHookDragDrop.FDragDropControl.ScreenToClient(
  1512. FDragDetectStart),
  1513. MouseHookDragDrop.FDragDetectStatus);
  1514. end;
  1515. end;
  1516. MouseHookDragDrop:=self;
  1517. MouseHookHandle:=SetWindowsHookEx(WH_MOUSE,MouseHookProc,LongWord(HInstance),0);
  1518. end;
  1519. end;
  1520. WM_HSCROLL:
  1521. if LOWORD(wParam)<>SB_ENDSCROLL then FTargetScrolling:=FTargetScrolling or 1
  1522. else FTargetScrolling:=FTargetScrolling and not 1;
  1523. WM_VSCROLL:
  1524. if LOWORD(wParam)<>SB_ENDSCROLL then FTargetScrolling:=FTargetScrolling or 2
  1525. else FTargetScrolling:=FTargetScrolling and not 2;
  1526. WM_MOUSEMOVE:
  1527. if (MouseHookHandle<>0) and (wParam and (MK_LBUTTON or MK_RBUTTON)=0) then
  1528. begin
  1529. UnHookWindowsHookEx(MouseHookHandle);
  1530. MouseHookHandle:=0;
  1531. if assigned(MouseHookDragDrop) then
  1532. begin
  1533. MouseHookDragDrop.FDragDetectStatus:=ddsNone;
  1534. if assigned(MouseHookDragDrop.FOnDragDetect) then
  1535. MouseHookDragDrop.FOnDragDetect(wparam,
  1536. MouseHookDragDrop.FDragDropControl.ScreenToClient(
  1537. MouseHookDragDrop.FDragDetectStart),
  1538. MouseHookDragDrop.FDragDropControl.ScreenToClient(
  1539. FDragDetectStart),
  1540. MouseHookDragDrop.FDragDetectStatus);
  1541. end;
  1542. MouseHookDragDrop:=nil;
  1543. end;
  1544. end;
  1545. end;
  1546. end;
  1547. procedure TDragDrop.StartDnDDetection(Button: TMouseButton);
  1548. var grfKeyState: Longint;
  1549. begin
  1550. if Button=mbLeft then FDragDetectStatus:=ddsLeft
  1551. else if Button=mbRight then FDragDetectStatus:=ddsRight
  1552. else
  1553. begin
  1554. FDragDetectStatus:=ddsNone;
  1555. exit;
  1556. end;
  1557. GetCursorPos(FDragDetectStart);
  1558. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then grfKeyState:=MK_SHIFT
  1559. else grfKeyState:=0;
  1560. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  1561. grfKeyState:=grfKeyState or MK_CONTROL;
  1562. if (MouseHookHandle<>0) then
  1563. begin // MouseHookProc is used by another component ...
  1564. UnHookWindowsHookEx(MouseHookHandle);
  1565. MouseHookHandle:=0;
  1566. if assigned(MouseHookDragDrop) then
  1567. begin
  1568. MouseHookDragDrop.FDragDetectStatus:=ddsNone;
  1569. if assigned(MouseHookDragDrop.FOnDragDetect) then
  1570. MouseHookDragDrop.FOnDragDetect(grfKeyState,
  1571. MouseHookDragDrop.FDragDropControl.ScreenToClient(
  1572. MouseHookDragDrop.FDragDetectStart),
  1573. MouseHookDragDrop.FDragDropControl.ScreenToClient(FDragDetectStart),
  1574. MouseHookDragDrop.FDragDetectStatus);
  1575. end;
  1576. end;
  1577. MouseHookDragDrop:=self;
  1578. MouseHookHandle:=SetWindowsHookEx(WH_MOUSE,MouseHookProc,LongWord(HInstance),0);
  1579. if assigned(FOnDragDetect) then
  1580. FOnDragDetect(grfKeyState,
  1581. FDragDropControl.ScreenToClient(FDragDetectStart),
  1582. FDragDropControl.ScreenToClient(FDragDetectStart),
  1583. FDragDetectStatus);
  1584. end;
  1585. procedure TDragDrop.Loaded;
  1586. // Methode which is called if all components are created - now, we can register
  1587. // the target control for drag-and-drop operations
  1588. begin
  1589. inherited Loaded;
  1590. if (FDragDropControl<>nil) and (csDesigning in ComponentState=false) then RegisterTarget;
  1591. end;
  1592. procedure TDragDrop.Notification(AComponent: TComponent; Operation: TOperation);
  1593. begin
  1594. inherited Notification(AComponent,Operation);
  1595. if (AComponent=FDragDropControl) and (Operation=opRemove) then
  1596. begin
  1597. UnregisterTarget;
  1598. UnhookMessageHandler(true);
  1599. FDragDropControl:=nil;
  1600. end;
  1601. end;
  1602. function TDragDrop.RegisterTarget: Boolean;
  1603. // Methode for registering the DragDropControl for drag-and-drop oprations
  1604. begin
  1605. Result:=false;
  1606. try
  1607. HookMessageHandler;
  1608. finally
  1609. // nothing to do
  1610. end;
  1611. if FRegistered or (FTargetEffects=0) or (FDragDropControl=nil) then exit;
  1612. try
  1613. // Ensure that drag-and-drop interface stays in memory
  1614. CoLockObjectExternal(FDropTarget, True, False);
  1615. if RegisterDragDrop(FDragDropControl.Handle, IDropTarget(FDropTarget))=S_OK then
  1616. begin
  1617. Result:=True;
  1618. FRegistered:=True;
  1619. end;
  1620. except
  1621. Result:=false;
  1622. FRegistered:=false;
  1623. end;
  1624. end;
  1625. function TDragDrop.UnRegisterTarget: Boolean;
  1626. begin
  1627. Result:=false;
  1628. if (FRegistered=false) or (FDragDropControl=nil) then exit;
  1629. try
  1630. UnHookMessageHandler(false);
  1631. CoLockObjectExternal(FDropTarget, false, False);
  1632. if (FDragDropControl.HandleAllocated=false) or
  1633. (FDragDropControl.HandleAllocated and
  1634. (RevokeDragDrop(FDragDropControl.Handle)=S_OK)) then
  1635. begin
  1636. FRegistered:=false;
  1637. Result:=true;
  1638. end;
  1639. except
  1640. end;
  1641. end;
  1642. procedure TDragDrop.HookMessageHandler;
  1643. begin
  1644. if (FDragDropControl=nil) or (FDragDropControl.Handle=0) then exit;
  1645. if (FMessageHooked=false) and ((FSourceEffects<>0) or (FTargetEffects<>0)) then
  1646. begin
  1647. WndProcPtr:=MakeObjectInstance(WndMethod);
  1648. OldWndProc:=Pointer(SetWindowLong(FDragDropControl.Handle, GWL_WNDPROC,
  1649. longint(WndProcPtr)));
  1650. FMessageHooked:=true;
  1651. end;
  1652. end;
  1653. procedure TDragDrop.UnhookMessageHandler(ForceUnhook:boolean);
  1654. begin
  1655. if FMessageHooked and (ForceUnhook or ((FSourceEffects=0) and (FTargetEffects=0))) then
  1656. begin
  1657. begin
  1658. SetWindowLong(FDragDropControl.Handle, GWL_WNDPROC, longint(OldWndProc));
  1659. FreeObjectInstance(WndProcPtr);
  1660. WndProcPtr:=nil;
  1661. OldWndProc:=nil;
  1662. end;
  1663. FMessageHooked:=false;
  1664. end;
  1665. end;
  1666. procedure TDragDrop.DoMenuPopup(Sender: TObject; AMenu: HMenu; DataObj: IDataObject; AMinCustCmd:integer;
  1667. grfKeyState: Longint; pt: TPoint);
  1668. begin
  1669. if assigned(FOnMenuPopup) then
  1670. FOnMenuPopup(Sender, AMenu, DataObj, AMinCustCmd, grfKeyState,
  1671. FDragDropControl.ScreenToClient(pt));
  1672. end;
  1673. function TDragDrop.DoMenuExecCmd(Sender: TObject; AMenu: HMenu; DataObj:IDataObject;
  1674. Command:integer; var dwEffect: longint):boolean;
  1675. begin
  1676. Result:=false;
  1677. if assigned(FOnMenuExecCmd) then
  1678. FOnMenuExecCmd(Sender, AMenu, DataObj, Command, dwEffect, Result);
  1679. end;
  1680. procedure TDragDrop.DoMenuDestroy(Sender:TObject; AMenu: HMenu);
  1681. begin
  1682. if assigned(FOnMenuDestroy) then FOnMenuDestroy(Sender, AMenu);
  1683. end;
  1684. procedure TDragDrop.SetDragDropControl(WinControl: TWinControl);
  1685. begin
  1686. if WinControl<>FDragDropControl then
  1687. begin
  1688. if FRegistered and (csDesigning in ComponentState=false) then
  1689. begin
  1690. UnhookMessageHandler(true);
  1691. UnregisterTarget;
  1692. end;
  1693. FDragDropControl:=WinControl;
  1694. if (csDesigning in ComponentState=false) then RegisterTarget;
  1695. end;
  1696. end;
  1697. function TDragDrop.ExecuteOperation(DataObject:TDataObject): TDragResult;
  1698. var dwEffect: Longint;
  1699. DropSource: TDropSource;
  1700. pt: tpoint;
  1701. grfKeyState:longint;
  1702. begin
  1703. Result:=drInvalid;
  1704. if (DataObject=nil) or (GInternalSource<>nil) then exit;
  1705. GInternalSource:=self;
  1706. if (FSourceEffects<>0) then
  1707. begin
  1708. if MouseHookHandle<>0 then
  1709. begin
  1710. UnHookWindowsHookEx(MouseHookHandle);
  1711. MouseHookHandle:=0;
  1712. end;
  1713. FDragDetectStatus:=ddsDrag;
  1714. DataObject.FCheckLindex:=CheckLindex in FSrcCompatibilityCheck;
  1715. DataObject.FCheckdwAspect:=CheckdwAspect in FSrcCompatibilityCheck;
  1716. try
  1717. FOwnerIsSource:=true;
  1718. try
  1719. DropSource:=TDropSource.Create(self);
  1720. try
  1721. if (DataObject<>nil) and (DragDropControl<>nil) and
  1722. (DoDragDrop(IDataObject(DataObject), DropSource,
  1723. FSourceEffects, dwEffect)=DRAGDROP_S_DROP) then
  1724. case dwEffect and ((DropEffect_Copy or
  1725. DropEffect_Move or DropEffect_Link)) of
  1726. DropEffect_Copy: Result:=drCopy;
  1727. DropEffect_Move: Result:=drMove;
  1728. DropEffect_Link: Result:=drLink;
  1729. else
  1730. begin
  1731. if WIN32Platform = VER_PLATFORM_WIN32_NT then Result:=drMove
  1732. else Result:=drCancelled;
  1733. end;
  1734. end
  1735. else Result:=drCancelled;
  1736. finally
  1737. DropSource._Release;
  1738. end;
  1739. except
  1740. Result:=drInvalid;
  1741. raise;
  1742. end;
  1743. finally
  1744. FOwnerIsSource:=false;
  1745. DataObject._Release;
  1746. end;
  1747. FDragDetectStatus:=ddsNone;
  1748. if assigned(FOnDragDetect) then
  1749. begin
  1750. GetCursorPos(pt);
  1751. if HiWord(DWord(GetKeyState(VK_SHIFT)))<>0 then grfKeyState:=MK_SHIFT
  1752. else grfKeyState:=0;
  1753. if HiWord(DWord(GetKeyState(VK_CONTROL)))<>0 then
  1754. grfKeyState:=grfKeyState or MK_CONTROL;
  1755. FOnDragDetect(grfKeyState,
  1756. FDragDropControl.ScreenToClient(FDragDetectStart),
  1757. FDragDropControl.ScreenToClient(pt), FDragDetectStatus);
  1758. end;
  1759. end
  1760. else
  1761. begin
  1762. FDragDetectStatus:=ddsNone;
  1763. Result:=drCancelled;
  1764. end;
  1765. GInternalSource:=nil;
  1766. end;
  1767. function TDragDrop.Execute: TDragResult;
  1768. begin
  1769. Result:=ExecuteOperation(CreateDataObject);
  1770. end;
  1771. procedure TDragDrop.SetSourceEffects(Values:TDropEffectSet);
  1772. begin
  1773. FSourceEffectsSet:=Values;
  1774. FSourceEffects:=0;
  1775. if deCopy in Values then inc(FSourceEffects,DROPEFFECT_COPY);
  1776. if deMove in Values then inc(FSourceEffects,DROPEFFECT_MOVE);
  1777. if deLink in Values then inc(FSourceEffects,DROPEFFECT_LINK);
  1778. if (csDesigning in ComponentState=false) and (csLoading in ComponentState=false) then
  1779. begin
  1780. if (csDesigning in ComponentState=false) and (FMessageHooked=false) and
  1781. (FSourceEffects<>0) then HookMessageHandler;
  1782. if (csDesigning in ComponentState=false) and (FMessageHooked=true) and
  1783. (FSourceEffects=0) then UnhookMessageHandler(false);
  1784. end;
  1785. end;
  1786. procedure TDragDrop.SetTargetEffects(Values:TDropEffectSet);
  1787. begin
  1788. FTargetEffectsSet:=Values;
  1789. FTargetEffects:=0;
  1790. if deCopy in Values then inc(FTargetEffects,DROPEFFECT_COPY);
  1791. if deMove in Values then inc(FTargetEffects,DROPEFFECT_MOVE);
  1792. if deLink in Values then inc(FTargetEffects,DROPEFFECT_LINK);
  1793. if (csDesigning in ComponentState=false) and (FRegistered=false) and
  1794. (FTargetEffects<>0) then RegisterTarget;
  1795. if (FRegistered=true) and (FTargetEffects=0) then
  1796. UnRegisterTarget;
  1797. end;
  1798. procedure SetMenuItemsStrings;
  1799. begin
  1800. {MP}{ case SysLocale.PriLangID of
  1801. LANG_GERMAN:
  1802. begin
  1803. MICopyStr:='Hierher &kopieren';
  1804. MIMoveStr:='Hierher &verschieben';
  1805. MILinkStr:='Verknüpfung(en) hier &erstellen';
  1806. MIAbortStr:='&Abbrechen';
  1807. end;
  1808. LANG_FRENCH:
  1809. begin // French
  1810. MICopyStr:='&Copier ici';
  1811. MIMoveStr:='&Transférer ici';
  1812. MILinkStr:='&Créer un ou des raccourci(s) ici';
  1813. MIAbortStr:='&Arrêt';
  1814. end;
  1815. LANG_ITALIAN:
  1816. begin // Italian
  1817. MICopyStr:='&Copiare qui';
  1818. MIMoveStr:='&Muoversi qui';
  1819. MILinkStr:='&Scorciatoia(e) crea qui';
  1820. MIAbortStr:='&Terminazione';
  1821. end;
  1822. LANG_POLISH:
  1823. begin // Polish
  1824. MICopyStr:='&Kopiuj tutaj';
  1825. MIMoveStr:='&Przenieœ tutaj';
  1826. MILinkStr:='Utwórz &skrót(y) tutaj';
  1827. MIAbortStr:='&Anuluj';
  1828. end;
  1829. LANG_PORTUGUESE:
  1830. begin // Portuguese
  1831. MICopyStr:='&Copíe aqui';
  1832. MIMoveStr:='&Mova aqui';
  1833. MILinkStr:='&Atalho(s) cría aqui';
  1834. MIAbortStr:='&Aborto';
  1835. end;
  1836. LANG_SPANISH:
  1837. begin // Spanish
  1838. MICopyStr:='&Copie aquí';
  1839. MIMoveStr:='&Muévase aquí';
  1840. MILinkStr:='&Atajo(s) crea aquí ';
  1841. MIAbortStr:='&Aborto';
  1842. end;
  1843. else
  1844. begin // English
  1845. MICopyStr:=SCopyStr;'&Copy Here';
  1846. MIMoveStr:=SMoveStr;'&Move Here';
  1847. MILinkStr:=SLinkStr;'&Shortcut(s) Create Here';
  1848. MIAbortStr:=SAbortStr;'&Abort';
  1849. end;
  1850. end;}{/MP}
  1851. end;
  1852. function TDragDrop.CopyToClipboard:boolean;
  1853. var DataObject:IDataObject;
  1854. begin
  1855. Result:=false;
  1856. DataObject:=CreateDataObject;
  1857. if DataObject=nil then exit;
  1858. try
  1859. Result:=OLESetClipBoard(DataObject)=S_Ok;
  1860. finally
  1861. DataObject._Release;
  1862. end;
  1863. end;
  1864. function TDragDrop.GetFromClipboard:boolean;
  1865. var DataObject:IDataObject;
  1866. pt:TPoint;
  1867. dwEffect:longint;
  1868. begin
  1869. Result:=OLEGetClipBoard(DataObject)=S_Ok;
  1870. if Result then
  1871. begin
  1872. pt.x:=-1;
  1873. pt.y:=-1;
  1874. dwEffect:=DropEffect_Copy;
  1875. FDropTarget.RenderDropped(DataObject, 0, pt, dwEffect);
  1876. end;
  1877. end;
  1878. function TDragDrop.DropHandler(const dataObj: IDataObject; grfKeyState: Longint;
  1879. pt: TPoint; var dwEffect: Longint): boolean;
  1880. begin
  1881. Result:=false;
  1882. end;
  1883. // Register method -------------------------------------------------------------
  1884. procedure Register;
  1885. begin
  1886. {MP}RegisterComponents({'Shell32'}'DragDrop', [TDragDrop]);
  1887. end;
  1888. // initialize/de-initialize the ole libary -------------------------------------
  1889. initialization
  1890. begin
  1891. OleInitialize(nil);
  1892. MouseHookHandle:=0;
  1893. GInternalSource:=nil;
  1894. SetMenuItemsStrings;
  1895. // to avoid mix ups
  1896. DDM_ProcessDropped:=RegisterWindowMessage('DDM_ProcessDropped');
  1897. end;
  1898. finalization
  1899. begin
  1900. if MouseHookHandle<>0 then UnHookWindowsHookEx(MouseHookHandle);
  1901. OleUninitialize;
  1902. end;
  1903. end.