CustomDriveView.pas 38 KB

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