Unfortunately, the TListView object does not have a specific event fired, when the
Checked state changes for a TListItem (an item in the ListView). If you need to react in such situation, you have to mimic this behaviour yourself. Here are some tips on this.
Every Delphi's Guru will probably think about subclassing and catching windows messages here. If you're one of them -- at delphi.about.com you'll find an example. But, there's an easier way to achieve the same.
All you have to do is to catch
OnMouseUp and use two methods of
TListView there --
GetItemAt. Here is full example:
procedure TMainForm.ListViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ht: THitTests; Item: TListItem; begin ht := (Sender as TCustomListView).GetHitTestInfoAt(X, Y); if htOnStateIcon in ht then begin Item := (Sender as TCustomListView).GetItemAt(X, Y); ShowMessage('OnCheckboxClick fired on item "' + Item.Caption + '"'); end; end;
If, for any reason, you need to use
OnClick event (which does not provides
Y variables), you still can do this, but you need to add these lines to your code:
var P: TPoint; begin GetCursorPos(P); P := (Sender as TCustomListView).ScreenToClient(P);
and then change:
ht := (Sender as TCustomListView).GetHitTestInfoAt(X, Y);
ht := (Sender as TCustomListView).GetHitTestInfoAt(P.X, P.Y);
Leave rest untoched and your code should work the same even in
This example uses
(Sender as TCustomListView) construction, because I use the same procedure as
OnMouseUp even handler for more than one
TListView. If you only need to use this solution for one ListView, you can use its name directly (i.e.
ListView1.GetItemAt assuming that it's name is
Of course, this solutions mimic
OnCheckBoxStateChange. This means, that with it, you can react only on user clicking checbox. You can't react this way on checkbox changing state by programical meanings -- i.e. changing
TListItem.Checked property from your code.