CustomDriveView.pas 40 KB

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