Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show the sort arrow on a TListView column?

Windows Explorer has an arrow indicating which column a list view (in report view style) is sorted by and in which direction (ASC vs. DESC).

Is it possible to display such a sort indication arrow on a TListView in Delphi?

like image 537
Jens Mühlenhoff Avatar asked Feb 09 '13 22:02

Jens Mühlenhoff


2 Answers

Here's some simple code to mark a header column as sorted ascending:

uses
  Winapi.CommCtrl;

var
  Header: HWND;
  Item: THDItem;
begin
  Header := ListView_GetHeader(ListView1.Handle);
  ZeroMemory(@Item, SizeOf(Item));
  Item.Mask := HDI_FORMAT;
  Header_GetItem(Header, 0, Item);
  Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
  Item.fmt := Item.fmt or HDF_SORTUP;//include the sort ascending flag
  Header_SetItem(Header, 0, Item);
end;

I have omitted error checking for the sake of simplicity. If you want the arrow in the opposite direction, I'm sure you can work out how to swap the logic around.

The key MSDN topic is that for the HDITEM struct.

like image 193
David Heffernan Avatar answered Nov 12 '22 12:11

David Heffernan


You can easily extend this code to make it work for all columns in a ListView; Declare two variables (in the private section of the Form):

ColumnToSort: Integer; Ascending: Boolean;

Initialize them in the FormCreate procedure with 0 and True.

procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: ListColumn);
var
  Header: HWND;
  Item: THDItem;
begin
  Header := ListView_GetHeader(ListView1.Handle);
  ZeroMemory(@Item, SizeOf(Item));
  Item.Mask := HDI_FORMAT;

  // Clear the previous arrow
  Header_GetItem(Header, ColumnToSort, Item);
  Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
  Header_SetItem(Header, ColumnToSort, Item);

  if Column.Index = ColumnToSort then
    Ascending := not Ascending
  else
    ColumnToSort := Column.Index;

  // Get the new column
  Header_GetItem(Header, ColumnToSort, Item);
  Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags

  if Ascending then
    Item.fmt := Item.fmt or HDF_SORTUP//include the sort ascending flag
  else
    Item.fmt := Item.fmt or HDF_SORTDOWN;//include the sort descending flag
  Header_SetItem(Header, ColumnToSort, Item);

  with ListView1 do
    begin
      Items.BeginUpdate;
      AlphaSort;
      Items.EndUpdate;
    end;
end;

Of course, you will have to provide your own OnCompare function for the actual sorting of the columns. This code only displays the sort arrow in the clicked column header.

like image 36
Jan Muller Avatar answered Nov 12 '22 11:11

Jan Muller