How to show the sort arrow on a TListView column?
Asked Answered
F

2

6

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?

Feltonfelts answered 9/2, 2013 at 22:20 Comment(0)
A
17

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.

Aside answered 9/2, 2013 at 22:37 Comment(4)
I added the Winapi.CommCtrl uses clause to your example, thanks.Highbrow
Is there a way to do this for grids?Bently
@No Grids are custom controls, entirely implemented in VCL code. If the VCL doesn't offer such a facility, then you'd have to customise the painting in your code.Aside
The arrow hides as soon as the ListView resizes.Revolve
P
3

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.

Pregnable answered 16/2, 2014 at 2:48 Comment(1)
Welcome to stackoverflow. Strictly speaking this is not an answer to my question. I am upvoting it anyway, because your answer is useful.Highbrow

© 2022 - 2024 — McMap. All rights reserved.