CustomDriveView.pas 37 KB

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