How to detect a click on the CheckBox in the TListView
Asked Answered
B

2

6

So basically when a user clicks on the checkbox, I want to add that item in my list, I have tried using the OnChange event but this is not working for me as it gets fired even when the Checkbox is not clicked.

My code is simple and straightforward

procedure LvUserChange(Sender: TObject; Item: TListItem;Change: TItemChange);
 var
 objUser : TUsers;
begin
   if not assigned(objListOfChangedUsers) then
   objListOfChangedUsers := TObjectList.Create;

   objUser := Item.Data;
   objListOfChangedUsers.Add(objUser);
end;

I want this code to be fired ONLY when the checkbox is clicked in the ListView

Bohr answered 15/8, 2017 at 12:33 Comment(10)
Really? Works for me. Show us your code and explain what unwanted behaviour occurs.Implosive
unwanted behaviour is that the Onchange event fires even though the Checkbox was not clicked as I stated in the question, is there any other event or method I can use?Bohr
You appear to be using the OnChange event rather than the OnClick Event. The OnChange event fires every time the component is changed for whatever reason.Implosive
Does OnItemChecked event exist in D2007?Ganesha
@Implosive So are you saying I should use the OnClick event? wont this fire even though Im not clicking on the checkbox?Bohr
Sorry - I meant the OnClickCheck event - you are quite right.Implosive
@Implosive I am not aware of this event in D2007Bohr
@Ganesha I dont think D2007 has that eventBohr
Do you have an OnItemChecked property? If so, that is the one to use.Implosive
@Implosive that property does not exist in D2007Bohr
O
9

In Delphi 2009 and later, you can use the TListView.OnItemChecked event to detect checkbox clicks. Delphi 2007 does not have such an event, in which case you will need to detect the notification manually in your own code. I will demonstrate with an interposer class, but there are other ways to do this.

uses
  ..., CommCtrl, ComCtrls, ...;

type
  TListView = class(ComCtrls.TListView)
  protected
    procedure CNNotify(var Message: TWMNotifyLV); message CN_NOTIFY;
  end;

....

procedure TListView.CNNotify(var Message: TWMNotifyLV);
begin
  inherited;
  if Message.NMHdr.code = LVN_ITEMCHANGED then
  begin
    if (Message.NMListView.uChanged = LVIF_STATE) and
       ( ((Message.NMListView.uOldState and LVIS_STATEIMAGEMASK) shr 12)
         <> ((Message.NMListView.uNewState and LVIS_STATEIMAGEMASK) shr 12)) then
    begin
      // changing check box state will land you here
    end;
  end;
end;
Outmaneuver answered 15/8, 2017 at 13:13 Comment(3)
This is the correct solution, and how TListView implements the OnItemChecked event in Delphi 2009+. However, do note that the checkboxes are implemented as state images, and the OnChanging and OnChange events are fired with Change=ctState when an item's checkbox state is (being) changed, and TListItem does have a Checked property in D2007.Norther
@David, since this is sort of a hack, is it preferable to put this in a separate unit?Bohr
That's how I'd do it. I'd make a derived class that surfaced the same event as modern Delphi. But it's really up to you how you organise your code.Outmaneuver
I
3

Since OnItemChecked does not exist, you cannot get your event to fire only when the item is checked, but you can filter your event like this

procedure LvUserChange(Sender: TObject; Item: TListItem;Change: TItemChange);
 var
 objUser : TUsers;
begin
   if Change = ctState then
   begin
     if Item.Checked then
     begin
       if not assigned(objListOfChangedUsers) then
       objListOfChangedUsers := TObjectList.Create;

       objUser := Item.Data;
       objListOfChangedUsers.Add(objUser);
     end
     else
     begin
       // just in case there are any actions when unchecking
     end;
   end;
end;

I don't have Delphi 2007 but have checked the documentation and it should work.

Implosive answered 15/8, 2017 at 14:12 Comment(1)
I can confirm this does not work, as the event fires even when the checkbox was not clicked but instead by putting a focus on the "checked" Item, then all the condions becomes true and ends up adding the item to the listBohr

© 2022 - 2024 — McMap. All rights reserved.