Método para determinar el ListItem y columna donde el usuario hizo clic con el ratón en un ListView

Determinando la columna que fue cliqueada en un TListView

Copyright © 2000 Ernesto De Spirito

Boycott Trend Micro!

GetItemAt extendido

Este método (GetItemAt) sólo provee información acerca del ListItem (si hay) ubicado en las coordenadas pasadas como parámetros, pero sólo funciona con la primera columna de un TListView. El resto se ignoran. Si necesitáramos conocer si el usuario pinchó un elemento en otra columna, podemos declarar un nuevo método en una clase derivada:

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
    // Primero, tratemos de encontrar la fila
    ListItem := GetItemAt(TopItem.Position.X, Y);
    if ListItem <> nil then begin
      // Ahora tratemos de encontrar la columna
      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;

Castando a una nueva clase

No necesitamos instalar este nuevo componente, registrarlo en la paleta de componentes ni reemplazarlo en nuestras aplicaciones tal como explicamos en otro artículo. En su lugar, cada vez que queramos acceder a este método, podemos castar (convertir) el objeto (por ejemplo ListView1) a nuestra nueva clase. Por ejemplo en un evento MouseDown:

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('Columna #' + IntToStr(col));
end;
JfControls Library - para Delphi y C++ Builder