Changeset 75 for trunk/Packages/Common/ListViewSort.pas
- Timestamp:
- Jun 4, 2024, 12:22:49 AM (5 months ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/Packages/Common/ListViewSort.pas
r74 r75 1 unit UListViewSort; 2 3 // Date: 2010-11-03 4 5 {$mode delphi} 1 unit ListViewSort; 2 3 // Date: 2019-05-17 6 4 7 5 interface 8 6 9 7 uses 10 {$IFDEF Windows}Windows, CommCtrl, {$ENDIF}Classes, Graphics, ComCtrls, SysUtils, 11 Controls, DateUtils, Dialogs, SpecializedList, Forms, Grids, StdCtrls, ExtCtrls; 8 {$IFDEF Windows}Windows, CommCtrl, LMessages, {$ENDIF}Classes, Graphics, ComCtrls, SysUtils, 9 Controls, DateUtils, Dialogs, Forms, Grids, StdCtrls, ExtCtrls, 10 LclIntf, LclType, LResources, Generics.Collections, Generics.Defaults; 12 11 13 12 type … … 18 17 TCompareEvent = function (Item1, Item2: TObject): Integer of object; 19 18 TListFilterEvent = procedure (ListViewSort: TListViewSort) of object; 19 20 TObjects = TObjectList<TObject>; 21 22 { TListViewSort } 20 23 21 24 TListViewSort = class(TComponent) … … 28 31 FColumn: Integer; 29 32 FOrder: TSortOrder; 33 FOldListViewWindowProc: TWndMethod; 34 FOnColumnWidthChanged: TNotifyEvent; 35 procedure DoColumnBeginResize(const AColIndex: Integer); 36 procedure DoColumnResized(const AColIndex: Integer); 37 procedure DoColumnResizing(const AColIndex, AWidth: Integer); 30 38 procedure SetListView(const Value: TListView); 31 39 procedure ColumnClick(Sender: TObject; Column: TListColumn); … … 40 48 procedure SetColumn(const Value: Integer); 41 49 procedure SetOrder(const Value: TSortOrder); 50 {$IFDEF WINDOWS} 51 procedure NewListViewWindowProc(var AMsg: TMessage); 52 {$ENDIF} 42 53 public 43 List: TListObject;44 Source: TListObject;54 Source: TObjects; 55 List: TObjects; 45 56 constructor Create(AOwner: TComponent); override; 46 57 destructor Destroy; override; … … 58 69 property OnCustomDraw: TLVCustomDrawItemEvent read FOnCustomDraw 59 70 write FOnCustomDraw; 71 property OnColumnWidthChanged: TNotifyEvent read FOnColumnWidthChanged 72 write FOnColumnWidthChanged; 60 73 property Column: Integer read FColumn write SetColumn; 61 74 property Order: TSortOrder read FOrder write SetOrder; … … 68 81 FOnChange: TNotifyEvent; 69 82 FStringGrid1: TStringGrid; 70 procedure DoOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); 83 procedure DoOnChange; 84 procedure GridDoOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); 85 procedure GridDoOnResize(Sender: TObject); 71 86 public 72 87 constructor Create(AOwner: TComponent); override; 73 88 procedure UpdateFromListView(ListView: TListView); 74 89 function TextEntered: Boolean; 90 function TextEnteredCount: Integer; 91 function TextEnteredColumn(Index: Integer): Boolean; 75 92 function GetColValue(Index: Integer): string; 93 procedure Reset; 76 94 property StringGrid: TStringGrid read FStringGrid1 write FStringGrid1; 77 95 published … … 79 97 property Align; 80 98 property Anchors; 99 property BorderSpacing; 100 end; 101 102 { TListViewEx } 103 104 TListViewEx = class(TWinControl) 105 private 106 FFilter: TListViewFilter; 107 FListView: TListView; 108 FListViewSort: TListViewSort; 109 procedure ResizeHanlder; 110 public 111 constructor Create(TheOwner: TComponent); override; 112 destructor Destroy; override; 113 published 114 property ListView: TListView read FListView write FListView; 115 property ListViewSort: TListViewSort read FListViewSort write FListViewSort; 116 property Filter: TListViewFilter read FFilter write FFilter; 117 property Visible; 81 118 end; 82 119 … … 88 125 procedure Register; 89 126 begin 90 RegisterComponents('Common', [TListViewSort, TListViewFilter]); 127 RegisterComponents('Common', [TListViewSort, TListViewFilter, TListViewEx]); 128 end; 129 130 { TListViewEx } 131 132 procedure TListViewEx.ResizeHanlder; 133 begin 134 end; 135 136 constructor TListViewEx.Create(TheOwner: TComponent); 137 begin 138 inherited Create(TheOwner); 139 Filter := TListViewFilter.Create(Self); 140 Filter.Parent := Self; 141 Filter.Align := alBottom; 142 ListView := TListView.Create(Self); 143 ListView.Parent := Self; 144 ListView.Align := alClient; 145 ListViewSort := TListViewSort.Create(Self); 146 ListViewSort.ListView := ListView; 147 end; 148 149 destructor TListViewEx.Destroy; 150 begin 151 inherited; 91 152 end; 92 153 93 154 { TListViewFilter } 94 155 95 procedure TListViewFilter.DoOnKeyUp(Sender: TObject; var Key: Word; 156 procedure TListViewFilter.DoOnChange; 157 begin 158 if Assigned(FOnChange) then FOnChange(Self); 159 end; 160 161 procedure TListViewFilter.GridDoOnKeyUp(Sender: TObject; var Key: Word; 96 162 Shift: TShiftState); 97 163 begin 98 if Assigned(FOnChange) then 99 FOnChange(Self); 164 DoOnChange; 165 end; 166 167 procedure TListViewFilter.GridDoOnResize(Sender: TObject); 168 begin 169 FStringGrid1.DefaultRowHeight := FStringGrid1.Height; 100 170 end; 101 171 … … 113 183 FStringGrid1.Options := [goFixedHorzLine, goFixedVertLine, goVertLine, 114 184 goHorzLine, goRangeSelect, goEditing, goAlwaysShowEditor, goSmoothScroll]; 115 FStringGrid1.OnKeyUp := DoOnKeyUp; 185 FStringGrid1.OnKeyUp := GridDoOnKeyUp; 186 FStringGrid1.OnResize := GridDoOnResize; 116 187 end; 117 188 … … 119 190 var 120 191 I: Integer; 121 NewColumn: TGridColumn;192 R: TRect; 122 193 begin 123 194 with FStringGrid1 do begin 124 Columns.Clear;125 195 while Columns.Count > ListView.Columns.Count do Columns.Delete(Columns.Count - 1); 126 while Columns.Count < ListView.Columns.Count do NewColumn :=Columns.Add;196 while Columns.Count < ListView.Columns.Count do Columns.Add; 127 197 for I := 0 to ListView.Columns.Count - 1 do begin 128 198 Columns[I].Width := ListView.Columns[I].Width; 199 if Selection.Left = I then begin 200 R := CellRect(I, 0); 201 Editor.Left := R.Left + 2; 202 Editor.Width := R.Width - 4; 203 end; 129 204 end; 130 205 end; … … 132 207 133 208 function TListViewFilter.TextEntered: Boolean; 209 begin 210 Result := TextEnteredCount > 0; 211 end; 212 213 function TListViewFilter.TextEnteredCount: Integer; 134 214 var 135 215 I: Integer; 136 216 begin 137 Result := False;217 Result := 0; 138 218 for I := 0 to FStringGrid1.ColCount - 1 do begin 139 219 if FStringGrid1.Cells[I, 0] <> '' then begin 140 Result := True; 141 Break; 220 Inc(Result); 142 221 end; 143 222 end; 223 end; 224 225 function TListViewFilter.TextEnteredColumn(Index: Integer): Boolean; 226 begin 227 Result := FStringGrid1.Cells[Index, 0] <> ''; 144 228 end; 145 229 … … 151 235 end; 152 236 237 procedure TListViewFilter.Reset; 238 var 239 I: Integer; 240 begin 241 with StringGrid do 242 for I := 0 to ColCount - 1 do 243 Cells[I, 0] := ''; 244 DoOnChange; 245 end; 246 153 247 { TListViewSort } 154 248 249 {$IFDEF WINDOWS} 250 procedure TListViewSort.NewListViewWindowProc(var AMsg: TMessage); 251 var 252 vColWidth: Integer; 253 vMsgNotify: TLMNotify absolute AMsg; 254 Code: Integer; 255 begin 256 // call the old WindowProc of ListView 257 FOldListViewWindowProc(AMsg); 258 259 // Currently we care only with WM_NOTIFY message 260 if AMsg.Msg = WM_NOTIFY then 261 begin 262 Code := NMHDR(PHDNotify(vMsgNotify.NMHdr)^.Hdr).Code; 263 case Code of 264 HDN_ENDTRACKA, HDN_ENDTRACKW: 265 DoColumnResized(PHDNotify(vMsgNotify.NMHdr)^.Item); 266 267 HDN_BEGINTRACKA, HDN_BEGINTRACKW: 268 DoColumnBeginResize(PHDNotify(vMsgNotify.NMHdr)^.Item); 269 270 HDN_TRACKA, HDN_TRACKW: 271 begin 272 vColWidth := -1; 273 if (PHDNotify(vMsgNotify.NMHdr)^.PItem<>nil) 274 and (PHDNotify(vMsgNotify.NMHdr)^.PItem^.Mask and HDI_WIDTH <> 0) 275 then 276 vColWidth := PHDNotify(vMsgNotify.NMHdr)^.PItem^.cxy; 277 278 DoColumnResizing(PHDNotify(vMsgNotify.NMHdr)^.Item, vColWidth); 279 end; 280 end; 281 end; 282 end; 283 {$ENDIF} 284 285 procedure TListViewSort.DoColumnBeginResize(const AColIndex: Integer); 286 begin 287 end; 288 289 procedure TListViewSort.DoColumnResizing(const AColIndex, AWidth: Integer); 290 begin 291 end; 292 293 procedure TListViewSort.DoColumnResized(const AColIndex: Integer); 294 begin 295 if Assigned(FOnColumnWidthChanged) then 296 FOnColumnWidthChanged(Self); 297 end; 155 298 156 299 procedure TListViewSort.ColumnClick(Sender: TObject; Column: TListColumn); … … 179 322 procedure TListViewSort.SetListView(const Value: TListView); 180 323 begin 324 if FListView = Value then Exit; 325 if Assigned(FListView) then 326 ListView.WindowProc := FOldListViewWindowProc; 181 327 FListView := Value; 182 328 FListView.OnColumnClick := ColumnClick; 183 329 FListView.OnCustomDrawItem := ListViewCustomDrawItem; 184 330 FListView.OnClick := ListViewClick; 331 FOldListViewWindowProc := FListView.WindowProc; 332 {$IFDEF WINDOWS} 333 FListView.WindowProc := NewListViewWindowProc; 334 {$ENDIF} 335 end; 336 337 var 338 ListViewSortCompare: TCompareEvent; 339 340 function ListViewCompare(constref Item1, Item2: TObject): Integer; 341 begin 342 Result := ListViewSortCompare(Item1, Item2); 185 343 end; 186 344 187 345 procedure TListViewSort.Sort(Compare: TCompareEvent); 188 346 begin 347 // TODO: Because TFLGObjectList compare handler is not class method, 348 // it is necessary to use simple function compare handler with local variable 349 ListViewSortCompare := Compare; 189 350 if (List.Count > 0) then 190 List.Sort( Compare);351 List.Sort(TComparer<TObject>.Construct(ListViewCompare)); 191 352 end; 192 353 … … 194 355 begin 195 356 if Assigned(FOnFilter) then FOnFilter(Self) 196 else if Assigned(Source) then 197 List.Assign(Source) else 357 else if Assigned(Source) then begin 198 358 List.Clear; 359 List.AddRange(Source); 360 end else List.Clear; 199 361 if ListView.Items.Count <> List.Count then 200 362 ListView.Items.Count := List.Count; 201 if Assigned(FOnCompareItem) then Sort(FOnCompareItem);363 if Assigned(FOnCompareItem) and (Order <> soNone) then Sort(FOnCompareItem); 202 364 //ListView.Items[-1]; // Workaround for not show first row if selected 203 365 ListView.Refresh; … … 251 413 begin 252 414 inherited; 253 List := T ListObject.Create;415 List := TObjects.Create; 254 416 List.OwnsObjects := False; 255 417 end; … … 257 419 destructor TListViewSort.Destroy; 258 420 begin 259 List.Free;421 FreeAndNil(List); 260 422 inherited; 261 423 end; … … 266 428 TP1: TPoint; 267 429 XBias, YBias: Integer; 268 OldColor: TColor; 430 PenColor: TColor; 431 BrushColor: TColor; 269 432 BiasTop, BiasLeft: Integer; 270 433 Rect1: TRect; … … 278 441 Item.Left := 0; 279 442 GetCheckBias(XBias, YBias, BiasTop, BiasLeft, ListView); 280 OldColor := ListView.Canvas.Pen.Color; 443 PenColor := ListView.Canvas.Pen.Color; 444 BrushColor := ListView.Canvas.Brush.Color; 281 445 //TP1 := Item.GetPosition; 282 446 lRect := Item.DisplayRect(drBounds); // Windows 7 workaround … … 290 454 ItemLeft := Item.Left; 291 455 ItemLeft := 23; // Windows 7 workaround 292 456 293 457 Rect1.Left := ItemLeft - CheckWidth - BiasLeft + 1 + XBias; 294 458 //ShowMessage(IntToStr(Tp1.Y) + ', ' + IntToStr(BiasTop) + ', ' + IntToStr(XBias)); … … 321 485 end; 322 486 //ListView.Canvas.Brush.Color := ListView.Color; 323 ListView.Canvas.Brush.Color := clWindow;324 ListView.Canvas.Pen.Color := OldColor;487 ListView.Canvas.Brush.Color := BrushColor; 488 ListView.Canvas.Pen.Color := PenColor; 325 489 end; 326 490 … … 389 553 FHeaderHandle := ListView_GetHeader(FListView.Handle); 390 554 for I := 0 to FListView.Columns.Count - 1 do begin 555 {$push}{$warn 5057 off} 391 556 FillChar(Item, SizeOf(THDItem), 0); 557 {$pop} 392 558 Item.Mask := HDI_FORMAT; 393 559 Header_GetItem(FHeaderHandle, I, Item);
Note:
See TracChangeset
for help on using the changeset viewer.