CustomDriveView.pas 38 KB

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