Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2095
  • Last Modified:

Select subItem in TListView

I am using Delphi 5.  
I have a TListview with the ViewStyle as vsReport.  It has 8 columns and the number of rows varies.  I need some code to get the string that is located where the user double clicks on the TListView.  No mater what subitem they click on.  

Thanks

Rich
0
coondog091800
Asked:
coondog091800
  • 4
  • 4
  • 2
1 Solution
 
shaneholmesCommented:

This will give you the first column

 ListView1.Selected.Caption

This will give you the additional columns:

 ListView1.Selected.Subitems[n]

WHere n is the column number

Shane
0
 
shaneholmesCommented:
IM sorry, that is assuming you have rowselect = true

SHane
0
 
shaneholmesCommented:
procedure TForm1.ListView1DblClick(Sender: TObject);
var
 MP: TPoint;
 Pt: TSmallPoint;
 LI: TListItem;
begin
GetCursorPos(MP);
Pt := PointToSmallPoint(ListView1.ScreenToClient( MP ));
LI := ListView1.GetItemAt( pt.X, pt.Y );
if LI <> nil then
 ShowMessage(LI.SubItems[1]);
end;

Shane
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
shaneholmesCommented:
If you want to determine the Column of the item selected,  you need to get the item  like I show above, and prbably manually determine which column was clicked by comparinng to column widths.

Shane
0
 
mokuleCommented:
Try this

var
  SelTxt: string;

procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  l: TListItem;
  i: integer;
  w: integer;
begin
 l := ListView1.GetItemAt( 3, Y );
 SelTxt := '';
 if l <> nil then
   begin
   w := 0;
   for i := 0 to ListView1.Columns.Count-1 do
     begin
     w := w + ListView1.Column[i].Width;
     if w >= X then
       begin
       if i = 0 then
         SelTxt := l.Caption
       else
         SelTxt := l.SubItems[i-1];
       break;
       end;
     end;
   end;
end;

procedure TForm1.ListView1DblClick(Sender: TObject);
begin
  // do something with SelTxt
end;
0
 
MikProgCommented:
mokule: you miss partially scrolled listview so X is not position in list columns but position in list window. From now I can figure out how to find value of scroll offset.

BOOL ListView_GetItemRect(
    HWND hwnd,       
    int i,       
    RECT FAR *prc,       
    int code      
   );      
PRC.LEFT returns negative value of offset.

 l := ListView1.GetItemAt( 3, Y );
if not Assigned(l) then
  exit;
 SelTxt := '';
r.Left:=LVIR_BOUNDS;
 ListView_GetItemRect(Listview1.Handle,l.Index,r,LVIR_BOUNDS);
 w:=r.left;

0
 
mokuleCommented:

Yes. You are right. But You don't solve the problem :(
0
 
mokuleCommented:
Thanks to MikProg hint I think that this time I solve the problem to the end.

procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
const
  LVM_FIRST = $1000;
  LVM_GETITEMRECT = (LVM_FIRST + 14);
  LVIR_BOUNDS = 0;
var
  l: TListItem;
  i: integer;
  w: integer;
  r: TRect;
begin
  l := nil;
  for i := 0 to ListView1.Items.Count-1 do
    begin
    r.Left := LVIR_BOUNDS;
    SendMessage(ListView1.Handle,LVM_GETITEMRECT,WPARAM(i),LPARAM(@r));
    if (Y > r.Top) and (Y < r.Bottom) then
      begin
      l := ListView1.Items[i];
      break;
      end;
    end;
 SelTxt := '';
 if l <> nil then
   begin
   w := r.Left;
   for i := 0 to ListView1.Columns.Count-1 do
     begin
     w := w + ListView1.Column[i].Width;
     if w >= X then
       begin
       if i = 0 then
         SelTxt := l.Caption
       else if l.SubItems.Count >= i then
         SelTxt := l.SubItems[i-1];
       break;
       end;
     end;
   end;
end;
0
 
MikProgCommented:
mokule: We want to grab points fast. We are wrong. The Easiest Way To Get Display Rectangle of List Item Is to Call
   DisplayRect function of TListItem class :(
Althought both answers were right but we wrong. Therfore why you define LVM_ constants they definitions included in CommCtrl.pas (where you can find ListView_GetItemRect definition. My piece of code works well no need to send messages).
0
 
mokuleCommented:
MikProg
Thanks again.

CommCtrl isn't appended to the uses automatically and I've omitted it somehow.

If You've tested Your answer You would know that it didn't work. Though You may argue that the wrong line is from my code but something has had to be done with it.
To be concrete. After scrolling this doesn't work.
 l := ListView1.GetItemAt( 3, Y );
It was this what had to be changed.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now