NortonLikeListView.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. unit NortonLikeListView;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5. ComCtrls, ListViewColProperties, CommCtrl;
  6. type
  7. TCustomNortonLikeListView = class;
  8. TSelectMode = (smAll, smNone, smInvert);
  9. TNortonLikeMode = (nlOn, nlOff, nlKeyboard);
  10. TSelectByMaskEvent = procedure(Control: TCustomNortonLikeListView; Select: Boolean) of object;
  11. TCustomNortonLikeListView = class(TCustomListView)
  12. private
  13. { Private declarations }
  14. FColProperties: TCustomListViewColProperties;
  15. FDontSelectItem: Boolean;
  16. FDontUnSelectItem: Boolean;
  17. FSelCount: Integer;
  18. FNortonLike: TNortonLikeMode;
  19. FOnSelectByMask: TSelectByMaskEvent;
  20. FLastDeletedItem: TListItem; // aby sme nepocitali smazany item 2x
  21. FFocusingItem: Boolean;
  22. FManageSelection: Boolean;
  23. FFirstSelected: Integer;
  24. FLastSelected: Integer;
  25. procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  26. procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
  27. procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
  28. procedure WMChar(var Message: TWMChar); message WM_CHAR;
  29. procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
  30. procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  31. function GetMarkedCount: Integer;
  32. function GetMarkedFile: TListItem;
  33. procedure ItemSelected(Item: TListItem; Index: Integer);
  34. procedure ItemUnselected(Item: TListItem; Index: Integer);
  35. protected
  36. { Protected declarations }
  37. FClearingItems: Boolean;
  38. FUpdatingSelection: Integer;
  39. procedure CreateWnd; override;
  40. procedure BeginSelectionUpdate; virtual;
  41. procedure EndSelectionUpdate; virtual;
  42. function CanChangeSelection(Item: TListItem; Select: Boolean): Boolean; virtual;
  43. procedure ClearItems; virtual;
  44. procedure ColRightClick(Column: TListColumn; Point: TPoint); override;
  45. procedure Delete(Item: TListItem); override;
  46. function DoSelectByMask(Select: Boolean): Boolean; virtual;
  47. function ExCanChange(Item: TListItem; Change: Integer;
  48. NewState, OldState: Word): Boolean; dynamic;
  49. procedure InsertItem(Item: TListItem); override;
  50. function NewColProperties: TCustomListViewColProperties; virtual;
  51. procedure FocusSomething; virtual;
  52. function EnableDragOnClick: Boolean; virtual;
  53. procedure FocusItem(Item: TListItem);
  54. function GetItemFromHItem(const Item: TLVItem): TListItem;
  55. function GetValid: Boolean; virtual;
  56. function GetSelCount: Integer; override;
  57. procedure DDBeforeDrag;
  58. public
  59. { Public declarations }
  60. constructor Create(AOwner: TComponent); override;
  61. destructor Destroy; override;
  62. function ClosestUnselected(Item: TListItem): TListItem;
  63. procedure SelectAll(Mode: TSelectMode); reintroduce;
  64. procedure SelectCurrentItem(FocusNext: Boolean);
  65. function GetNextItem(StartItem: TListItem; Direction: TSearchDirection;
  66. States: TItemStates): TListItem;
  67. property ColProperties: TCustomListViewColProperties read FColProperties write FColProperties stored False;
  68. property MultiSelect default True;
  69. property NortonLike: TNortonLikeMode read FNortonLike write FNortonLike default nlOn;
  70. property OnSelectByMask: TSelectByMaskEvent read FOnSelectByMask write FOnSelectByMask;
  71. property MarkedCount: Integer read GetMarkedCount;
  72. property MarkedFile: TListItem read GetMarkedFile;
  73. property Valid: Boolean read GetValid;
  74. end;
  75. type
  76. TNortonLikeListView = class(TCustomNortonLikeListView)
  77. published
  78. { Published declarations }
  79. property Align;
  80. property AllocBy;
  81. property Anchors;
  82. property BiDiMode;
  83. property BorderStyle;
  84. property BorderWidth;
  85. property Checkboxes;
  86. property Color;
  87. property ColumnClick;
  88. property Constraints;
  89. property Ctl3D;
  90. property Enabled;
  91. property Font;
  92. property FlatScrollBars;
  93. property FullDrag;
  94. property GridLines;
  95. property HideSelection;
  96. property HotTrack;
  97. property HotTrackStyles;
  98. property IconOptions;
  99. property Items;
  100. property LargeImages;
  101. property ReadOnly;
  102. property RowSelect;
  103. property ParentBiDiMode;
  104. property ParentColor;
  105. property ParentFont;
  106. property ParentShowHint;
  107. property PopupMenu;
  108. property ShowColumnHeaders;
  109. property ShowHint;
  110. property SmallImages;
  111. property StateImages;
  112. property TabOrder;
  113. property TabStop;
  114. property ViewStyle;
  115. property Visible;
  116. property OnChange;
  117. property OnChanging;
  118. property OnClick;
  119. property OnColumnClick;
  120. property OnCustomDraw;
  121. property OwnerDraw;
  122. property OnCustomDrawItem;
  123. property OnCustomDrawSubItem;
  124. property OwnerData;
  125. property OnGetImageIndex;
  126. property OnCompare;
  127. property OnData;
  128. property OnDataFind;
  129. property OnDataHint;
  130. property OnDataStateChange;
  131. property OnDblClick;
  132. property OnDeletion;
  133. property OnDrawItem;
  134. property OnEdited;
  135. property OnEditing;
  136. property OnEndDock;
  137. property OnEnter;
  138. property OnExit;
  139. property OnInsert;
  140. property OnKeyDown;
  141. property OnKeyPress;
  142. property OnKeyUp;
  143. property OnMouseDown;
  144. property OnMouseMove;
  145. property OnMouseUp;
  146. property OnResize;
  147. property OnStartDock;
  148. property OnSelectItem;
  149. property NortonLike;
  150. property OnSelectByMask;
  151. property ColProperties;
  152. end;
  153. procedure Register;
  154. implementation
  155. uses
  156. PasTools;
  157. procedure Register;
  158. begin
  159. RegisterComponents('Martin', [TNortonLikeListView]);
  160. end;
  161. { TCustomNortonLikeListView }
  162. constructor TCustomNortonLikeListView.Create(AOwner: TComponent);
  163. begin
  164. inherited Create(AOwner);
  165. FSelCount := 0;
  166. FFirstSelected := -1;
  167. FLastSelected := -1;
  168. FClearingItems := False;
  169. MultiSelect := True;
  170. FDontSelectItem := False;
  171. FDontUnSelectItem := False;
  172. FNortonLike := nlOn;
  173. FColProperties := NewColProperties;
  174. FLastDeletedItem := nil;
  175. FUpdatingSelection := 0;
  176. FFocusingItem := False;
  177. // On Windows Vista, native GetNextItem for selection stops working once we
  178. // disallow deselecting any item (see ExCanChange).
  179. // So we need to manage selection state ourselves
  180. // cannot use Win32MajorVersion as it is affected by compatibility mode and
  181. // the bug is present even in compatibility mode
  182. FManageSelection := IsVista;
  183. end;
  184. destructor TCustomNortonLikeListView.Destroy;
  185. begin
  186. FColProperties.Free;
  187. inherited;
  188. end;
  189. procedure TCustomNortonLikeListView.ItemSelected(Item: TListItem; Index: Integer);
  190. begin
  191. Inc(FSelCount);
  192. if FManageSelection then
  193. begin
  194. if Index < 0 then
  195. Index := Item.Index;
  196. if FSelCount = 1 then
  197. begin
  198. Assert(FFirstSelected < 0);
  199. FFirstSelected := Index;
  200. Assert(FLastSelected < 0);
  201. FLastSelected := Index;
  202. end
  203. else
  204. begin
  205. // if reference is not assigned, do not assign it as we
  206. // cannot be sure that the item is actually first/last
  207. if (FFirstSelected >= 0) and (Index < FFirstSelected) then
  208. FFirstSelected := Index;
  209. if (FLastSelected >= 0) and (Index > FLastSelected) then
  210. FLastSelected := Index;
  211. end;
  212. end;
  213. end;
  214. procedure TCustomNortonLikeListView.ItemUnselected(Item: TListItem; Index: Integer);
  215. begin
  216. Dec(FSelCount);
  217. if FManageSelection then
  218. begin
  219. if Index < 0 then
  220. Index := Item.Index;
  221. if FFirstSelected = Index then
  222. begin
  223. if FSelCount = 1 then
  224. FFirstSelected := FLastSelected // may be -1
  225. else
  226. FFirstSelected := -1;
  227. end;
  228. if FLastSelected = Index then
  229. begin
  230. if FSelCount = 1 then
  231. FLastSelected := FFirstSelected // may be -1
  232. else
  233. FLastSelected := -1;
  234. end;
  235. end;
  236. end;
  237. procedure TCustomNortonLikeListView.Delete(Item: TListItem);
  238. begin
  239. if (FLastDeletedItem <> Item) and Item.Selected then
  240. begin
  241. ItemUnselected(Item, -1);
  242. end;
  243. FLastDeletedItem := Item;
  244. inherited;
  245. FLastDeletedItem := nil;
  246. end;
  247. function TCustomNortonLikeListView.DoSelectByMask(Select: Boolean): Boolean;
  248. begin
  249. if Assigned(FOnSelectByMask) then
  250. begin
  251. FOnSelectByMask(Self, Select);
  252. Result := True;
  253. end
  254. else Result := False;
  255. end;
  256. function TCustomNortonLikeListView.ExCanChange(Item: TListItem; Change: Integer;
  257. NewState, OldState: Word): Boolean;
  258. begin
  259. Assert(Assigned(Item));
  260. Result := True;
  261. if (Change = LVIF_STATE) and
  262. ((((OldState and LVIS_SELECTED) < (NewState and LVIS_SELECTED)) and
  263. (FDontSelectItem or (not CanChangeSelection(Item, True)))) or
  264. (((OldState and LVIS_SELECTED) > (NewState and LVIS_SELECTED)) and
  265. (FDontUnSelectItem or (not CanChangeSelection(Item, False))))) then
  266. begin
  267. if (OldState or LVIS_SELECTED) <> (NewState or LVIS_SELECTED) then
  268. begin
  269. ListView_SetItemState(Handle, Item.Index, NewState,
  270. (NewState or OldState) - LVIS_SELECTED);
  271. end;
  272. Result := False;
  273. end;
  274. end;
  275. function TCustomNortonLikeListView.CanChangeSelection(Item: TListItem;
  276. Select: Boolean): Boolean;
  277. begin
  278. Result := True;
  279. end;
  280. procedure TCustomNortonLikeListView.ClearItems;
  281. begin
  282. Items.BeginUpdate;
  283. try
  284. FClearingItems := True;
  285. Items.Clear;
  286. finally
  287. FSelCount := 0;
  288. if FManageSelection then
  289. begin
  290. FFirstSelected := -1;
  291. FLastSelected := -1;
  292. end;
  293. FClearingItems := False;
  294. Items.EndUpdate;
  295. end;
  296. end; { ClearItems }
  297. procedure TCustomNortonLikeListView.ColRightClick(Column: TListColumn; Point: TPoint);
  298. var
  299. HitInfo: TLVHitTestInfo;
  300. begin
  301. // Fix: Otherwise we get wrong column when view is horizontally scrolled
  302. HitInfo.pt := Point;
  303. if ListView_SubItemHitTest(Handle, @HitInfo) = 0 then
  304. Column := Columns[HitInfo.iSubItem];
  305. inherited ColRightClick(Column, Point);
  306. end;
  307. function TCustomNortonLikeListView.ClosestUnselected(Item: TListItem): TListItem;
  308. var
  309. Index: Integer;
  310. begin
  311. if Assigned(Item) and (Item.Selected or ((NortonLike <> nlOff) and (SelCount = 0))) then
  312. begin
  313. Index := Item.Index + 1;
  314. while (Index < Items.Count) and Items[Index].Selected do Inc(Index);
  315. if (Index >= Items.Count) or Items[Index].Selected then
  316. begin
  317. Index := Item.Index - 1;
  318. while (Index >= 0) and Items[Index].Selected do Dec(Index);
  319. end;
  320. if (Index >= 0) and (Index < Items.Count) and (not Items[Index].Selected) then
  321. Result := Items[Index]
  322. else
  323. Result := nil;
  324. end
  325. else Result := Item;
  326. end;
  327. procedure TCustomNortonLikeListView.WMNotify(var Message: TWMNotify);
  328. begin
  329. // disallow resizing of "invisible" (width=0) columns
  330. with PHDNotify(Message.NMHdr)^ do
  331. case Hdr.code of
  332. HDN_BEGINTRACK, HDN_TRACK, HDN_BEGINTRACKW, HDN_TRACKW:
  333. if not ColProperties.Visible[Item] then
  334. begin
  335. Message.Result := 1;
  336. Exit;
  337. end;
  338. end;
  339. inherited;
  340. end;
  341. procedure TCustomNortonLikeListView.DDBeforeDrag;
  342. begin
  343. FDontSelectItem := False;
  344. FDontUnSelectItem := False;
  345. end;
  346. procedure TCustomNortonLikeListView.CNNotify(var Message: TWMNotify);
  347. var
  348. Item: TListItem;
  349. begin
  350. with Message do
  351. case NMHdr^.code of
  352. LVN_ITEMCHANGING:
  353. with PNMListView(NMHdr)^ do
  354. begin
  355. Item := Items[iItem];
  356. if Valid and (not FClearingItems) and (Item <> FLastDeletedItem) and
  357. ((not CanChange(Item, uChanged)) or
  358. (not ExCanChange(Item, uChanged, uNewState, uOldState)))
  359. then
  360. begin
  361. Result := 1;
  362. end;
  363. end;
  364. LVN_ITEMCHANGED:
  365. begin
  366. with PNMListView(NMHdr)^ do
  367. begin
  368. Item := Items[iItem];
  369. if Valid and (not FClearingItems) and
  370. (uChanged = LVIF_STATE) and (Item <> FLastDeletedItem) and
  371. ((uOldState and LVIS_SELECTED) <> (uNewState and LVIS_SELECTED)) then
  372. begin
  373. if (uOldState and LVIS_SELECTED) <> 0 then
  374. begin
  375. ItemUnselected(Item, iItem);
  376. end
  377. else
  378. begin
  379. ItemSelected(Item, iItem);
  380. end;
  381. end;
  382. end;
  383. inherited;
  384. end;
  385. else
  386. inherited;
  387. end;
  388. end;
  389. procedure TCustomNortonLikeListView.SelectCurrentItem(FocusNext: Boolean);
  390. var
  391. Item: TListItem;
  392. begin
  393. Item := ItemFocused;
  394. if Item = nil then Item := Items[0];
  395. Item.Selected := not Item.Selected;
  396. if FocusNext then
  397. begin
  398. SendMessage(Handle, WM_KEYDOWN, VK_DOWN, LongInt(0));
  399. end;
  400. end;
  401. procedure TCustomNortonLikeListView.WMKeyDown(var Message: TWMKeyDown);
  402. var
  403. PDontUnSelectItem: Boolean;
  404. PDontSelectItem: Boolean;
  405. begin
  406. if (NortonLike <> nlOff) and (Message.CharCode = VK_INSERT) then
  407. begin
  408. if Items.Count > 0 then
  409. begin
  410. SelectCurrentItem(True);
  411. Message.Result := 1;
  412. end;
  413. end
  414. else
  415. {if (NortonLike <> nlOff) and (Message.CharCode = VK_MULTIPLY) then
  416. begin
  417. SelectAll(smInvert)
  418. Message.Result := 1;
  419. end
  420. else }
  421. if (Message.CharCode = VK_ADD) or (Message.CharCode = VK_SUBTRACT) then
  422. begin
  423. if DoSelectByMask((Message.CharCode = VK_ADD)) then
  424. Message.Result := 1;
  425. end
  426. else
  427. if (NortonLike <> nlOff) and (Message.CharCode in [VK_LEFT, VK_RIGHT]) and
  428. (ViewStyle = vsReport) and
  429. ((GetWindowLong(Handle, GWL_STYLE) and WS_HSCROLL) = 0) then
  430. begin
  431. if Items.Count > 0 then
  432. begin
  433. // do not focus item directly to make later selecting work
  434. if Message.CharCode = VK_LEFT then
  435. SendMessage(Handle, WM_KEYDOWN, VK_HOME, LongInt(0))
  436. else
  437. SendMessage(Handle, WM_KEYDOWN, VK_END, LongInt(0));
  438. end;
  439. Message.Result := 1;
  440. end
  441. else
  442. if (Message.CharCode in [VK_SPACE, VK_PRIOR, VK_NEXT, VK_END, VK_HOME, VK_LEFT,
  443. VK_UP, VK_RIGHT, VK_DOWN, VK_SELECT]) then
  444. begin
  445. PDontSelectItem := FDontSelectItem;
  446. PDontUnSelectItem := FDontUnSelectItem;
  447. FDontSelectItem := FDontSelectItem or
  448. ((NortonLike <> nlOff) and
  449. ((KeyDataToShiftState(Message.KeyData) * [ssShift]) = []));
  450. FDontUnSelectItem := FDontUnSelectItem or (NortonLike <> nlOff);
  451. try
  452. inherited;
  453. finally
  454. FDontSelectItem := PDontSelectItem;
  455. FDontUnSelectItem := PDontUnSelectItem;
  456. end;
  457. end
  458. else inherited;
  459. end;
  460. procedure TCustomNortonLikeListView.WMChar(var Message: TWMChar);
  461. var
  462. PDontUnSelectItem: Boolean;
  463. PDontSelectItem: Boolean;
  464. begin
  465. if Message.CharCode in [Word('+'), Word('-'), Word('*')] then
  466. begin
  467. // ugly fix to avoid Windows beeping when these keys are processed by
  468. // WMKeyDown instead of here (WMChar)
  469. Message.Result := 1;
  470. end
  471. else
  472. if (NortonLike <> nlOff) and (Message.CharCode = Byte(' ')) then
  473. begin
  474. if (GetKeyState(VK_CONTROL) >= 0) then
  475. begin
  476. if Assigned(ItemFocused) then
  477. ItemFocused.Selected := not ItemFocused.Selected;
  478. end
  479. else inherited;
  480. end
  481. else
  482. begin
  483. PDontSelectItem := FDontSelectItem;
  484. PDontUnSelectItem := FDontUnSelectItem;
  485. FDontSelectItem := FDontSelectItem or (NortonLike <> nlOff);
  486. FDontUnSelectItem := FDontUnSelectItem or (NortonLike <> nlOff);
  487. try
  488. inherited;
  489. finally
  490. FDontSelectItem := PDontSelectItem;
  491. FDontUnSelectItem := PDontUnSelectItem;
  492. end;
  493. end;
  494. end;
  495. procedure TCustomNortonLikeListView.FocusSomething;
  496. begin
  497. if Valid and (Items.Count > 0) and not Assigned(ItemFocused) then
  498. begin
  499. if (NortonLike <> nlOff) then SendMessage(Handle, WM_KEYDOWN, VK_DOWN, LongInt(0));
  500. if not Assigned(ItemFocused) then
  501. ItemFocused := Items[0];
  502. end;
  503. if Assigned(ItemFocused) then
  504. ItemFocused.MakeVisible(False);
  505. end;
  506. function TCustomNortonLikeListView.EnableDragOnClick: Boolean;
  507. begin
  508. Result := (not FFocusingItem);
  509. end;
  510. procedure TCustomNortonLikeListView.FocusItem(Item: TListItem);
  511. var
  512. P: TPoint;
  513. PDontUnSelectItem: Boolean;
  514. PDontSelectItem: Boolean;
  515. begin
  516. Item.MakeVisible(False);
  517. if Focused then
  518. begin
  519. P := Item.GetPosition;
  520. PDontSelectItem := FDontSelectItem;
  521. PDontUnSelectItem := FDontUnSelectItem;
  522. FDontSelectItem := True;
  523. FDontUnSelectItem := True;
  524. FFocusingItem := True;
  525. try
  526. SendMessage(Handle, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(P.X, P.Y));
  527. finally
  528. FFocusingItem := False;
  529. FDontSelectItem := PDontSelectItem;
  530. FDontUnSelectItem := PDontUnSelectItem;
  531. end;
  532. Assert(ItemFocused = Item);
  533. end;
  534. if ItemFocused <> Item then
  535. ItemFocused := Item;
  536. end;
  537. procedure TCustomNortonLikeListView.SelectAll(Mode: TSelectMode);
  538. var
  539. Index: Integer;
  540. Item: TListItem;
  541. begin
  542. BeginSelectionUpdate;
  543. try
  544. for Index := 0 to Items.Count - 1 do
  545. begin
  546. Item := Items[Index];
  547. case Mode of
  548. smAll: Item.Selected := True;
  549. smNone: Item.Selected := False;
  550. smInvert: Item.Selected := not Item.Selected;
  551. end;
  552. end;
  553. finally
  554. EndSelectionUpdate;
  555. end;
  556. end;
  557. procedure TCustomNortonLikeListView.WMLButtonDown(var Message: TWMLButtonDown);
  558. var
  559. PDontUnSelectItem: Boolean;
  560. PDontSelectItem: Boolean;
  561. Shift: TShiftState;
  562. begin
  563. Shift := KeysToShiftState(Message.Keys);
  564. PDontSelectItem := FDontSelectItem;
  565. PDontUnSelectItem := FDontUnSelectItem;
  566. FDontSelectItem := FDontSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl, ssShift]) = []));
  567. FDontUnSelectItem := FDontUnSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl]) = []));
  568. try
  569. inherited;
  570. finally
  571. FDontSelectItem := PDontSelectItem;
  572. FDontUnSelectItem := PDontUnSelectItem;
  573. end;
  574. end;
  575. procedure TCustomNortonLikeListView.WMRButtonDown(var Message: TWMRButtonDown);
  576. var
  577. PDontUnSelectItem: Boolean;
  578. PDontSelectItem: Boolean;
  579. begin
  580. PDontSelectItem := FDontSelectItem;
  581. PDontUnSelectItem := FDontUnSelectItem;
  582. FDontSelectItem := FDontSelectItem or (NortonLike = nlOn);
  583. FDontUnSelectItem := FDontUnSelectItem or (NortonLike = nlOn);
  584. try
  585. inherited;
  586. finally
  587. FDontSelectItem := PDontSelectItem;
  588. FDontUnSelectItem := PDontUnSelectItem;
  589. end;
  590. end;
  591. function TCustomNortonLikeListView.GetMarkedFile: TListItem;
  592. begin
  593. if Assigned(Selected) then Result := Selected
  594. else
  595. if Assigned(ItemFocused) and (NortonLike <> nlOff) then Result := ItemFocused
  596. else Result := nil;
  597. end;
  598. function TCustomNortonLikeListView.GetNextItem(StartItem: TListItem;
  599. Direction: TSearchDirection; States: TItemStates): TListItem;
  600. var
  601. Start, Index, First, Last: Integer;
  602. begin
  603. if not FManageSelection then
  604. begin
  605. Result := inherited GetNextItem(StartItem, Direction, States);
  606. end
  607. else
  608. begin
  609. Assert(Direction = sdAll);
  610. if States = [isSelected] then
  611. begin
  612. if FSelCount = 0 then
  613. begin
  614. Result := nil
  615. end
  616. else
  617. if (not Assigned(StartItem)) and (FFirstSelected >= 0) then
  618. begin
  619. Result := Items[FFirstSelected]
  620. end
  621. else
  622. begin
  623. if Assigned(StartItem) then
  624. Start := StartItem.Index
  625. else
  626. Start := -1;
  627. if (FFirstSelected >= 0) and (Start < FFirstSelected) then
  628. First := FFirstSelected
  629. else
  630. First := Start + 1;
  631. if FLastSelected >= 0 then
  632. Last := FLastSelected
  633. else
  634. Last := Items.Count - 1;
  635. if Start > Last then
  636. begin
  637. Result := nil;
  638. end
  639. else
  640. begin
  641. Index := First;
  642. while (Index <= Last) and (not (Items[Index].Selected)) do
  643. begin
  644. Inc(Index);
  645. end;
  646. if Index > Last then
  647. begin
  648. Result := nil;
  649. if Assigned(StartItem) and StartItem.Selected then
  650. begin
  651. Assert((FLastSelected < 0) or (FLastSelected = Start));
  652. FLastSelected := Start;
  653. end;
  654. end
  655. else
  656. begin
  657. Result := Items[Index];
  658. Assert(Result.Selected);
  659. if not Assigned(StartItem) then
  660. begin
  661. Assert((FFirstSelected < 0) or (FFirstSelected = Index));
  662. FFirstSelected := Index;
  663. end;
  664. end;
  665. end;
  666. end;
  667. end
  668. else
  669. if States = [isCut] then
  670. begin
  671. Result := inherited GetNextItem(StartItem, Direction, States);
  672. end
  673. else
  674. begin
  675. Assert(False);
  676. Result := nil;
  677. end;
  678. end;
  679. end;
  680. function TCustomNortonLikeListView.GetSelCount: Integer;
  681. begin
  682. Result := FSelCount;
  683. end;
  684. procedure TCustomNortonLikeListView.InsertItem(Item: TListItem);
  685. begin
  686. inherited;
  687. if Item.Selected then
  688. ItemSelected(Item, -1);
  689. end;
  690. function TCustomNortonLikeListView.NewColProperties: TCustomListViewColProperties;
  691. begin
  692. Result := TListViewColProperties.Create(Self, 5);
  693. end;
  694. function TCustomNortonLikeListView.GetItemFromHItem(const Item: TLVItem): TListItem;
  695. begin
  696. with Item do
  697. if (state and LVIF_PARAM) <> 0 then Result := Pointer(lParam)
  698. else Result := Items[iItem];
  699. end;
  700. function TCustomNortonLikeListView.GetMarkedCount: Integer;
  701. begin
  702. if (SelCount > 0) or (NortonLike = nlOff) then Result := SelCount
  703. else
  704. if Assigned(ItemFocused) then Result := 1
  705. else Result := 0;
  706. end;
  707. function TCustomNortonLikeListView.GetValid: Boolean;
  708. begin
  709. // Note that TCustomDirView::GetValid don't inherit
  710. // this method because of optimalization
  711. Result := (not (csDestroying in ComponentState)) and (not FClearingItems);
  712. end;
  713. procedure TCustomNortonLikeListView.BeginSelectionUpdate;
  714. begin
  715. // Higher value is probably some nesting error
  716. Assert(FUpdatingSelection in [0..4]);
  717. Inc(FUpdatingSelection);
  718. end; { BeginUpdatingSelection }
  719. procedure TCustomNortonLikeListView.EndSelectionUpdate;
  720. begin
  721. Assert(FUpdatingSelection > 0);
  722. Dec(FUpdatingSelection);
  723. end; { EndUpdatingSelection }
  724. procedure TCustomNortonLikeListView.CreateWnd;
  725. begin
  726. inherited;
  727. Assert(ColProperties <> nil);
  728. ColProperties.ListViewWndCreated;
  729. end;
  730. end.