Ever tried to sort CRC values in a TListView ?
I have hunted high and low on the Internet, and have found plenty of examples on
how to sort strings and numbers alphabetically. However, I have never found
anything which would sort CRC values. A good example of wanting to do this would be
if I were writing a compression program, or some sort of application to verify the
integrity of files.
The real problem is that sorting a CRC value would only be done alphabetically, if
the standard ListView.CustomSort routine were used. This may be fine in some
respects, but it will not sort the numbers in the true order. I started researching
this, and was trying to convert the numbers to integers, displaying them, sorting
them, then converting them back to hex values. A very slow way to do it !
I then discovered that the trick is to convert them to integers on the fly, sort
them, then move the original hex number to its new position. I cannot guarantee it
is the best way - use of machine code might improve this, but this way does work.
Alphabetically sorted,
Assumptions:
- A TListView is being used.
- Some CRC values are entered in a column. I use the first column, but the code can
be modified to use different columns.
Entire code below:
1 unit cdSortCRC;
2
3 interface
4
5 uses
6 Classes, Forms, StdCtrls, ComCtrls, Controls;
7
8
9 type
10 TForm1 = class(TForm)
11 ListView1: TListView;
12 procedure byCRCClick(Sender: TObject);
13 procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
14 private
15 { Private declarations }
16 public
17 { Public declarations }
18 end;
19
20 var
21 Form1 : TForm1; { main form }
22 n1, n2 : double; { used to determine order of numbers}
23 b : Byte; { used to get individual integer digit before conversion}
24
25 implementation
26
27 {$R *.dfm}
28
29 { used to convert hex number into integer on the fly }
30 function HexToInt(Value: string): Longword;
31 begin
32 Result := 0;
33 for b := 1 to Length(Value) do
34 begin
35 case Value[b] of
36 '0'..'9': Result := 16 * Result + (Ord(Value[b]) - $30);
37 'A'..'F': Result := 16 * Result + (Ord(Value[b]) - $37);
38 'a'..'f': Result := 16 * Result + (Ord(Value[b]) - $57);
39 end;
40 end;
41 end;
42
43 function CustomCRCSortProc(Item1, Item2: TListItem; ParamSort: integer): integer;
44 stdcall;
45 begin
46 { initialise values }
47 n1 := 0;
48 n2 := 0;
49
50 { case routine to effect swap of numbers in TListView ? }
51 case ParamSort of
52 1 : begin
53 n1 := HexToInt(Item1.SubItems.Strings[0]);
54 n2 := HexToInt(Item2.SubItems.Strings[0]);
55 end;
56 -1: begin
57 n1 := HexToInt(Item2.SubItems.Strings[0]);
58 n2 := HexToInt(Item1.SubItems.Strings[0]);
59 end;
60 end;
61
62 { used to determine order of numbers }
63 if n1 > n2 then Result := -1 else if n1 < n2 then Result := 1 else Result := 0;
64 end;
65
66 { procedure to call sorting routine - could be called from other components, e.g.
67 TButton }
68 procedure TForm1.byCRCClick(Sender: TObject);
69 begin
70 if ListView1.Tag = -1 then ListView1.Tag := 1 else ListView1.Tag := -1;
71 ListView1.CustomSort(@CustomCRCSortProc, ListView1.Tag);
72 end;
73
74 { Activates sort from column click - optional extra}
75 procedure TForm1.ListView1ColumnClick(Sender: TObject;
76 Column: TListColumn);
77 begin
78 if column = ListView1.Column[1] then byCRCClick(Sender);
79 end;
80
81 end.
|