2005. február 22., kedd
Check which column of a TListView in vsReport style has been clicked
Problem/Question/Abstract:
How can I know which column was click in a TListView? GetItemAt only works with the first column.
Answer:
Solve 1:
The 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:
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 ("Adding new methods and properties without registering new components"). 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.GetItemAtX(x, y, col);
if li <> nil then
ShowMessage('Column #' + IntToStr(col));
end;
Solve 2:
uses
commctrl;
procedure TForm1.ListView1Click(Sender: TObject);
var
pt: TPoint;
col: Integer;
pos: Integer;
begin
GetCursorPos(pt);
pt := Listview1.ScreenToClient(pt);
Pos := -GetScrollPos(ListView1.Handle, SB_HORZ);
Col := -1;
while Pos < Pt.X do
begin
Inc(Col);
Inc(Pos, ListView_GetColumnWidth(ListView1.Handle, Col));
end;
if Col >= ListView1.Columns.Count then
Col := -1; {clicked past last column}
showmessage(inttostr(col));
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése