| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059 | 
							- unit NortonLikeListView;
 
- interface
 
- uses
 
-   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 
-   ComCtrls, ListViewColProperties, CommCtrl, Menus;
 
- type
 
-   TCustomNortonLikeListView = class;
 
-   TSelectMode = (smAll, smNone, smInvert);
 
-   TNortonLikeMode = (nlOn, nlOff, nlKeyboard);
 
-   TSelectMethod = (smNoneYet, smMouse, smKeyboard);
 
-   TCustomNortonLikeListView = class(TCustomListView)
 
-   private
 
-     { Private declarations }
 
-     FColProperties: TCustomListViewColProperties;
 
-     FDontSelectItem: Boolean;
 
-     FDontUnSelectItem: Boolean;
 
-     FSelCount: Integer;
 
-     FNortonLike: TNortonLikeMode;
 
-     FLastDeletedItem: TListItem; // aby sme nepocitali smazany item 2x
 
-     FFocusingItem: Boolean;
 
-     FManageSelection: Boolean;
 
-     FForceUpdateOnItemUnfocus: Boolean;
 
-     FFirstSelected: Integer;
 
-     FLastSelected: Integer;
 
-     FFocused: TDateTime;
 
-     FIgnoreSetFocusFrom: THandle;
 
-     FSelectingImplicitly: Boolean;
 
-     FAnyAndAllSelectedImplicitly: Boolean;
 
-     FLButtonDownShiftState: TShiftState;
 
-     FLButtonDownPos: TPoint;
 
-     FLastSelectMethod: TSelectMethod;
 
-     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
 
-     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
 
-     procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
 
-     procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
 
-     procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
 
-     procedure WMChar(var Message: TWMChar); message WM_CHAR;
 
-     procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
 
-     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
 
-     procedure LVMEditLabel(var Message: TMessage); message LVM_EDITLABEL;
 
-     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
 
-     procedure CMWantSpecialKey(var Message: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
 
-     function GetMarkedCount: Integer;
 
-     function GetMarkedFile: TListItem;
 
-     procedure ItemSelected(Item: TListItem; Index: Integer);
 
-     procedure ItemUnselected(Item: TListItem; Index: Integer);
 
-     procedure SelectAll(Mode: TSelectMode; Exclude: TListItem); reintroduce; overload;
 
-   protected
 
-     { Protected declarations }
 
-     FClearingItems: Boolean;
 
-     FUpdatingSelection: Integer;
 
-     FNextCharToIgnore: Word;
 
-     FHeaderHandle: HWND;
 
-     procedure CreateWnd; override;
 
-     procedure DestroyWnd; override;
 
-     procedure BeginSelectionUpdate; virtual;
 
-     procedure EndSelectionUpdate; virtual;
 
-     function CanChangeSelection(Item: TListItem; Select: Boolean): Boolean; virtual;
 
-     procedure ClearItems; virtual;
 
-     procedure ItemsReordered;
 
-     procedure Delete(Item: TListItem); override;
 
-     function ExCanChange(Item: TListItem; Change: Integer;
 
-       NewState, OldState: Word): Boolean; dynamic;
 
-     procedure InsertItem(Item: TListItem); override;
 
-     function NewColProperties: TCustomListViewColProperties; virtual; abstract;
 
-     procedure FocusSomething; virtual;
 
-     function EnableDragOnClick: Boolean; virtual;
 
-     function GetItemFromHItem(const Item: TLVItem): TListItem;
 
-     function GetValid: Boolean; virtual;
 
-     function GetSelCount: Integer; override;
 
-     procedure DDBeforeDrag;
 
-     function CanEdit(Item: TListItem): Boolean; override;
 
-     function GetPopupMenu: TPopupMenu; override;
 
-     procedure ChangeScale(M, D: Integer); override;
 
-   public
 
-     { Public declarations }
 
-     constructor Create(AOwner: TComponent); override;
 
-     destructor Destroy; override;
 
-     function ClosestUnselected(Item: TListItem): TListItem;
 
-     procedure SelectAll(Mode: TSelectMode); reintroduce; overload;
 
-     procedure SelectCurrentItem(FocusNext: Boolean);
 
-     function GetNextItem(StartItem: TListItem; Direction: TSearchDirection;
 
-       States: TItemStates): TListItem;
 
-     procedure MakeProgressVisible(Item: TListItem);
 
-     procedure FocusItem(Item: TListItem);
 
-     property ColProperties: TCustomListViewColProperties read FColProperties write FColProperties stored False;
 
-     property MultiSelect default True;
 
-     property NortonLike: TNortonLikeMode read FNortonLike write FNortonLike default nlOn;
 
-     property MarkedCount: Integer read GetMarkedCount;
 
-     property MarkedFile: TListItem read GetMarkedFile;
 
-     property Valid: Boolean read GetValid;
 
-     property LastSelectMethod: TSelectMethod read FLastSelectMethod;
 
-   end;
 
- implementation
 
- uses
 
-   PasTools, Types;
 
-   { TCustomNortonLikeListView }
 
- constructor TCustomNortonLikeListView.Create(AOwner: TComponent);
 
- begin
 
-   inherited Create(AOwner);
 
-   FSelCount := 0;
 
-   FFirstSelected := -1;
 
-   FLastSelected := -1;
 
-   FClearingItems := False;
 
-   MultiSelect := True;
 
-   FDontSelectItem := False;
 
-   FDontUnSelectItem := False;
 
-   FNortonLike := nlOn;
 
-   FColProperties := NewColProperties;
 
-   FLastDeletedItem := nil;
 
-   FUpdatingSelection := 0;
 
-   FFocusingItem := False;
 
-   FLastSelectMethod := smNoneYet;
 
-   // On Windows Vista, native GetNextItem for selection stops working once we
 
-   // disallow deselecting any item (see ExCanChange).
 
-   // So we need to manage selection state ourselves
 
-   // cannot use Win32MajorVersion as it is affected by compatibility mode and
 
-   // the bug is present even in compatibility mode
 
-   FManageSelection := IsVistaHard;
 
-   FFocused := 0;
 
-   FIgnoreSetFocusFrom := INVALID_HANDLE_VALUE;
 
-   // On Windows 7 we have to force item update when it looses focus,
 
-   // otherwise some remnants of focus rectangle remain
 
-   // Doing the same on WinXP makes list view down from the item flicker,
 
-   // so we avoid this there.
 
-   // Not sure about Vista
 
-   FForceUpdateOnItemUnfocus := IsWin7;
 
-   FNextCharToIgnore := 0;
 
- end;
 
- destructor TCustomNortonLikeListView.Destroy;
 
- begin
 
-   FColProperties.Free;
 
-   inherited;
 
- end;
 
- procedure TCustomNortonLikeListView.ItemSelected(Item: TListItem; Index: Integer);
 
- begin
 
-   Inc(FSelCount);
 
-   if FSelectingImplicitly and (FSelCount = 1) then
 
-   begin
 
-     FAnyAndAllSelectedImplicitly := True;
 
-   end
 
-     else
 
-   if not FSelectingImplicitly then
 
-   begin
 
-     FAnyAndAllSelectedImplicitly := False;
 
-   end;
 
-   if FManageSelection then
 
-   begin
 
-     if Index < 0 then
 
-       Index := Item.Index;
 
-     if FSelCount = 1 then
 
-     begin
 
-       Assert(FFirstSelected < 0);
 
-       FFirstSelected := Index;
 
-       Assert(FLastSelected < 0);
 
-       FLastSelected := Index;
 
-     end
 
-       else
 
-     begin
 
-       // if reference is not assigned, do not assign it as we
 
-       // cannot be sure that the item is actually first/last
 
-       if (FFirstSelected >= 0) and (Index < FFirstSelected) then
 
-         FFirstSelected := Index;
 
-       if (FLastSelected >= 0) and (Index > FLastSelected) then
 
-         FLastSelected := Index;
 
-     end;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.ItemUnselected(Item: TListItem; Index: Integer);
 
- begin
 
-   Dec(FSelCount);
 
-   if (FSelCount = 0) or (not FSelectingImplicitly) then
 
-   begin
 
-     FAnyAndAllSelectedImplicitly := False;
 
-   end;
 
-   if FManageSelection then
 
-   begin
 
-     if Index < 0 then
 
-       Index := Item.Index;
 
-     if FFirstSelected = Index then
 
-     begin
 
-       if FSelCount = 1 then
 
-         FFirstSelected := FLastSelected // may be -1
 
-       else
 
-         FFirstSelected := -1;
 
-     end;
 
-     if FLastSelected = Index then
 
-     begin
 
-       if FSelCount = 1 then
 
-         FLastSelected := FFirstSelected // may be -1
 
-       else
 
-         FLastSelected := -1;
 
-     end;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.Delete(Item: TListItem);
 
- var
 
-   Index: Integer;
 
- begin
 
-   if (FLastDeletedItem <> Item) and (not FClearingItems) then
 
-   begin
 
-     Index := Item.Index;
 
-     if Item.Selected then
 
-       ItemUnselected(Item, Index);
 
-     if FManageSelection then
 
-     begin
 
-       if (FLastSelected >= 0) and (Index <= FLastSelected) then
 
-         Dec(FLastSelected);
 
-       if (FFirstSelected >= 0) and (Index <= FFirstSelected) then
 
-         Dec(FFirstSelected);
 
-     end;
 
-   end;
 
-   FLastDeletedItem := Item;
 
-   inherited;
 
-   FLastDeletedItem := nil;
 
- end;
 
- function TCustomNortonLikeListView.ExCanChange(Item: TListItem; Change: Integer;
 
-   NewState, OldState: Word): Boolean;
 
- begin
 
-   Assert(Assigned(Item));
 
-   Result := True;
 
-   if (Change = LVIF_STATE) and
 
-      ((((OldState and LVIS_SELECTED) < (NewState and LVIS_SELECTED)) and
 
-        (FDontSelectItem or (not CanChangeSelection(Item, True)))) or
 
-       (((OldState and LVIS_SELECTED) > (NewState and LVIS_SELECTED)) and
 
-        (FDontUnSelectItem or (not CanChangeSelection(Item, False))))) then
 
-   begin
 
-     if (OldState or LVIS_SELECTED) <> (NewState or LVIS_SELECTED) then
 
-     begin
 
-       ListView_SetItemState(Handle, Item.Index, NewState,
 
-         (NewState or OldState) - LVIS_SELECTED);
 
-     end;
 
-     Result := False;
 
-   end;
 
- end;
 
- function TCustomNortonLikeListView.CanChangeSelection(Item: TListItem;
 
-   Select: Boolean): Boolean;
 
- begin
 
-   Result := True;
 
- end;
 
- procedure TCustomNortonLikeListView.ClearItems;
 
- begin
 
-   Items.BeginUpdate;
 
-   try
 
-     FClearingItems := True;
 
-     Items.Clear;
 
-   finally
 
-     FSelCount := 0;
 
-     if FManageSelection then
 
-     begin
 
-       FFirstSelected := -1;
 
-       FLastSelected := -1;
 
-     end;
 
-     FClearingItems := False;
 
-     Items.EndUpdate;
 
-   end;
 
- end; { ClearItems }
 
- procedure TCustomNortonLikeListView.ItemsReordered;
 
- begin
 
-   if FManageSelection then
 
-   begin
 
-     FFirstSelected := -1;
 
-     FLastSelected := -1;
 
-   end;
 
- end;
 
- function TCustomNortonLikeListView.ClosestUnselected(Item: TListItem): TListItem;
 
- var
 
-   Index: Integer;
 
- begin
 
-   if Assigned(Item) and (Item.Selected or ((NortonLike <> nlOff) and (SelCount = 0))) then
 
-   begin
 
-     Index := Item.Index + 1;
 
-     while (Index < Items.Count) and Items[Index].Selected do Inc(Index);
 
-     if (Index >= Items.Count) or Items[Index].Selected then
 
-     begin
 
-       Index := Item.Index - 1;
 
-       while (Index >= 0) and Items[Index].Selected do Dec(Index);
 
-     end;
 
-     if (Index >= 0) and (Index < Items.Count) and (not Items[Index].Selected) then
 
-       Result := Items[Index]
 
-     else
 
-       Result := nil;
 
-   end
 
-     else Result := Item;
 
- end;
 
- function TCustomNortonLikeListView.GetPopupMenu: TPopupMenu;
 
- begin
 
-   // While editing pretend that we do not have a popup menu.
 
-   // Otherwise Ctrl+V is swallowed by the TWinControl.CNKeyDown,
 
-   // when it finds out (TWinControl.IsMenuKey) that there's a command with Ctrl+V shortcut in the list view context menu
 
-   // (the "paste" file action)
 
-   if IsEditing then
 
-   begin
 
-     Result := nil;
 
-   end
 
-     else
 
-   begin
 
-     Result := inherited;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.WMNotify(var Message: TWMNotify);
 
- var
 
-   HDNotify: PHDNotify;
 
- begin
 
-   if (FHeaderHandle <> 0) and (Message.NMHdr^.hWndFrom = FHeaderHandle) then
 
-   begin
 
-     HDNotify := PHDNotify(Message.NMHdr);
 
-     // Disallow resizing of "invisible" (width=0) columns.
 
-     // (We probably get only Unicode versions of the messages here as
 
-     // controls are created as Unicode by VCL)
 
-     case HDNotify.Hdr.code of
 
-       HDN_BEGINTRACKA, HDN_TRACKA, HDN_BEGINTRACKW, HDN_TRACKW:
 
-         if not ColProperties.Visible[HDNotify.Item] then
 
-         begin
 
-           Message.Result := 1;
 
-           Exit;
 
-         end;
 
-       // We won't get here when user tries to resize the column by mouse,
 
-       // as that's prevented above.
 
-       // But we get here when other methods are used
 
-       // (the only we know about atm is Ctrl-+ shortcut)
 
-       // We are getting this notification also when control is being setup,
 
-       // with mask including also other fields, not just HDI_WIDTH.
 
-       // While it does not seem to hurt to swallow even those messages,
 
-       // not sure it's good thing to do, so we swallow width-only messages only.
 
-       // That's why there's "= HDI_WIDTH" not "and HDI_WIDTH <> 0".
 
-       HDN_ITEMCHANGINGA, HDN_ITEMCHANGINGW:
 
-         if (HDNotify.PItem.Mask = HDI_WIDTH) and
 
-            (HDNotify.PItem.cxy <> 0) and
 
-            (not ColProperties.Visible[HDNotify.Item]) then
 
-         begin
 
-           Message.Result := 1;
 
-           Exit;
 
-         end;
 
-     end;
 
-   end;
 
-   inherited;
 
- end;
 
- procedure TCustomNortonLikeListView.DDBeforeDrag;
 
- begin
 
-   FDontSelectItem := False;
 
-   FDontUnSelectItem := False;
 
- end;
 
- procedure TCustomNortonLikeListView.CNNotify(var Message: TWMNotify);
 
- var
 
-   Item: TListItem;
 
- begin
 
-   with Message do
 
-     case NMHdr^.code of
 
-       LVN_ITEMCHANGING:
 
-         with PNMListView(NMHdr)^ do
 
-         begin
 
-           Item := Items[iItem];
 
-           if Valid and (not FClearingItems) and (Item <> FLastDeletedItem) and
 
-              ((not CanChange(Item, uChanged)) or
 
-               (not ExCanChange(Item, uChanged, uNewState, uOldState)))
 
-               then
 
-           begin
 
-             Result := 1;
 
-           end;
 
-         end;
 
-       LVN_ITEMCHANGED:
 
-         begin
 
-           with PNMListView(NMHdr)^ do
 
-           begin
 
-             Item := Items[iItem];
 
-             if Valid and (not FClearingItems) and
 
-                (uChanged = LVIF_STATE) and (Item <> FLastDeletedItem) then
 
-             begin
 
-               if FForceUpdateOnItemUnfocus and
 
-                  (NortonLike <> nlOff) and
 
-                  ((uOldState and LVIS_FOCUSED) > (uNewState and LVIS_FOCUSED)) then
 
-               begin
 
-                 // force update, otherwise some remnants of focus rectangle remain
 
-                 Item.Update;
 
-               end;
 
-               if (uOldState and LVIS_SELECTED) <> (uNewState and LVIS_SELECTED) then
 
-               begin
 
-                 if (uOldState and LVIS_SELECTED) <> 0 then
 
-                 begin
 
-                   ItemUnselected(Item, iItem);
 
-                 end
 
-                   else
 
-                 begin
 
-                   ItemSelected(Item, iItem);
 
-                 end;
 
-               end;
 
-             end;
 
-           end;
 
-           inherited;
 
-         end;
 
-       LVN_ENDLABELEDIT:
 
-         begin
 
-           FIgnoreSetFocusFrom := ListView_GetEditControl(Handle);
 
-           inherited;
 
-         end;
 
-       else
 
-         begin
 
-           inherited;
 
-         end;
 
-     end;
 
- end;
 
- procedure TCustomNortonLikeListView.SelectCurrentItem(FocusNext: Boolean);
 
- var
 
-   Item: TListItem;
 
- begin
 
-   Item := ItemFocused;
 
-   if Item = nil then Item := Items[0];
 
-   Item.Selected := not Item.Selected;
 
-   if FocusNext then
 
-   begin
 
-     SendMessage(Handle, WM_KEYDOWN, VK_DOWN, LongInt(0));
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.WMKeyDown(var Message: TWMKeyDown);
 
- var
 
-   PLastSelectMethod: TSelectMethod;
 
-   PDontUnSelectItem: Boolean;
 
-   PDontSelectItem: Boolean;
 
- begin
 
-   FNextCharToIgnore := 0;
 
-   if (NortonLike <> nlOff) and (Message.CharCode = VK_INSERT) then
 
-   begin
 
-     if Items.Count > 0 then
 
-     begin
 
-       PLastSelectMethod := FLastSelectMethod;
 
-       FLastSelectMethod := smKeyboard;
 
-       try
 
-         SelectCurrentItem(True);
 
-       finally
 
-         FLastSelectMethod := PLastSelectMethod;
 
-       end;
 
-       Message.Result := 1;
 
-     end;
 
-   end
 
-     else
 
-   if Message.CharCode = VK_ADD then
 
-   begin
 
-     FNextCharToIgnore := Word('+');
 
-     inherited;
 
-   end
 
-     else
 
-   if Message.CharCode = VK_SUBTRACT then
 
-   begin
 
-     FNextCharToIgnore := Word('-');
 
-     inherited;
 
-   end
 
-     else
 
-   if Message.CharCode = VK_MULTIPLY then
 
-   begin
 
-     FNextCharToIgnore := Word('*');
 
-     inherited;
 
-   end
 
-     else
 
-   if (NortonLike <> nlOff) and (Message.CharCode in [VK_LEFT, VK_RIGHT]) and
 
-      (ViewStyle = vsReport) and
 
-      ((GetWindowLong(Handle, GWL_STYLE) and WS_HSCROLL) = 0) then
 
-   begin
 
-     if Items.Count > 0 then
 
-     begin
 
-       // do not focus item directly to make later selecting work
 
-       if Message.CharCode = VK_LEFT then
 
-         SendMessage(Handle, WM_KEYDOWN, VK_HOME, LongInt(0))
 
-       else
 
-         SendMessage(Handle, WM_KEYDOWN, VK_END, LongInt(0));
 
-     end;
 
-     Message.Result := 1;
 
-   end
 
-     else
 
-   if (NortonLike <> nlOff) and (Message.CharCode = VK_SPACE) and
 
-      ((KeyDataToShiftState(Message.KeyData) * [ssCtrl]) <> []) then
 
-   begin
 
-     // prevent Ctrl+Space landing in else branch below,
 
-     // this can safely get processed by default handler as Ctrl+Space
 
-     // toggles only focused item, not affecting others
 
-     PLastSelectMethod := FLastSelectMethod;
 
-     FLastSelectMethod := smKeyboard;
 
-     try
 
-       inherited;
 
-     finally
 
-       FLastSelectMethod := PLastSelectMethod;
 
-     end;
 
-   end
 
-     else
 
-   if (Message.CharCode in [VK_SPACE, VK_PRIOR, VK_NEXT, VK_END, VK_HOME, VK_LEFT,
 
-     VK_UP, VK_RIGHT, VK_DOWN, VK_SELECT]) then
 
-   begin
 
-     PLastSelectMethod := FLastSelectMethod;
 
-     PDontSelectItem := FDontSelectItem;
 
-     PDontUnSelectItem := FDontUnSelectItem;
 
-     FLastSelectMethod := smKeyboard;
 
-     FDontSelectItem := FDontSelectItem or
 
-       ((NortonLike <> nlOff) and
 
-        ((KeyDataToShiftState(Message.KeyData) * [ssShift]) = []));
 
-     // Note that Space (selecting toggling) is processed by default handler for WM_CHAR,
 
-     // otherwise the below condition would prevent unselection
 
-     FDontUnSelectItem :=
 
-       FDontUnSelectItem or
 
-       (NortonLike = nlOn) or
 
-       ((NortonLike = nlKeyboard) and (not FAnyAndAllSelectedImplicitly));
 
-     try
 
-       inherited;
 
-     finally
 
-       FDontSelectItem := PDontSelectItem;
 
-       FDontUnSelectItem := PDontUnSelectItem;
 
-       FLastSelectMethod := PLastSelectMethod;
 
-     end;
 
-   end
 
-     else inherited;
 
- end;
 
- procedure TCustomNortonLikeListView.WMSysCommand(var Message: TWMSysCommand);
 
- begin
 
-   // Ugly workaround to avoid Windows beeping when Alt+Grey +/- are pressed
 
-   // (for (Us)Select File with Same Ext commands)
 
-   if (Message.CmdType = SC_KEYMENU) and
 
-      ((Message.Key = Word('+')) or (Message.Key = Word('-'))) then
 
-   begin
 
-     Message.Result := 1;
 
-   end
 
-     else inherited;
 
- end;
 
- procedure TCustomNortonLikeListView.WMChar(var Message: TWMChar);
 
- var
 
-   PLastSelectMethod: TSelectMethod;
 
-   PDontUnSelectItem: Boolean;
 
-   PDontSelectItem: Boolean;
 
- begin
 
-   if Message.CharCode = FNextCharToIgnore then
 
-   begin
 
-     // ugly fix to avoid Windows beeping when these keys are processed by
 
-     // WMKeyDown instead of here (WMChar)
 
-     Message.Result := 1;
 
-   end
 
-     else
 
-   if (NortonLike <> nlOff) and (Message.CharCode = Byte(' ')) then
 
-   begin
 
-     if (GetKeyState(VK_CONTROL) >= 0) then
 
-     begin
 
-       // If not handled in TCustomScpExplorerForm::DirViewKeyPress
 
-       if not DoKeyPress(Message) then
 
-       begin
 
-         if Assigned(ItemFocused) then
 
-           ItemFocused.Selected := not ItemFocused.Selected;
 
-       end;
 
-     end
 
-       else inherited;
 
-   end
 
-     else
 
-   begin
 
-     PLastSelectMethod := FLastSelectMethod;
 
-     PDontSelectItem := FDontSelectItem;
 
-     PDontUnSelectItem := FDontUnSelectItem;
 
-     FDontSelectItem := FDontSelectItem or (NortonLike <> nlOff);
 
-     FLastSelectMethod := smKeyboard;
 
-     FDontUnSelectItem :=
 
-       FDontUnSelectItem or
 
-       (NortonLike = nlOn) or
 
-       ((NortonLike = nlKeyboard) and (not FAnyAndAllSelectedImplicitly));
 
-     try
 
-       inherited;
 
-     finally
 
-       FLastSelectMethod := PLastSelectMethod;
 
-       FDontSelectItem := PDontSelectItem;
 
-       FDontUnSelectItem := PDontUnSelectItem;
 
-     end;
 
-   end;
 
-   FNextCharToIgnore := 0;
 
- end;
 
- procedure TCustomNortonLikeListView.FocusSomething;
 
- begin
 
-   if Valid and (Items.Count > 0) and not Assigned(ItemFocused) then
 
-   begin
 
-     if (NortonLike <> nlOff) then
 
-     begin
 
-       SendMessage(Handle, WM_KEYDOWN, VK_DOWN, LongInt(0));
 
-     end;
 
-     if not Assigned(ItemFocused) then
 
-     begin
 
-       ItemFocused := Items[0];
 
-     end;
 
-   end;
 
-   if Assigned(ItemFocused) then
 
-   begin
 
-     ItemFocused.MakeVisible(False);
 
-   end;
 
- end;
 
- function TCustomNortonLikeListView.EnableDragOnClick: Boolean;
 
- begin
 
-   Result := (not FFocusingItem);
 
- end;
 
- procedure TCustomNortonLikeListView.FocusItem(Item: TListItem);
 
- var
 
-   P: TPoint;
 
-   PLastSelectMethod: TSelectMethod;
 
-   PDontUnSelectItem: Boolean;
 
-   PDontSelectItem: Boolean;
 
-   WParam: UINT_PTR;
 
-   LParam: INT_PTR;
 
- begin
 
-   // This whole is replacement for mere ItemFocused := Item
 
-   // because that does not reset some internal focused pointer,
 
-   // causing subsequent Shift-Click selects range from the first item,
 
-   // not from focused item.
 
-   Item.MakeVisible(False);
 
-   Assert(Focused);
 
-   if Focused then
 
-   begin
 
-     P := Item.GetPosition;
 
-     PLastSelectMethod := FLastSelectMethod;
 
-     PDontSelectItem := FDontSelectItem;
 
-     PDontUnSelectItem := FDontUnSelectItem;
 
-     FLastSelectMethod := smNoneYet;
 
-     FDontSelectItem := True;
 
-     FDontUnSelectItem := True;
 
-     FFocusingItem := True;
 
-     try
 
-       // HACK
 
-       // WM_LBUTTONDOWN enters loop, waiting for WM_LBUTTONUP,
 
-       // so we have to post it in advance to break the loop immediately
 
-       // Without MK_CONTROL, if there are more items selected,
 
-       // they won't get unselected on subsequent focus change
 
-       // (with explorer-style selection).
 
-       // And it also makes the click the least obtrusive, affecting the focused
 
-       // file only.
 
-       WParam := MK_LBUTTON or MK_CONTROL;
 
-       LParam := MAKELPARAM(P.X, P.Y);
 
-       PostMessage(Handle, WM_LBUTTONUP, WParam, LParam);
 
-       SendMessage(Handle, WM_LBUTTONDOWN, WParam, LParam);
 
-     finally
 
-       FFocusingItem := False;
 
-       FLastSelectMethod := PLastSelectMethod;
 
-       FDontSelectItem := PDontSelectItem;
 
-       FDontUnSelectItem := PDontUnSelectItem;
 
-     end;
 
-   end;
 
-   if ItemFocused <> Item then
 
-     ItemFocused := Item;
 
- end;
 
- procedure TCustomNortonLikeListView.SelectAll(Mode: TSelectMode; Exclude: TListItem);
 
- var
 
-   Index: Integer;
 
-   Item: TListItem;
 
- begin
 
-   BeginSelectionUpdate;
 
-   try
 
-     for Index := 0 to Items.Count - 1 do
 
-     begin
 
-       Item := Items[Index];
 
-       if Item <> Exclude then
 
-       begin
 
-         case Mode of
 
-           smAll: Item.Selected := True;
 
-           smNone: Item.Selected := False;
 
-           smInvert: Item.Selected := not Item.Selected;
 
-         end;
 
-       end;
 
-     end;
 
-   finally
 
-     EndSelectionUpdate;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.SelectAll(Mode: TSelectMode);
 
- begin
 
-   SelectAll(Mode, nil);
 
- end;
 
- procedure TCustomNortonLikeListView.WMLButtonDown(var Message: TWMLButtonDown);
 
- var
 
-   PLastSelectMethod: TSelectMethod;
 
-   PDontUnSelectItem: Boolean;
 
-   PDontSelectItem: Boolean;
 
-   PSelectingImplicitly: Boolean;
 
-   SelectingImplicitly: Boolean;
 
-   Shift: TShiftState;
 
-   Item: TListItem;
 
- begin
 
-   Shift := KeysToShiftState(Message.Keys);
 
-   PLastSelectMethod := FLastSelectMethod;
 
-   PDontSelectItem := FDontSelectItem;
 
-   PDontUnSelectItem := FDontUnSelectItem;
 
-   PSelectingImplicitly := FSelectingImplicitly;
 
-   FLastSelectMethod := smMouse;
 
-   FDontSelectItem := FDontSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl, ssShift]) = []));
 
-   FDontUnSelectItem := FDontUnSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl]) = []));
 
-   SelectingImplicitly := ((Shift * [ssCtrl, ssShift]) = []);
 
-   if SelectingImplicitly and (NortonLike = nlKeyboard) then
 
-   begin
 
-     // in general, when clicking, we clear selection only after mouse button is released,
 
-     // from within WMLButtonUp, so we know we are not starting dragging,
 
-     // so we do not want to clear the selection.
 
-     // on the other hand, when clicking outside of the selection,
 
-     // we want to explicitly clear the selection, no matter what
 
-     Item := GetItemAt(Message.XPos, Message.YPos);
 
-     if (Item = nil) or (not Item.Selected) then
 
-       SelectAll(smNone);
 
-   end;
 
-   FSelectingImplicitly := FSelectingImplicitly or SelectingImplicitly;
 
-   FLButtonDownShiftState := Shift;
 
-   FLButtonDownPos := Point(Message.XPos, Message.YPos);
 
-   try
 
-     inherited;
 
-   finally
 
-     FLastSelectMethod := PLastSelectMethod;
 
-     FDontSelectItem := PDontSelectItem;
 
-     FDontUnSelectItem := PDontUnSelectItem;
 
-     FSelectingImplicitly := PSelectingImplicitly;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.WMRButtonDown(var Message: TWMRButtonDown);
 
- var
 
-   PLastSelectMethod: TSelectMethod;
 
-   PDontUnSelectItem: Boolean;
 
-   PDontSelectItem: Boolean;
 
-   PSelectingImplicitly: Boolean;
 
-   SelectingImplicitly: Boolean;
 
-   Shift: TShiftState;
 
- begin
 
-   Shift := KeysToShiftState(Message.Keys);
 
-   PLastSelectMethod := FLastSelectMethod;
 
-   PDontSelectItem := FDontSelectItem;
 
-   PDontUnSelectItem := FDontUnSelectItem;
 
-   PSelectingImplicitly := FSelectingImplicitly;
 
-   FLastSelectMethod := smMouse;
 
-   FDontSelectItem := FDontSelectItem or (NortonLike = nlOn);
 
-   FDontUnSelectItem := FDontUnSelectItem or (NortonLike = nlOn);
 
-   SelectingImplicitly := ((Shift * [ssCtrl, ssShift]) = []);
 
-   // TODO unselect all when clicking outside of selection
 
-   // (is not done automatically when focused item is not selected)
 
-   FSelectingImplicitly := FSelectingImplicitly or SelectingImplicitly;
 
-   try
 
-     inherited;
 
-   finally
 
-     FLastSelectMethod := PLastSelectMethod;
 
-     FDontSelectItem := PDontSelectItem;
 
-     FDontUnSelectItem := PDontUnSelectItem;
 
-     FSelectingImplicitly := PSelectingImplicitly;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.WMLButtonUp(var Message: TWMLButtonUp);
 
- var
 
-   SelectingImplicitly: Boolean;
 
-   Shift: TShiftState;
 
- begin
 
-   // Workaround
 
-   // For some reason Message.Keys is always 0 here,
 
-   // so we use shift state from the LButtonDown as a workaround
 
-   Shift := KeysToShiftState(Message.Keys);
 
-   SelectingImplicitly :=
 
-     ((Shift * [ssCtrl, ssShift]) = []) and
 
-     ((FLButtonDownShiftState * [ssCtrl, ssShift]) = []);
 
-   if SelectingImplicitly and (csClicked in ControlState) and
 
-      (Abs(FLButtonDownPos.X - Message.XPos) <= 4) and
 
-      (Abs(FLButtonDownPos.Y - Message.YPos) <= 4) then
 
-   begin
 
-     SelectAll(smNone, ItemFocused);
 
-     // Because condition in ItemSelected is not triggered as we first select
 
-     // the new item and then unselect the previous.
 
-     // This probably means that we can get rid of the code in ItemSelected.
 
-     FAnyAndAllSelectedImplicitly := True;
 
-   end;
 
-   inherited;
 
- end;
 
- function TCustomNortonLikeListView.GetMarkedFile: TListItem;
 
- begin
 
-   if Assigned(Selected) then Result := Selected
 
-     else
 
-   if Assigned(ItemFocused) and (NortonLike <> nlOff) then Result := ItemFocused
 
-     else Result := nil;
 
- end;
 
- function TCustomNortonLikeListView.GetNextItem(StartItem: TListItem;
 
-   Direction: TSearchDirection; States: TItemStates): TListItem;
 
- var
 
-   Start, Index, First, Last: Integer;
 
- begin
 
-   if not FManageSelection then
 
-   begin
 
-     Result := inherited GetNextItem(StartItem, Direction, States);
 
-   end
 
-     else
 
-   begin
 
-     Assert(Direction = sdAll);
 
-     if States = [isSelected] then
 
-     begin
 
-       if FSelCount = 0 then
 
-       begin
 
-         Result := nil
 
-       end
 
-         else
 
-       if (not Assigned(StartItem)) and (FFirstSelected >= 0) then
 
-       begin
 
-         Result := Items[FFirstSelected]
 
-       end
 
-         else
 
-       begin
 
-         if Assigned(StartItem) then
 
-           Start := StartItem.Index
 
-         else
 
-           Start := -1;
 
-         if (FFirstSelected >= 0) and (Start < FFirstSelected) then
 
-           First := FFirstSelected
 
-         else
 
-           First := Start + 1;
 
-         if FLastSelected >= 0 then
 
-           Last := FLastSelected
 
-         else
 
-           Last := Items.Count - 1;
 
-         if Start > Last then
 
-         begin
 
-           Result := nil;
 
-         end
 
-           else
 
-         begin
 
-           Index := First;
 
-           while (Index <= Last) and (not (Items[Index].Selected)) do
 
-           begin
 
-             Inc(Index);
 
-           end;
 
-           if Index > Last then
 
-           begin
 
-             Result := nil;
 
-             if Assigned(StartItem) and StartItem.Selected then
 
-             begin
 
-               Assert((FLastSelected < 0) or (FLastSelected = Start));
 
-               FLastSelected := Start;
 
-             end;
 
-           end
 
-             else
 
-           begin
 
-             Result := Items[Index];
 
-             Assert(Result.Selected);
 
-             if not Assigned(StartItem) then
 
-             begin
 
-               Assert((FFirstSelected < 0) or (FFirstSelected = Index));
 
-               FFirstSelected := Index;
 
-             end;
 
-           end;
 
-         end;
 
-       end;
 
-     end
 
-       else
 
-     if States = [isCut] then
 
-     begin
 
-       Result := inherited GetNextItem(StartItem, Direction, States);
 
-     end
 
-       else
 
-     if States = [] then
 
-     begin
 
-       if Assigned(StartItem) then
 
-         Start := StartItem.Index
 
-       else
 
-         Start := -1;
 
-       Inc(Start);
 
-       if Start < Items.Count then
 
-         Result := Items[Start]
 
-       else
 
-         Result := nil;
 
-     end
 
-       else
 
-     begin
 
-       Assert(False);
 
-       Result := nil;
 
-     end;
 
-   end;
 
- end;
 
- function TCustomNortonLikeListView.GetSelCount: Integer;
 
- begin
 
-   Result := FSelCount;
 
- end;
 
- procedure TCustomNortonLikeListView.InsertItem(Item: TListItem);
 
- begin
 
-   inherited;
 
-   if Item.Selected then
 
-     ItemSelected(Item, -1);
 
- end;
 
- function TCustomNortonLikeListView.GetItemFromHItem(const Item: TLVItem): TListItem;
 
- begin
 
-   with Item do
 
-     if (state and LVIF_PARAM) <> 0 then Result := Pointer(lParam)
 
-       else Result := Items[iItem];
 
- end;
 
- function TCustomNortonLikeListView.GetMarkedCount: Integer;
 
- begin
 
-   if (SelCount > 0) or (NortonLike = nlOff) then Result := SelCount
 
-     else
 
-   if Assigned(ItemFocused) then Result := 1
 
-     else Result := 0;
 
- end;
 
- function TCustomNortonLikeListView.GetValid: Boolean;
 
- begin
 
-   // Note that TCustomDirView::GetValid don't inherit
 
-   // this method because of optimalization
 
-   Result := (not (csDestroying in ComponentState)) and (not FClearingItems);
 
- end;
 
- procedure TCustomNortonLikeListView.BeginSelectionUpdate;
 
- begin
 
-   // Higher value is probably some nesting error
 
-   Assert(FUpdatingSelection in [0..4]);
 
-   Inc(FUpdatingSelection);
 
- end; { BeginUpdatingSelection }
 
- procedure TCustomNortonLikeListView.EndSelectionUpdate;
 
- begin
 
-   Assert(FUpdatingSelection > 0);
 
-   Dec(FUpdatingSelection);
 
- end; { EndUpdatingSelection }
 
- procedure TCustomNortonLikeListView.CreateWnd;
 
- begin
 
-   try
 
-     Assert(ColProperties <> nil);
 
-     inherited;
 
-     FHeaderHandle := ListView_GetHeader(Handle);
 
-     ColProperties.ListViewWndCreated;
 
-   finally
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.DestroyWnd;
 
- begin
 
-   ColProperties.ListViewWndDestroying;
 
-   try
 
-     inherited;
 
-   finally
 
-     ColProperties.ListViewWndDestroyed;
 
-   end;
 
- end;
 
- procedure TCustomNortonLikeListView.LVMEditLabel(var Message: TMessage);
 
- begin
 
-   // explicitly requesting editing (e.g. F2),
 
-   // so we do not care anymore when the view was focused
 
-   FFocused := 0;
 
-   inherited;
 
- end;
 
- function TCustomNortonLikeListView.CanEdit(Item: TListItem): Boolean;
 
- var
 
-   N: TDateTime;
 
-   Delta: Double;
 
- begin
 
-   N := Now;
 
-   Result := inherited CanEdit(Item);
 
-   if Result and (FFocused > 0) then
 
-   begin
 
-     Delta := N - FFocused;
 
-     // it takes little more than 500ms to trigger editing after click
 
-     Result := Delta > (750.0/MSecsPerDay);
 
-   end;
 
-   FFocused := 0;
 
- end;
 
- procedure TCustomNortonLikeListView.WMSetFocus(var Message: TWMSetFocus);
 
- begin
 
-   inherited;
 
-   if Message.FocusedWnd <> FIgnoreSetFocusFrom then
 
-     FFocused := Now;
 
- end;
 
- procedure TCustomNortonLikeListView.CMWantSpecialKey(var Message: TCMWantSpecialKey);
 
- begin
 
-   inherited;
 
-   if IsEditing and (Message.CharCode = VK_TAB) then
 
-     Message.Result := 1;
 
- end;
 
- procedure TCustomNortonLikeListView.MakeProgressVisible(Item: TListItem);
 
- var
 
-   DisplayRect: TRect;
 
- begin
 
-   if ViewStyle = vsReport then
 
-   begin
 
-     DisplayRect := Item.DisplayRect(drBounds);
 
-     if DisplayRect.Bottom > ClientHeight then
 
-     begin
 
-       Scroll(0, Item.Top - TopItem.Top);
 
-     end;
 
-   end;
 
-   Item.MakeVisible(False);
 
- end;
 
- procedure TCustomNortonLikeListView.ChangeScale(M, D: Integer);
 
- begin
 
-   if M <> D then
 
-   begin
 
-     // When font is scaled, while the control is being re-created, previous font is restored once
 
-     // read from the persistence data in TCustomListView.CreateWnd.
 
-     // Requiring handle, makes sure the re-create phase is closed.
 
-     // We could limit impact by checking ControlHasRecreationPersistenceData,
 
-     // but for now, we actually prefer larger impact to test this change better.
 
-     HandleNeeded;
 
-   end;
 
-   inherited;
 
- end;
 
- end.
 
 
  |