Which column was clicked in a TListView?
Copyright © 2000 Ernesto De Spirito
![]() |
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;
![]() |



