CustomDriveView.pas 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. unit CustomDriveView;
  2. interface
  3. uses
  4. Classes, ComCtrls, CommCtrl, Windows, Controls, Forms, ShlObj, Messages,
  5. Graphics,
  6. DragDrop, CustomDirView, IEDriveInfo, DragDropFilesEx, PasTools;
  7. type
  8. {Types uses by the function IterateSubTree:}
  9. {TRecursiveScan: determines, wich nodes are scanned by the function IterateSubTree:
  10. rsNoRecursive: Scan startnode only.
  11. rsRecursiveExisting: Scan all subnodes of the startnode but not new created subnodes.}
  12. TRecursiveScan = (rsNoRecursive, rsRecursiveExisting);
  13. {TScanStartnode: determines, wether the startnode should also be scanned:}
  14. TScanStartNode = (coNoScanStartNode, coScanStartNode);
  15. TCallBackFunc = function(var Node: TTreeNode; Data: Pointer): Boolean of object;
  16. type
  17. TCustomDriveView = class(TCustomTreeView)
  18. protected
  19. FParentForm: TCustomForm;
  20. FDragFileList: TStringList;
  21. FDragDropFilesEx: TCustomizableDragDropFilesEx;
  22. FDragImageList: TDragImageList;
  23. FDragDrive: string;
  24. FExeDrag: Boolean;
  25. FDDLinkOnExeDrag: Boolean;
  26. FDragNode: TTreeNode;
  27. FDragStartTime: FILETIME;
  28. FDragPos: TPoint;
  29. FStartPos: TPoint;
  30. FContextMenu: Boolean;
  31. FCanChange: Boolean;
  32. FUseSystemContextMenu: Boolean;
  33. FDimmHiddenDirs: Boolean;
  34. FShowHiddenDirs: Boolean;
  35. FNaturalOrderNumericalSorting: Boolean;
  36. FContinue: Boolean;
  37. FImageList: TImageList;
  38. FScrollOnDragOver: TTreeViewScrollOnDragOver;
  39. FOnDDDragEnter: TDDOnDragEnter;
  40. FOnDDDragLeave: TDDOnDragLeave;
  41. FOnDDDragOver: TDDOnDragOver;
  42. FOnDDDrop: TDDOnDrop;
  43. FOnDDQueryContinueDrag: TDDOnQueryContinueDrag;
  44. FOnDDChooseEffect: TDDOnChooseEffect;
  45. FOnDDGiveFeedback: TDDOnGiveFeedback;
  46. FOnDDDragDetect: TDDOnDragDetect;
  47. FOnDDMenuPopup: TOnMenuPopup;
  48. FOnDDProcessDropped: TOnProcessDropped;
  49. FOnDDError: TDDErrorEvent;
  50. FOnDDExecuted: TDDExecutedEvent;
  51. FOnDDFileOperation: TDDFileOperationEvent;
  52. FOnDDFileOperationExecuted: TDDFileOperationExecutedEvent;
  53. FOnDDCreateDragFileList: TDDOnCreateDragFileList;
  54. FOnDDEnd: TNotifyEvent;
  55. FOnDDCreateDataObject: TDDOnCreateDataObject;
  56. FLastDDResult: TDragResult;
  57. FOnBusy: TDirViewBusy;
  58. function GetTargetPopupMenu: Boolean;
  59. procedure SetTargetPopUpMenu(Value: Boolean);
  60. procedure SetDimmHiddenDirs(Value: Boolean);
  61. procedure SetShowHiddenDirs(Value: Boolean);
  62. procedure SetNaturalOrderNumericalSorting(Value: Boolean);
  63. function GetDirectory: string; virtual;
  64. procedure SetDirectory(Value: string); virtual;
  65. function GetCustomDirView: TCustomDirView; virtual; abstract;
  66. procedure SetCustomDirView(Value: TCustomDirView); virtual; abstract;
  67. procedure CreateWnd; override;
  68. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  69. function GetNodeFromHItem(Item: TTVItem): TTreeNode;
  70. function IsCustomDrawn(Target: TCustomDrawTarget; Stage: TCustomDrawStage): Boolean; override;
  71. function CustomDrawItem(Node: TTreeNode; State: TCustomDrawState;
  72. Stage: TCustomDrawStage; var PaintImages: Boolean): Boolean; override;
  73. procedure NeedImageLists(Recreate: Boolean);
  74. procedure DoCompare(Sender: TObject; Node1, Node2: TTreeNode; Data: Integer; var Compare: Integer);
  75. procedure CNNotify(var Msg: TWMNotify); message CN_NOTIFY;
  76. procedure CMColorChanged(var Msg: TMessage); message CM_COLORCHANGED;
  77. procedure CMRecreateWnd(var Msg: TMessage); message CM_RECREATEWND;
  78. procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN;
  79. procedure WMLButtonUp(var Msg: TWMLButtonDown); message WM_LBUTTONUP;
  80. procedure WMRButtonDown(var Msg: TWMRButtonDown); message WM_RBUTTONDOWN;
  81. procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
  82. procedure WMContextMenu(var Msg: TWMContextMenu); message WM_CONTEXTMENU;
  83. procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
  84. procedure CMDPIChanged(var Message: TMessage); message CM_DPICHANGED;
  85. procedure Delete(Node: TTreeNode); override;
  86. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  87. procedure KeyPress(var Key: Char); override;
  88. procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  89. procedure InternalOnDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
  90. State: TCustomDrawState; var DefaultDraw: Boolean);
  91. procedure DDDragEnter(DataObj: IDataObject; KeyState: Longint;
  92. Point: TPoint; var Effect: Longint; var Accept: Boolean);
  93. procedure DDDragLeave;
  94. procedure DDDragOver(KeyState: Longint; Point: TPoint; var Effect: Longint);
  95. procedure DDDrop(DataObj: IDataObject; KeyState: Longint; Point: TPoint;
  96. var Effect: Longint);
  97. procedure DDQueryContinueDrag(EscapePressed: BOOL; KeyState: Longint;
  98. var Result: HResult);
  99. procedure DDDropHandlerSucceeded(Sender: TObject; KeyState: Longint;
  100. Point: TPoint; Effect: Longint);
  101. procedure DDGiveFeedback(Effect: Longint; var Result: HResult);
  102. procedure DDMenuPopup(Sender: TObject; AMenu: HMenu; DataObj: IDataObject;
  103. AMinCustCmd: Integer; grfKeyState: Longint; Point: TPoint);
  104. procedure DDMenuDone(Sender: TObject; AMenu: HMenu);
  105. procedure DDProcessDropped(Sender: TObject; KeyState: Longint;
  106. Point: TPoint; Effect: Longint);
  107. procedure DDError(Error: TDDError); virtual;
  108. procedure DDSpecifyDropTarget(Sender: TObject; DragDropHandler: Boolean;
  109. Point: TPoint; var PIDL: PItemIDList; var Filename: string);
  110. procedure DDDragDetect(KeyState: Longint; DetectStart, Point: TPoint;
  111. DragStatus: TDragDetectStatus); virtual;
  112. procedure PerformDragDropFileOperation(Node: TTreeNode; Effect: Integer); virtual; abstract;
  113. procedure DDChooseEffect(KeyState: Integer; var Effect: Integer); virtual;
  114. function DragCompleteFileList: Boolean; virtual; abstract;
  115. function DDExecute: TDragResult; virtual;
  116. function DDSourceEffects: TDropEffectSet; virtual; abstract;
  117. function NodePath(Node: TTreeNode): string; virtual; abstract;
  118. function NodeIsRecycleBin(Node: TTreeNode): Boolean; virtual;
  119. function NodePathExists(Node: TTreeNode): Boolean; virtual;
  120. function NodeColor(Node: TTreeNode): TColor; virtual; abstract;
  121. function NodeCanDrag(Node: TTreeNode): Boolean; virtual;
  122. function NodeOverlayIndexes(Node: TTreeNode): Word; virtual;
  123. function FindPathNode(Path: string): TTreeNode; virtual; abstract;
  124. procedure ClearDragFileList(FileList: TFileList); virtual;
  125. procedure AddToDragFileList(FileList: TFileList; Node: TTreeNode); virtual;
  126. procedure ValidateDirectoryEx(Node: TTreeNode; Recurse: TRecursiveScan;
  127. NewDirs: Boolean); virtual; abstract;
  128. procedure RebuildTree; virtual; abstract;
  129. procedure DisplayContextMenu(Node: TTreeNode; ScreenPos: TPoint); virtual; abstract;
  130. procedure DisplayPropertiesMenu(Node: TTreeNode); virtual; abstract;
  131. procedure ScrollOnDragOverBeforeUpdate(ObjectToValidate: TObject);
  132. procedure ScrollOnDragOverAfterUpdate;
  133. function DoBusy(Busy: Integer): Boolean;
  134. function StartBusy: Boolean;
  135. procedure EndBusy;
  136. function IsBusy: Boolean;
  137. property ImageList: TImageList read FImageList;
  138. public
  139. constructor Create(AOwner: TComponent); override;
  140. destructor Destroy; override;
  141. procedure ValidateDirectory(Node: TTreeNode);
  142. procedure CenterNode(Node: TTreeNode); virtual;
  143. function SortChildren(ParentNode: TTreeNode; Recurse: Boolean): Boolean;
  144. function IterateSubTree(var StartNode : TTreeNode;
  145. CallBackFunc: TCallBackFunc; Recurse: TRecursiveScan;
  146. ScanStartNode: TScanStartNode; Data: Pointer): Boolean;
  147. function NodePathName(Node: TTreeNode): string; virtual; abstract;
  148. property DragDropFilesEx: TCustomizableDragDropFilesEx read FDragDropFilesEx;
  149. property UseSystemContextMenu: Boolean read FUseSystemContextMenu
  150. write FUseSystemContextMenu default True;
  151. property DimmHiddenDirs: Boolean read FDimmHiddenDirs
  152. write SetDimmHiddenDirs default False;
  153. property ShowHiddenDirs: Boolean read FShowHiddenDirs
  154. write SetShowHiddenDirs default False;
  155. property NaturalOrderNumericalSorting: Boolean read FNaturalOrderNumericalSorting write SetNaturalOrderNumericalSorting;
  156. property DDLinkOnExeDrag: Boolean read FDDLinkOnExeDrag write FDDLinkOnExeDrag default True;
  157. {The mouse has entered the component window as a target of a drag&drop operation:}
  158. property OnDDDragEnter: TDDOnDragEnter read FOnDDDragEnter write FOnDDDragEnter;
  159. {The mouse has leaved the component window as a target of a drag&drop operation:}
  160. property OnDDDragLeave: TDDOnDragLeave read FOnDDDragLeave write FOnDDDragLeave;
  161. {The mouse is dragging in the component window as a target of a drag&drop operation:}
  162. property OnDDDragOver: TDDOnDragOver read FOnDDDragOver write FOnDDDragOver;
  163. {The Drag&drop operation is about to be executed:}
  164. property OnDDDrop: TDDOnDrop read FOnDDDrop write FOnDDDrop;
  165. property OnDDQueryContinueDrag: TDDOnQueryContinueDrag read FOnDDQueryContinueDrag write FOnDDQueryContinueDrag;
  166. property OnDDChooseEffect: TDDOnChooseEffect read FOnDDChooseEffect write FOnDDChooseEffect;
  167. property OnDDGiveFeedback: TDDOnGiveFeedback read FOnDDGiveFeedback write FOnDDGiveFeedback;
  168. {A drag&drop operation is about to be initiated whith the components window as the source:}
  169. property OnDDDragDetect: TDDOnDragDetect read FOnDDDragDetect write FOnDDDragDetect;
  170. {The component window is the target of a drag&drop operation:}
  171. property OnDDProcessDropped: TOnProcessDropped read FOnDDProcessDropped write FOnDDProcessDropped;
  172. {An error has occurred during a drag&drop operation:}
  173. property OnDDError: TDDErrorEvent read FOnDDError write FOnDDError;
  174. {The drag&drop operation has been executed:}
  175. property OnDDExecuted: TDDExecutedEvent read FOnDDExecuted write FOnDDExecuted;
  176. {Event is fired just before executing the fileoperation. This event is also fired when
  177. files are pasted from the clipboard:}
  178. property OnDDFileOperation: TDDFileOperationEvent read FOnDDFileOperation write FOnDDFileOperation;
  179. {Event is fired after executing the fileoperation. This event is also fired when
  180. files are pasted from the clipboard:}
  181. property OnDDFileOperationExecuted: TDDFileOperationExecutedEvent read FOnDDFileOperationExecuted write FOnDDFileOperationExecuted;
  182. property OnDDCreateDragFileList: TDDOnCreateDragFileList
  183. read FOnDDCreateDragFileList write FOnDDCreateDragFileList;
  184. property OnDDEnd: TNotifyEvent
  185. read FOnDDEnd write FOnDDEnd;
  186. property OnDDCreateDataObject: TDDOnCreateDataObject
  187. read FOnDDCreateDataObject write FOnDDCreateDataObject;
  188. property OnDDMenuPopup: TOnMenuPopup read FOnDDMenuPopup write FOnDDMenuPopup;
  189. property OnBusy: TDirViewBusy read FOnBusy write FOnBusy;
  190. { Show popupmenu when dropping a file with the right mouse button }
  191. property TargetPopUpMenu: Boolean read GetTargetPopUpMenu write SetTargetPopUpMenu default True;
  192. {Current selected directory:}
  193. property Directory: string read GetDirectory write SetDirectory;
  194. property DragNode: TTreeNode read FDragNode;
  195. property Continue: Boolean read FContinue write FContinue;
  196. property LastDDResult: TDragResult read FLastDDResult;
  197. end;
  198. resourcestring
  199. SDragDropError = 'Drag&drop error: %d';
  200. implementation
  201. uses
  202. SysUtils, ShellApi, ImgList,
  203. IEListView, BaseUtils;
  204. constructor TCustomDriveView.Create(AOwner: TComponent);
  205. begin
  206. inherited;
  207. DragMode := dmAutomatic;
  208. FDragFileList := TStringList.Create;
  209. FDragDrive := '';
  210. FExeDrag := False;
  211. FDDLinkOnExeDrag := True;
  212. FContextMenu := False;
  213. FCanChange := True;
  214. FUseSystemContextMenu := True;
  215. FContinue := True;
  216. FNaturalOrderNumericalSorting := True;
  217. OnCompare := DoCompare;
  218. FDragDropFilesEx := TCustomizableDragDropFilesEx.Create(Self);
  219. with FDragDropFilesEx do
  220. begin
  221. AcceptOwnDnd := True;
  222. {MP}
  223. AutoDetectDnD := False;
  224. {/MP}
  225. BringToFront := True;
  226. CompleteFileList := True;
  227. NeedValid := [nvFileName];
  228. RenderDataOn := rdoEnterAndDropSync;
  229. TargetPopUpMenu := True;
  230. OnDragEnter := DDDragEnter;
  231. OnDragLeave := DDDragLeave;
  232. OnDragOver := DDDragOver;
  233. OnDrop := DDDrop;
  234. OnQueryContinueDrag := DDQueryContinueDrag;
  235. OnSpecifyDropTarget := DDSpecifyDropTarget;
  236. OnMenuPopup := DDMenuPopup;
  237. OnMenuDestroy := DDMenuDone;
  238. OnDropHandlerSucceeded := DDDropHandlerSucceeded;
  239. OnGiveFeedback := DDGiveFeedback;
  240. OnProcessDropped := DDProcessDropped;
  241. OnDragDetect := DDDragDetect;
  242. end;
  243. OnCustomDrawItem := InternalOnDrawItem;
  244. FScrollOnDragOver := TTreeViewScrollOnDragOver.Create(Self, False);
  245. FScrollOnDragOver.OnBeforeUpdate := ScrollOnDragOverBeforeUpdate;
  246. FScrollOnDragOver.OnAfterUpdate := ScrollOnDragOverAfterUpdate;
  247. end;
  248. destructor TCustomDriveView.Destroy;
  249. begin
  250. FreeAndNil(FScrollOnDragOver);
  251. FreeAndNil(FImageList);
  252. if Assigned(Images) then
  253. Images.Free;
  254. if Assigned(FDragImageList) then
  255. begin
  256. if GlobalDragImageList = FDragImageList then
  257. GlobalDragImageList := nil;
  258. FDragImageList.Free;
  259. end;
  260. FDragFileList.Destroy;
  261. if Assigned(FDragDropFilesEx) then
  262. FDragDropFilesEx.Free;
  263. inherited Destroy;
  264. end;
  265. procedure TCustomDriveView.NeedImageLists(Recreate: Boolean);
  266. var
  267. MinHeight: Integer;
  268. AImages: TImageList;
  269. begin
  270. if not Assigned(Images) then
  271. begin
  272. Images := TImageList.Create(Self);
  273. Images.BkColor := Color;
  274. end;
  275. AImages := ShellImageListForControl(Self, ilsSmall);
  276. if Images.Handle <> AImages.Handle then
  277. begin
  278. Images.Handle := AImages.Handle;
  279. end;
  280. if (not Assigned(FImageList)) or Recreate then
  281. begin
  282. if Assigned(FImageList) then
  283. FImageList.Free;
  284. FImageList := OverlayImageList(Images.Width);
  285. end;
  286. MinHeight := ScaleByTextHeight(Self, 18);
  287. if TreeView_GetItemHeight(Handle) < MinHeight then
  288. TreeView_SetItemHeight(Handle, MinHeight);
  289. end;
  290. procedure TCustomDriveView.CMDPIChanged(var Message: TMessage);
  291. begin
  292. inherited;
  293. NeedImageLists(True);
  294. end;
  295. procedure TCustomDriveView.CreateWnd;
  296. begin
  297. inherited;
  298. NeedImageLists(False);
  299. if not (csDesigning in ComponentState) then
  300. FDragImageList := TDragImageList.Create(Self);
  301. if not Assigned(GlobalDragImageList) then
  302. GlobalDragImageList := FDragImageList;
  303. FDragDropFilesEx.DragDropControl := Self;
  304. FParentForm := GetParentForm(Self);
  305. end;
  306. procedure TCustomDriveView.Notification(AComponent: TComponent; Operation: TOperation);
  307. begin
  308. inherited;
  309. if Operation = opRemove then
  310. begin
  311. if AComponent = GetCustomDirView then SetCustomDirView(nil);
  312. end;
  313. end;
  314. procedure TCustomDriveView.InternalOnDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
  315. State: TCustomDrawState; var DefaultDraw: Boolean);
  316. var
  317. FItemColor: TColor;
  318. begin
  319. if Assigned(Node) and Assigned(Node.Data) and (Node <> DropTarget) then
  320. begin
  321. if not Node.Selected then
  322. begin
  323. FItemColor := NodeColor(Node);
  324. if (FItemColor <> clDefaultItemColor) and
  325. (Canvas.Font.Color <> FItemColor) then
  326. Canvas.Font.Color := FItemColor;
  327. end
  328. else
  329. if (not Self.Focused) and HideSelection then
  330. begin
  331. Canvas.Brush.Color := clBtnFace;
  332. Canvas.Font.Color := clBtnText;
  333. end;
  334. end;
  335. end; {InternalOnDrawItem}
  336. procedure TCustomDriveView.ScrollOnDragOverBeforeUpdate(ObjectToValidate: TObject);
  337. var
  338. NodeToValidate: TTreeNode;
  339. begin
  340. GlobalDragImageList.HideDragImage;
  341. if Assigned(ObjectToValidate) then
  342. begin
  343. NodeToValidate := (ObjectToValidate as TTreeNode);
  344. if not NodeToValidate.HasChildren then
  345. ValidateDirectory(NodeToValidate);
  346. end;
  347. end;
  348. procedure TCustomDriveView.ScrollOnDragOverAfterUpdate;
  349. begin
  350. GlobalDragImageList.ShowDragImage;
  351. end;
  352. procedure TCustomDriveView.DDDragEnter(DataObj: IDataObject; KeyState: Longint;
  353. Point: TPoint; var Effect: Longint; var Accept: Boolean);
  354. var
  355. Index: Integer;
  356. begin
  357. if (FDragDropFilesEx.FileList.Count > 0) and
  358. (Length(TFDDListItem(FDragDropFilesEx.FileList[0]^).Name) > 0) Then
  359. begin
  360. FDragDrive := DriveInfo.GetDriveKey(TFDDListItem(FDragDropFilesEx.FileList[0]^).Name);
  361. FExeDrag := FDDLinkOnExeDrag and
  362. (deLink in DragDropFilesEx.TargetEffects) and
  363. ((DragDropFilesEx.AvailableDropEffects and DropEffect_Link) <> 0);
  364. if FExeDrag then
  365. begin
  366. for Index := 0 to FDragDropFilesEx.FileList.Count - 1 do
  367. if not IsExecutable(TFDDListItem(FDragDropFilesEx.FileList[Index]^).Name) then
  368. begin
  369. FExeDrag := False;
  370. Break;
  371. end;
  372. end;
  373. end
  374. else
  375. begin
  376. FDragDrive := '';
  377. end;
  378. FScrollOnDragOver.StartDrag;
  379. if Assigned(FOnDDDragEnter) then
  380. FOnDDDragEnter(Self, DataObj, KeyState, Point, Effect, Accept);
  381. end; {DDDragEnter}
  382. procedure TCustomDriveView.DDDragLeave;
  383. begin
  384. if Assigned(DropTarget) then
  385. begin
  386. if GlobalDragImageList.Dragging then
  387. GlobalDragImageList.HideDragImage;
  388. DropTarget := nil;
  389. Update;
  390. end;
  391. if Assigned(FOnDDDragLeave) then
  392. FOnDDDragLeave(Self);
  393. end; {DragLeave}
  394. procedure TCustomDriveView.DDDragOver(KeyState: Longint; Point: TPoint; var Effect: Longint);
  395. var
  396. Node: TTreeNode;
  397. Rect1: TRect;
  398. UpdateImage: Boolean;
  399. LastDragNode: TTreeNode;
  400. begin
  401. if Effect <> DropEffect_None then
  402. begin
  403. Node := GetNodeAt(Point.X, Point.Y);
  404. if Assigned(Node) then
  405. begin
  406. LastDragNode := DropTarget;
  407. UpdateImage := False;
  408. if GlobalDragImageList.Dragging and (LastDragNode <> Node) then
  409. begin
  410. if Assigned(LastDragNode) then
  411. begin
  412. Rect1 := LastDragNode.DisplayRect(True);
  413. if Rect1.Right >= Point.x - GlobalDragImageList.GetHotSpot.X then
  414. begin
  415. GlobalDragImageList.HideDragImage;
  416. UpdateImage := True;
  417. end
  418. else
  419. begin
  420. Rect1 := Node.DisplayRect(True);
  421. if Rect1.Right >= Point.x - GlobalDragImageList.GetHotSpot.X then
  422. begin
  423. GlobalDragImageList.HideDragImage;
  424. UpdateImage := True;
  425. end
  426. end;
  427. end
  428. else
  429. begin
  430. {LastDragNode not assigned:}
  431. GlobalDragImageList.HideDragImage;
  432. UpdateImage := True;
  433. end;
  434. end;
  435. DropTarget := Node;
  436. if UpdateImage then
  437. GlobalDragImageList.ShowDragImage;
  438. {Drop-operation allowed at this location?}
  439. if Assigned(FDragNode) and
  440. (Effect <> DropEffect_Link) and
  441. ((Node = FDragNode) or Node.HasAsParent(FDragNode) or (FDragNode.Parent = Node)) then
  442. Effect := DropEffect_None;
  443. FScrollOnDragOver.DragOver(Point);
  444. end {Assigned(Node)}
  445. else
  446. begin
  447. DropTarget := nil;
  448. end;
  449. end;
  450. DDChooseEffect(KeyState, Effect);
  451. if Assigned(FOnDDDragOver) then
  452. FOnDDDragOver(Self, KeyState, Point, Effect);
  453. if not Assigned(DropTarget) then Effect := DropEffect_None
  454. else
  455. if NodeIsRecycleBin(DropTarget) then
  456. begin
  457. if FDragDropFilesEx.FileNamesAreMapped then Effect := DropEffect_None
  458. else Effect := DropEffect_Move;
  459. end;
  460. end; {DDDragOver}
  461. procedure TCustomDriveView.DDDrop(DataObj: IDataObject; KeyState: Longint;
  462. Point: TPoint; var Effect: Longint);
  463. begin
  464. if GlobalDragImageList.Dragging then
  465. GlobalDragImageList.HideDragImage;
  466. if Effect = DropEffect_None then
  467. DropTarget := nil;
  468. if Assigned(FOnDDDrop) then
  469. FOnDDDrop(Self, DataObj, KeyState, Point, Effect);
  470. end; {DDDrop}
  471. procedure TCustomDriveView.DDQueryContinueDrag(EscapePressed: BOOL; KeyState: Longint;
  472. var Result: HResult);
  473. var
  474. Point: TPoint;
  475. ClientPoint: TPoint;
  476. KnowTime: FILETIME;
  477. begin
  478. if Result = DRAGDROP_S_DROP then
  479. begin
  480. GetSystemTimeAsFileTime(KnowTime);
  481. if ((Int64(KnowTime) - Int64(FDragStartTime)) <= DDDragStartDelay) then
  482. Result := DRAGDROP_S_CANCEL;
  483. end;
  484. if Assigned(FOnDDQueryContinueDrag) then
  485. FOnDDQueryContinueDrag(Self, EscapePressed, KeyState, Result);
  486. if EscapePressed then
  487. begin
  488. if GlobalDragImageList.Dragging then
  489. GlobalDragImageList.HideDragImage;
  490. DropTarget := nil;
  491. end
  492. else
  493. begin
  494. if GlobalDragImageList.Dragging then
  495. begin
  496. GetCursorPos(Point);
  497. {Convert screen coordinates to the parentforms coordinates:}
  498. ClientPoint := FParentForm.ScreenToClient(Point);
  499. {Move the drag image to the new position and show it:}
  500. if not CompareMem(@ClientPoint, @FDragPos, SizeOf(TPoint)) then
  501. begin
  502. FDragPos := ClientPoint;
  503. if PtInRect(FParentForm.BoundsRect, Point) then
  504. begin
  505. GlobalDragImageList.DragMove(ClientPoint.X, ClientPoint.Y);
  506. GlobalDragImageList.ShowDragImage;
  507. end
  508. else GlobalDragImageList.HideDragImage;
  509. end;
  510. end;
  511. end;
  512. end; {DDQueryContinueDrag}
  513. procedure TCustomDriveView.DDMenuPopup(Sender: TObject; AMenu: HMenu;
  514. DataObj: IDataObject; AMinCustCmd: Integer; grfKeyState: Longint; Point: TPoint);
  515. begin
  516. if Assigned(OnDDMenuPopup) then
  517. begin
  518. OnDDMenuPopup(Self, AMenu, DataObj, AMinCustCmd, grfKeyState, Point);
  519. end;
  520. end;
  521. procedure TCustomDriveView.DDMenuDone(Sender: TObject; AMenu: HMenu);
  522. begin
  523. end;
  524. procedure TCustomDriveView.DDDropHandlerSucceeded(Sender: TObject;
  525. KeyState: Integer; Point: TPoint; Effect: Integer);
  526. begin
  527. DropTarget := nil;
  528. end;
  529. procedure TCustomDriveView.DDChooseEffect(KeyState: Integer; var Effect: Integer);
  530. begin
  531. if Assigned(FOnDDChooseEffect) then
  532. FOnDDChooseEffect(Self, KeyState, Effect);
  533. end;
  534. procedure TCustomDriveView.DDGiveFeedback(Effect: Longint; var Result: HResult);
  535. begin
  536. if Assigned(FOnDDGiveFeedback) then
  537. FOnDDGiveFeedback(Self, Effect, Result);
  538. end; {DDGiveFeedback}
  539. procedure TCustomDriveView.DDProcessDropped(Sender: TObject; KeyState: Longint;
  540. Point: TPoint; Effect: Longint);
  541. begin
  542. try
  543. if Assigned(DropTarget) then
  544. try
  545. if NodePathExists(DropTarget) then
  546. begin
  547. if Assigned(FOnDDProcessDropped) then
  548. FOnDDProcessDropped(Self, KeyState, Point, Effect);
  549. if Effect <> DropEffect_None then
  550. begin
  551. PerformDragDropFileOperation(DropTarget, Effect);
  552. if Assigned(FOnDDExecuted) then
  553. FOnDDExecuted(Self, Effect);
  554. end;
  555. end
  556. else
  557. begin
  558. ValidateDirectory(DropTarget);
  559. DDError(DDPathNotFoundError);
  560. end;
  561. finally
  562. DropTarget := nil;
  563. ClearDragFileList(FDragDropFilesEx.FileList);
  564. end;
  565. except
  566. Application.HandleException(Self);
  567. end;
  568. end; {ProcessDropped}
  569. procedure TCustomDriveView.DDError(Error: TDDError);
  570. begin
  571. if Assigned(FOnDDError) then FOnDDError(Self, Error)
  572. else raise Exception.CreateFmt(SDragDropError, [Ord(Error)]);
  573. end; {DDError}
  574. procedure TCustomDriveView.DDSpecifyDropTarget(Sender: TObject;
  575. DragDropHandler: Boolean; Point: TPoint; var PIDL: PItemIDList; var Filename: string);
  576. begin
  577. PIDL := nil;
  578. if DragDropHandler and Assigned(DropTarget) then FileName := NodePathName(DropTarget)
  579. else FileName := EmptyStr;
  580. end; {DDSpecifyDropTarget}
  581. procedure TCustomDriveView.DDDragDetect(KeyState: Longint; DetectStart, Point: TPoint;
  582. DragStatus: TDragDetectStatus);
  583. var
  584. P: TPoint;
  585. ImageList: HImageList;
  586. NodeRect: TRect;
  587. FileListCreated: Boolean;
  588. AvoidDragImage: Boolean;
  589. begin
  590. if (DragStatus = ddsDrag) and (not Assigned(FDragNode)) then
  591. begin
  592. P := ScreenToClient(FStartPos);
  593. FDragNode := GetNodeAt(P.X, P.Y);
  594. end;
  595. if Assigned(FOnDDDragDetect) then
  596. FOnDDDragDetect(Self, KeyState, DetectStart, Point, DragStatus);
  597. if (DragStatus = ddsDrag) and Assigned(FDragNode) then
  598. begin
  599. NodeRect := FDragNode.DisplayRect(True);
  600. Dec(NodeRect.Left, 16);
  601. {Check, wether the mouse cursor was within the nodes display rectangle:}
  602. if (NodeRect.Left > P.X) or (NodeRect.Right < P.X) or
  603. (not NodeCanDrag(FDragNode)) then
  604. begin
  605. FDragNode := nil;
  606. Exit;
  607. end;
  608. FDragDrive := '';
  609. ClearDragFileList(FDragDropFilesEx.FileList);
  610. FDragDropFilesEx.CompleteFileList := DragCompleteFileList;
  611. FileListCreated := False;
  612. AvoidDragImage := False;
  613. if Assigned(OnDDCreateDragFileList) then
  614. begin
  615. OnDDCreateDragFileList(Self, FDragDropFilesEx.FileList, FileListCreated);
  616. if FileListCreated then
  617. AvoidDragImage := True;
  618. end;
  619. if not FileListCreated then
  620. begin
  621. AddToDragFileList(FDragDropFilesEx.FileList, FDragNode);
  622. end;
  623. FDragDropFilesEx.SourceEffects := DDSourceEffects;
  624. if FDragDropFilesEx.FileList.Count > 0 then
  625. try
  626. {Create the dragimage:}
  627. GlobalDragImageList := FDragImageList;
  628. if not AvoidDragImage then
  629. begin
  630. {Hide the selection mark to get a proper dragimage:}
  631. if Selected = FDragNode then
  632. Selected := nil;
  633. ImageList := TreeView_CreateDragImage(Handle, FDragNode.ItemID);
  634. {Show the selection mark if it was hidden:}
  635. if not Assigned(Selected) then
  636. Selected := FDragNode;
  637. if ImageList <> Invalid_Handle_Value then
  638. begin
  639. GlobalDragImageList.Handle := ImageList;
  640. GlobalDragImageList.SetDragImage(0, P.X - NodeRect.TopLeft.X, P.Y - NodeRect.TopLeft.Y);
  641. P := FParentForm.ScreenToClient(Point);
  642. GlobalDragImageList.BeginDrag(FParentForm.Handle, P.X, P.Y);
  643. GlobalDragImageList.HideDragImage;
  644. ShowCursor(True);
  645. end;
  646. end;
  647. DropSourceControl := Self;
  648. GetSystemTimeAsFileTime(FDragStartTime);
  649. {Supress the context menu:}
  650. FContextMenu := False;
  651. {Execute the drag&drop-Operation:}
  652. FLastDDResult := DDExecute;
  653. {the drag&drop operation is finished, so clean up the used drag image:}
  654. GlobalDragImageList.EndDrag;
  655. GlobalDragImageList.Clear;
  656. Application.ProcessMessages;
  657. finally
  658. ClearDragFileList(FDragDropFilesEx.FileList);
  659. FDragDrive := '';
  660. DropTarget := nil;
  661. try
  662. if Assigned(OnDDEnd) then
  663. OnDDEnd(Self);
  664. finally
  665. DropSourceControl := nil;
  666. FDragNode := nil;
  667. end;
  668. end;
  669. end;
  670. end; {(DDDragDetect}
  671. function TCustomDriveView.DDExecute: TDragResult;
  672. var
  673. DataObject: TDataObject;
  674. begin
  675. DataObject := nil;
  676. if Assigned(OnDDCreateDataObject) then
  677. OnDDCreateDataObject(Self, DataObject);
  678. Result := FDragDropFilesEx.Execute(DataObject);
  679. end;
  680. function TCustomDriveView.GetNodeFromHItem(Item: TTVItem): TTreeNode;
  681. begin
  682. Result := nil;
  683. if Items <> nil then
  684. with Item do
  685. if (state and TVIF_PARAM) <> 0 then
  686. Result := Pointer(lParam)
  687. else
  688. Result := Items.GetNode(hItem);
  689. end; {GetNodeFromItem}
  690. function TCustomDriveView.IsCustomDrawn(Target: TCustomDrawTarget;
  691. Stage: TCustomDrawStage): Boolean;
  692. begin
  693. Result := inherited IsCustomDrawn(Target, Stage) or
  694. ((Target = dtItem) and (Stage = cdPostPaint));
  695. end;
  696. function TCustomDriveView.CustomDrawItem(Node: TTreeNode; State: TCustomDrawState;
  697. Stage: TCustomDrawStage; var PaintImages: Boolean): Boolean;
  698. var
  699. Point: TPoint;
  700. Index: Integer;
  701. OverlayIndexes: Word;
  702. OverlayIndex: Word;
  703. Image: Word;
  704. begin
  705. Result := inherited CustomDrawItem(Node, State, Stage, PaintImages);
  706. if Result and (Stage = cdPostPaint) then
  707. begin
  708. Assert(Assigned(Node));
  709. OverlayIndexes := NodeOverlayIndexes(Node);
  710. OverlayIndex := 1;
  711. while OverlayIndexes > 0 do
  712. begin
  713. if (OverlayIndex and OverlayIndexes) <> 0 then
  714. begin
  715. Index := 0;
  716. Image := OverlayIndex;
  717. while Image > 1 do
  718. begin
  719. Inc(Index);
  720. Image := Image shr 1;
  721. end;
  722. Point := Node.DisplayRect(True).TopLeft;
  723. Dec(Point.X, Indent);
  724. ImageList_Draw(ImageList.Handle, Index, Self.Canvas.Handle,
  725. Point.X, Point.Y, ILD_TRANSPARENT);
  726. Dec(OverlayIndexes, OverlayIndex);
  727. end;
  728. OverlayIndex := OverlayIndex shl 1;
  729. end;
  730. end;
  731. end;
  732. procedure TCustomDriveView.CNNotify(var Msg: TWMNotify);
  733. begin
  734. case Msg.NMHdr.code of
  735. TVN_BEGINDRAG: DDDragDetect(MK_LBUTTON, FStartPos, Mouse.CursorPos, ddsDrag);
  736. TVN_BEGINRDRAG: DDDragDetect(MK_RBUTTON, FStartPos, Mouse.CursorPos, ddsDrag);
  737. else
  738. inherited;
  739. end;
  740. end; {CNNotify}
  741. procedure TCustomDriveView.CMColorChanged(var Msg: TMessage);
  742. begin
  743. inherited;
  744. if Assigned(Images) then
  745. Images.BkColor := Color;
  746. ForceColorChange(Self);
  747. end;
  748. procedure TCustomDriveView.WMLButtonDown(var Msg: TWMLButtonDown);
  749. begin
  750. if not IsBusy then
  751. begin
  752. FCanChange := False;
  753. GetCursorPos(FStartPos);
  754. inherited;
  755. end;
  756. end; {WMLButtonDown}
  757. procedure TCustomDriveView.WMLButtonUp(var Msg: TWMLButtonDown);
  758. begin
  759. FCanChange := True;
  760. if Assigned(DropTarget) and Assigned(DropTarget.Data) then
  761. Selected := DropTarget;
  762. DropTarget := nil;
  763. inherited;
  764. end; {WMLButtonUp}
  765. procedure TCustomDriveView.WMRButtonDown(var Msg: TWMRButtonDown);
  766. begin
  767. if not IsBusy then
  768. begin
  769. GetCursorPos(FStartPos);
  770. if FDragDropFilesEx.DragDetectStatus <> ddsDrag then
  771. FContextMenu := True;
  772. inherited;
  773. end;
  774. end; {WMRButtonDown}
  775. procedure TCustomDriveView.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  776. begin
  777. if not IsBusy then
  778. begin
  779. inherited;
  780. end;
  781. end;
  782. procedure TCustomDriveView.WMContextMenu(var Msg: TWMContextMenu);
  783. var
  784. Node: TTreeNode;
  785. Point: TPoint;
  786. PrevAutoPopup: Boolean;
  787. begin
  788. PrevAutoPopup := False;
  789. try
  790. if Assigned(PopupMenu) then
  791. begin
  792. PrevAutoPopup := PopupMenu.AutoPopup;
  793. PopupMenu.AutoPopup := False;
  794. end;
  795. inherited;
  796. finally
  797. if Assigned(PopupMenu) then
  798. PopupMenu.AutoPopup := PrevAutoPopup;
  799. end;
  800. FStartPos.X := -1;
  801. FStartPos.Y := -1;
  802. try
  803. if FContextMenu then
  804. begin
  805. Point.X := Msg.XPos;
  806. Point.Y := Msg.YPos;
  807. Point := ScreenToClient(Point);
  808. Node := GetNodeAt(Point.X, Point.Y);
  809. if FUseSystemContextMenu and Assigned(Node) then
  810. begin
  811. if Assigned(OnMouseDown) then
  812. OnMouseDown(Self, mbRight, [], Msg.XPos, Msg.YPos);
  813. DisplayContextMenu(Node, Mouse.CursorPos);
  814. end
  815. else
  816. begin
  817. if Assigned(PopupMenu) then
  818. PopupMenu.Popup(Msg.XPos, Msg.YPos);
  819. end;
  820. end;
  821. FContextMenu := False;
  822. finally
  823. DropTarget := nil;
  824. end;
  825. end; {WMContextMenu}
  826. procedure TCustomDriveView.CMRecreateWnd(var Msg: TMessage);
  827. var
  828. HadHandle: Boolean;
  829. begin
  830. HadHandle := HandleAllocated;
  831. inherited;
  832. // If the control is not showing (e.g. because the machine is locked), the handle is not recreated.
  833. // If contents is reloaded (LoadPath) without handle allocated, it crashes
  834. // (as the handle is implicitly created somewhere in the middle of the reload and chaos ensures).
  835. if HadHandle then
  836. begin
  837. HandleNeeded;
  838. end;
  839. end;
  840. procedure TCustomDriveView.Delete(Node: TTreeNode);
  841. begin
  842. if Node = FDragNode then
  843. FDragNode := nil;
  844. if Node = DropTarget then
  845. begin
  846. DropTarget := nil;
  847. Update;
  848. end;
  849. inherited;
  850. end; {OnDelete}
  851. procedure TCustomDriveView.WMKeyDown(var Message: TWMKeyDown);
  852. begin
  853. if not IsBusy then
  854. begin
  855. inherited;
  856. end;
  857. end;
  858. procedure TCustomDriveView.KeyDown(var Key: Word; Shift: TShiftState);
  859. begin
  860. if (Key = VK_RETURN) and (ssAlt in Shift) and (not IsEditing) and
  861. Assigned(Selected) then
  862. begin
  863. DisplayPropertiesMenu(Selected);
  864. Key := 0;
  865. end;
  866. inherited;
  867. end; {KeyDown}
  868. procedure TCustomDriveView.KeyPress(var Key : Char);
  869. begin
  870. if Assigned(Selected) then
  871. begin
  872. if not IsEditing then
  873. begin
  874. case Key of
  875. #13, ' ':
  876. begin
  877. Selected.Expanded := not Selected.Expanded;
  878. Key := #0;
  879. end;
  880. '/':
  881. begin
  882. Selected.Collapse(True);
  883. Selected.MakeVisible;
  884. Key := #0;
  885. end;
  886. '*':
  887. Selected.MakeVisible;
  888. end {Case}
  889. end
  890. end;
  891. inherited;
  892. end; {KeyPress}
  893. procedure TCustomDriveView.KeyUp(var Key: Word; Shift: TShiftState);
  894. var
  895. Point: TPoint;
  896. begin
  897. inherited;
  898. if (Key = VK_APPS) and Assigned(Selected) then
  899. begin
  900. Point := ClientToScreen(Selected.DisplayRect(True).TopLeft);
  901. Inc(Point.Y, 20);
  902. DisplayContextMenu(Selected, Point);
  903. end;
  904. end; {KeyUp}
  905. procedure TCustomDriveView.ValidateDirectory(Node: TTreeNode);
  906. begin
  907. ValidateDirectoryEx(Node, rsRecursiveExisting, False);
  908. end; {ValidateDirectory}
  909. procedure TCustomDriveView.CenterNode(Node: TTreeNode);
  910. var
  911. NodePos: TRect;
  912. ScrollInfo: TScrollInfo;
  913. begin
  914. if Assigned(Node) and (Items.Count > 0) then
  915. begin
  916. Node.MakeVisible;
  917. NodePos := Node.DisplayRect(False);
  918. with ScrollInfo do
  919. begin
  920. cbSize := SizeOf(ScrollInfo);
  921. fMask := SIF_ALL;
  922. nMin := 0;
  923. nMax := 0;
  924. nPage := 0;
  925. end;
  926. GetScrollInfo(Handle, SB_VERT, ScrollInfo);
  927. if ScrollInfo.nMin <> ScrollInfo.nMax then
  928. begin
  929. {Scroll tree up:}
  930. if (NodePos.Top < Height div 4) and (ScrollInfo.nPos > 0) then
  931. begin
  932. ScrollInfo.fMask := SIF_POS;
  933. while (ScrollInfo.nPos > 0) and (NodePos.Top < (Height div 4)) do
  934. begin
  935. Perform(WM_VSCROLL, SB_LINEUP, 0);
  936. GetScrollInfo(Handle, SB_VERT, ScrollInfo);
  937. NodePos := Node.DisplayRect(False);
  938. end;
  939. end
  940. else
  941. if (NodePos.Top > ((Height * 3) div 4)) then
  942. begin
  943. {Scroll tree down:}
  944. ScrollInfo.fMask := SIF_POS;
  945. while (ScrollInfo.nPos + ABS(ScrollInfo.nPage) < ScrollInfo.nMax) and
  946. (NodePos.Top > ((Height * 3) div 4)) and
  947. (ScrollInfo.nPage > 0) do
  948. begin
  949. Perform(WM_VSCROLL, SB_LINEDOWN, 0);
  950. GetScrollInfo(Handle, SB_VERT, ScrollInfo);
  951. NodePos := Node.DisplayRect(False);
  952. end;
  953. end;
  954. NodePos := Node.DisplayRect(True);
  955. end;
  956. if NodePos.Left < 50 then
  957. Perform(WM_HSCROLL, SB_PAGELEFT, 0);
  958. end;
  959. end; {CenterNode}
  960. procedure TCustomDriveView.DoCompare(Sender: TObject; Node1, Node2: TTreeNode; Data: Integer; var Compare: Integer);
  961. begin
  962. Compare := CompareLogicalTextPas(Node1.Text, Node2.Text, NaturalOrderNumericalSorting);
  963. end;
  964. function TCustomDriveView.SortChildren(ParentNode: TTreeNode; Recurse: Boolean): Boolean;
  965. begin
  966. Result := Assigned(ParentNode) and ParentNode.AlphaSort(Recurse);
  967. end; {SortChildren}
  968. function TCustomDriveView.IterateSubTree(var StartNode : TTreeNode;
  969. CallBackFunc: TCallBackFunc; Recurse: TRecursiveScan;
  970. ScanStartNode: TScanStartNode; Data: Pointer): Boolean;
  971. function ScanSubTree(var StartNode: TTreeNode): Boolean;
  972. var
  973. Node: TTreeNode;
  974. NextNode: TTreeNode;
  975. NodeHasChilds: Boolean;
  976. begin
  977. Result := False;
  978. if not Assigned(StartNode) then Exit;
  979. Node := StartNode.GetFirstChild;
  980. while Assigned(Node) and FContinue do
  981. begin
  982. NextNode := StartNode.GetNextChild(Node);
  983. NodeHasChilds := Node.HasChildren;
  984. if (not FContinue) or (not CallBackFunc(Node, Data)) then Exit;
  985. if Assigned(Node) and
  986. (Recurse = rsRecursiveExisting) and NodeHasChilds then
  987. begin
  988. if (not ScanSubTree(Node)) or (not FContinue) then Exit;
  989. end;
  990. Node := NextNode;
  991. end;
  992. Result := True;
  993. end; {ScanSubTree}
  994. begin {IterateSubTree}
  995. Result := False;
  996. FContinue := True;
  997. if Assigned(CallBackFunc) then
  998. begin
  999. if ScanStartNode = coScanStartNode then
  1000. begin
  1001. CallBackFunc(StartNode, Data);
  1002. end;
  1003. if (not Assigned(StartNode)) or
  1004. FContinue and ScanSubTree(StartNode) then
  1005. begin
  1006. Result := True;
  1007. end;
  1008. end;
  1009. end; {IterateSubTree}
  1010. procedure TCustomDriveView.ClearDragFileList(FileList: TFileList);
  1011. begin
  1012. FileList.Clear;
  1013. end;
  1014. procedure TCustomDriveView.AddToDragFileList(FileList: TFileList; Node: TTreeNode);
  1015. begin
  1016. FileList.AddItem(nil, NodePathName(Node));
  1017. end;
  1018. function TCustomDriveView.NodeCanDrag(Node: TTreeNode): Boolean;
  1019. begin
  1020. Result := True;
  1021. end;
  1022. function TCustomDriveView.NodeOverlayIndexes(Node: TTreeNode): Word;
  1023. begin
  1024. Result := oiNoOverlay;
  1025. end;
  1026. function TCustomDriveView.NodeIsRecycleBin(Node: TTreeNode): Boolean;
  1027. begin
  1028. Result := False;
  1029. end;
  1030. function TCustomDriveView.NodePathExists(Node: TTreeNode): Boolean;
  1031. begin
  1032. Result := True;
  1033. end;
  1034. procedure TCustomDriveView.SetDimmHiddenDirs(Value: Boolean);
  1035. begin
  1036. if Value <> FDimmHiddenDirs then
  1037. begin
  1038. FDimmHiddenDirs := Value;
  1039. Self.Invalidate;
  1040. end;
  1041. end; {SetDimmHiddenDirs}
  1042. procedure TCustomDriveView.SetShowHiddenDirs(Value: Boolean);
  1043. begin
  1044. if Value <> FShowHiddenDirs then
  1045. begin
  1046. FShowHiddenDirs := Value;
  1047. RebuildTree;
  1048. end;
  1049. end; {SetDimmHiddenDirs}
  1050. procedure TCustomDriveView.SetNaturalOrderNumericalSorting(Value: Boolean);
  1051. begin
  1052. if NaturalOrderNumericalSorting <> Value then
  1053. begin
  1054. FNaturalOrderNumericalSorting := Value;
  1055. AlphaSort;
  1056. end;
  1057. end;
  1058. function TCustomDriveView.GetTargetPopupMenu: Boolean;
  1059. begin
  1060. if Assigned(FDragDropFilesEx) then Result := FDragDropFilesEx.TargetPopupMenu
  1061. else Result := True;
  1062. end;
  1063. procedure TCustomDriveView.SetTargetPopUpMenu(Value: Boolean);
  1064. begin
  1065. if Assigned(FDragDropFilesEx) then
  1066. FDragDropFilesEx.TargetPopupMenu := Value;
  1067. end; {SetTargetPopUpMenu}
  1068. function TCustomDriveView.GetDirectory: string;
  1069. begin
  1070. if Assigned(Selected) then Result := NodePathName(Selected)
  1071. else Result := '';
  1072. end; {GetDirectory}
  1073. procedure TCustomDriveView.SetDirectory(Value: string);
  1074. var
  1075. NewSelected: TTreeNode;
  1076. Rect: TRect;
  1077. begin
  1078. NewSelected := FindPathNode(Value);
  1079. if Assigned(NewSelected) and (NewSelected <> Selected) then
  1080. begin
  1081. FCanChange := True;
  1082. NewSelected.MakeVisible;
  1083. Rect := NewSelected.DisplayRect(False);
  1084. Selected := NewSelected;
  1085. end
  1086. else
  1087. if csDesigning in ComponentState then
  1088. Selected := nil;
  1089. end; {SetDirectory}
  1090. function TCustomDriveView.DoBusy(Busy: Integer): Boolean;
  1091. begin
  1092. Result := True;
  1093. if Assigned(OnBusy) then
  1094. begin
  1095. OnBusy(Self, Busy, Result);
  1096. end;
  1097. end;
  1098. function TCustomDriveView.StartBusy: Boolean;
  1099. begin
  1100. Result := DoBusy(1);
  1101. end;
  1102. function TCustomDriveView.IsBusy: Boolean;
  1103. begin
  1104. Result := DoBusy(0);
  1105. end;
  1106. procedure TCustomDriveView.EndBusy;
  1107. begin
  1108. DoBusy(-1);
  1109. end;
  1110. end.