Mirror

Check which subitem of a TListView's ListItem was clicked (Views: 101)


Problem/Question/Abstract:

I have a listview that is displayed using the vsReport view style. It contains a number of columns, and subsequently, the listitems have corresponding subitems. I want to give the user the ability to edit the text in any of the subitems by just clicking on the subitem. How does one do this? I can't seem to figure out a straight forward way to capture the subitem index when a listitem is clicked.

Answer:

The following is copied and pasted from 2 different units in an old D3 project. The version of ListView_SubItemHitTest in D3 didn't allow for subitems to be "hit-tested" I think because it wasn't available in the version of ComCtl32.DLL at the time.

uses
  CommCtrl, ComCtrls;

type
  { Updated version of TLVHitTestInfo (has also been updated in D5) }
  PLVHitTestInfoNew = ^TLVHitTestInfoNew;
  TLVHitTestInfoNew = record
    Pt: TPoint;
    Flags: Integer;
    iItem: Integer;
    iSubItem: Integer;
  end;

  {Updated version of CommCtrl function}

function ListView_SubItemHitTest(hwndLV: HWND; var lvhti: TLVHitTestInfoNew): Integer;
begin
  Result := SendMessage(hwndLV, LVM_SUBITEMHITTEST, 0, Longint(@lvhti));
end;

function ListViewSubItemHitTest(Handle: HWND; X: Integer; Y: Integer): Integer;
var
  HitTest: TLVHitTestInfoNew;
begin
  HitTest.pt.X := X;
  HitTest.pt.Y := Y;
  {Calls ListView_SubItemHitTest from *this* unit, not from CommCtrl.pas}
  ListView_SubItemHitTest(Handle, HitTest);
  Result := HitTest.iSubItem;
end;

procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Item: TListItem;
  iSubItem: Integer;
begin
  Item := ListView1.GetItemAt(X, Y);
  if Assigned(Item) then
  begin
    iSubItem := ListViewSubItemHitTest(ListView1.Handle, X, Y);
    {etc.}
  end;
end;

<< Back to main page