To try and get my head around clicking in TCheckList boxes, I'll summarise what I've learned, some of which is from other forum posts.
- Clicking on the item in a TCheckListBox fires the onclick handler.
- Clicking on the checkbox fires both the onclick and onclickcheck handlers.
This is not good, there is not not a unique handler for each action*. This is made worse by the fact that:
- Clicking on an item does NOT change the state of the checkbox.
- Clicking on the checkbox does change the state of the checkbox, more importantly it changes the state of the checkbox before calling any event handler. I have not found any way of stopping this.
This means that a single
onclick handler cannot be used. If your handler runs a series of checks to determine if the user can change the state (mine do), then a simple
Checked:= not Checked; at the end cannot be used to toggle. The
onclick handler does not know whether it was fired from an item click or checkbox click (where the state has already been changed). Nor can you use a simple
onclickcheck handler that just flips the state, i.e.
Checked:= not Checked;. You cannot GUARANTEE the firing order, onclick > onclickcheck or onclickcheck > onclick.
I had previously tried and abandoned Jamie's idea - using
onclickcheck to toggle a flag. This doesn't work because of the firing order issue. I have found the first click on the checkbox is onclick > onclickcheck, subsequent clicks reverse this.
The solution I adopted was a custom TCheckListBox - adding
CheckState : array of boolean, where
CheckState maintains the state of the CheckBoxes. The
onclickcheck handler simply resets the checkbox from
CheckState, i.e.
Checked[j]:= CheckState[j]; so
onclick can do the grunt work and is responsible for maintaining
CheckState. Downside - increased complexity.
I also (by accident) looked at setting
Selected:= false in the
onclick handler. This results in:
- calls to the onclickcheck handler ALWAYS being passed an itemindex = -1, onclick does get passed the correct itemindex
- clicking on the checkbox still flips the state before calling any handler
- in theory selected:= false inside the onclick handler should create an infinite loop, in practice it doesn't, it fires twice. I can only assume that there must be some internal code to trap this. Still not a good idea and it doesn't help.
Life would be a LOT simpler if there were unique handlers for each action, or that clicking on the checkbox did
not flip state before calling the handler. I've spent so much time on this that I've kind of lost sight of the original objective.
* There is also onitemclick, but as I understand, this is fired by both clicking on the item or the checkbox, same as onclick, I can't see the point of it. Neither does dephi.