Help & Manual authoring tool
A method to find out the ListItem and column that was clicked in a ListView

Which column was clicked in a TListView?

Copyright © 2000 Ernesto De Spirito

EurekaLog - Catch and log every exception!

Extended GetItemAt

This method (GetItemAt) only provides the information about which ListItem (if any) is located at the specified coordinates passed as parameters, but only works with the first column of the TListView. The rest are ignored. If we needed to know if the user clicked on an element in another column, we can declare a new method in a derived class:

uses ComCtrls;

type
  TListViewX = class(TListView)
  public
    function GetItemAtX(X, Y: integer; var Col: integer): TListItem;
  end;

implementation

function TListViewX.GetItemAtX(X, Y: integer;
    var Col: integer): TListItem;
var
  i, n, RelativeX, ColStartX: Integer;
  ListItem: TlistItem;
begin
  Result := GetItemAt(X, Y);
  if Result <> nil then begin
    Col := 0; // First column
  end else if (ViewStyle = vsReport)
      and (TopItem <> nil) then begin
    // First, let's try to find the row
    ListItem := GetItemAt(TopItem.Position.X, Y);
    if ListItem <> nil then begin
      // Now let's try to find the Column
      RelativeX := X-ListItem.Position.X-BorderWidth;
      ColStartX := Columns[0].Width;
      n := Columns.Count - 1;
      for i := 1 to n do begin
        if RelativeX < ColStartX then break;
        if RelativeX <= ColStartX +
            StringWidth(ListItem.SubItems[i-1]) then
        begin
          Result := ListItem;
          Col := i;
          break;
        end;//if
        Inc(ColStartX, Columns[i].Width);
      end;//for
    end;//if
  end;//if
end;

Casting to the new class

We don't need to intall this new component and register it in the components palette as we explained in another article. Instead, any time we want to access this method, we can just cast the object (for example ListView1) to our new class. For example in a MouseDown event:

procedure TForm1.ListView1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  col: integer;
  li: TListItem;
begin
  li := TListViewX(ListView1).GetItemAtX(x, y, col);
  if li <> nil then
    ShowMessage('Column #' + IntToStr(col));
end;
JfControls Library - for Delphi and C++ Builder
Copyright © 2000/2006 Ernesto De Spirito.   All rights reserved.