CustomDriveView.pas 40 KB

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