### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Clicking on a CheckListBox  (Read 560 times)

• Full Member
• Posts: 144
##### Clicking on a CheckListBox
« on: September 24, 2023, 10:22:43 am »
I'm sure I've seen the answer to this somewhere in the forum but I'm damned if I can find it.
I have a CheckListBox which changes fine from checked to unchecked and vice versa when the box is clicked.  However, if I click on the text, the CheckListBox  doesn't change.
I'm sure it can be made to work. Any suggestions?
(A bad tempered, grumpy animal that sleeps most of the winter!)

If at first you don't succeed - you're running about average!

I'm using Windows 10 Lazarus v2.4.4  FPC 3.2.2   Win 32/64

#### Fibonacci

• Full Member
• Posts: 219
• #PDK
##### Re: Clicking on a CheckListBox
« Reply #1 on: September 24, 2023, 10:59:14 am »
Quick, dirty and tricky

Code: Pascal  [Select][+][-]
1. procedure TForm1.CheckListBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
2. var
3.   i: integer;
4.   p: TPoint;
5. begin
6.   p := ScreenToClient(Mouse.CursorPos);
7.   p.Y -= TCheckListBox(Sender).Top;
8.   if x <= 16 then exit; //if clicked on checkbox then exit, otherwise it will double swap
9.   i := TCheckListBox(Sender).ItemAtPos(p, true);
10.   if i > -1 then TCheckListBox(Sender).Checked[i] := not TCheckListBox(Sender).Checked[i];
11. end;

#### Josh

• Hero Member
• Posts: 1196
##### Re: Clicking on a CheckListBox
« Reply #2 on: September 24, 2023, 12:10:30 pm »
or

Code: Pascal  [Select][+][-]
1. procedure TForm1.CheckListBox1MouseUp(Sender: TObject; Button: TMouseButton;
2.   Shift: TShiftState; X, Y: Integer);
3. Begin
4.   if Sender is TCheckListBox then
5.   begin
6.     If X>Scale96ToForm(22) then  // only do if on text.
7.     begin
8.       with Sender as TCheckListBox do
9.       begin
10.         Y:=GetIndexAtY(Y);
11.         if ((Y>=0)And(Y<=Items.Count)) then Checked[Y]:=not Checked[Y];
12.       end;
13.     end;
14.   end;
15. end;
« Last Edit: September 24, 2023, 12:14:59 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

#### KodeZwerg

• Hero Member
• Posts: 1720
##### Re: Clicking on a CheckListBox
« Reply #3 on: September 24, 2023, 12:51:36 pm »
or
Code: Pascal  [Select][+][-]
1. procedure TForm1.CheckListBox1Click(Sender: TObject);
2. begin
3.   if (not (Sender is TCheckListBox)) then
4.     Exit;
5.   if (Sender as TCheckListBox).ItemIndex < 0 then
6.     Exit;
7.  (Sender as TCheckListBox).Checked[(Sender as TCheckListBox).ItemIndex] := not (Sender as TCheckListBox).Checked[(Sender as TCheckListBox).ItemIndex];
8. end;
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

#### Paolo

• Sr. Member
• Posts: 444
##### Re: Clicking on a CheckListBox
« Reply #4 on: September 24, 2023, 01:29:24 pm »
@KodeZwerg. at my understanding it doesn't work as expected.
selection change but the box is not properly checked/unchecked.

#### Fibonacci

• Full Member
• Posts: 219
• #PDK
##### Re: Clicking on a CheckListBox
« Reply #5 on: September 24, 2023, 01:30:33 pm »
@KodeZwerg: Unfortunately, clicking the box undoes the check (attachment)

Im kinda bored (Sundays..), so I thought I will compare asmlists for these 3 solutions

1. Fibonacci: 39 lines with 5 call's and 14 mov's
Code: ASM  [Select][+][-]
1.         pushl   %ebp
2.         movl    %esp,%ebp
3.         subl    \$16,%esp
4.         pushl   %ebx
5.         pushl   %esi
6.         movl    %eax,%esi
7.         movl    %edx,%ebx
8.         leal    -16(%ebp),%edx
9.         movl    U_\$CONTROLS_\$\$_MOUSE,%eax
10.         call    CONTROLS\$_\$TMOUSE_\$__\$\$_GETCURSORPOS\$\$TPOINT
11.         leal    -16(%ebp),%edx
12.         leal    -8(%ebp),%ecx
13.         movl    %esi,%eax
14.         movl    (%esi),%esi
15.         call    *832(%esi)
16.         movl    576(%ebx),%eax
17.         subl    %eax,-4(%ebp)
18.         cmpl    \$16,12(%ebp)
19.         jle     .Lj19
20.         leal    -8(%ebp),%edx
21.         movb    \$1,%cl
22.         movl    %ebx,%eax
23.         call    STDCTRLS\$_\$TCUSTOMLISTBOX_\$__\$\$_ITEMATPOS\$TPOINT\$BOOLEAN\$\$LONGINT
24.         movl    %eax,%esi
25.         cmpl    \$-1,%eax
26.         jng     .Lj19
27.         movl    %eax,%edx
28.         movl    %ebx,%eax
29.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_GETCHECKED\$LONGINT\$\$BOOLEAN
30.         testb   %al,%al
31.         seteb   %cl
32.         movl    %esi,%edx
33.         movl    %ebx,%eax
34.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_SETCHECKED\$LONGINT\$BOOLEAN
35. .Lj19:
36.         popl    %esi
37.         popl    %ebx
38.         leave
39.         ret     \$12

2. Josh: 45 lines with 7 call's and 18 mov's
Code: ASM  [Select][+][-]
1.         pushl   %ebp
2.         movl    %esp,%ebp
3.         pushl   %ebx
4.         pushl   %esi
5.         pushl   %edi
6.         movl    %eax,%ebx
7.         movl    %edx,%esi
8.         movl    8(%ebp),%edi
9.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
10.         call    fpc_do_is
11.         testb   %al,%al
12.         je      .Lj18
13.         movl    \$22,%edx
14.         movl    %ebx,%eax
15.         call    CONTROLS\$_\$TCONTROL_\$__\$\$_SCALE96TOFORM\$LONGINT\$\$LONGINT
16.         cmpl    12(%ebp),%eax
17.         jnl     .Lj18
18.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
19.         movl    %esi,%edx
20.         call    fpc_do_as
21.         movl    %eax,%ebx
22.         movl    %edi,%edx
23.         call    STDCTRLS\$_\$TCUSTOMLISTBOX_\$__\$\$_GETINDEXATY\$LONGINT\$\$LONGINT
24.         movl    %eax,%edi
25.         testl   %eax,%eax
26.         jnge    .Lj18
27.         movl    896(%ebx),%eax
28.         movl    (%eax),%edx
29.         call    *132(%edx)
30.         cmpl    %edi,%eax
31.         jnge    .Lj18
32.         movl    %ebx,%eax
33.         movl    %edi,%edx
34.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_GETCHECKED\$LONGINT\$\$BOOLEAN
35.         testb   %al,%al
36.         seteb   %cl
37.         movl    %ebx,%eax
38.         movl    %edi,%edx
39.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_SETCHECKED\$LONGINT\$BOOLEAN
40. .Lj18:
41.         popl    %edi
42.         popl    %esi
43.         popl    %ebx
44.         leave
45.         ret     \$12

3. KodeZwerg: 47 lines with 11 call's and 22 mov's (shortest code is in fact the longest, thats a surprise)
Code: ASM  [Select][+][-]
1.         pushl   %ebx
2.         pushl   %esi
3.         pushl   %edi
4.         movl    %edx,%esi
5.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
6.         call    fpc_do_is
7.         testb   %al,%al
8.         je      .Lj13
9.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
10.         movl    %esi,%edx
11.         call    fpc_do_as
12.         movl    (%eax),%edx
13.         call    *1172(%edx)
14.         testl   %eax,%eax
15.         jl      .Lj13
16.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
17.         movl    %esi,%edx
18.         call    fpc_do_as
19.         movl    %eax,%edi
20.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
21.         movl    %esi,%edx
22.         call    fpc_do_as
23.         movl    %eax,%ebx
24.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
25.         movl    %esi,%edx
26.         call    fpc_do_as
27.         movl    (%eax),%edx
28.         call    *1172(%edx)
29.         movl    %eax,%edx
30.         movl    %ebx,%eax
31.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_GETCHECKED\$LONGINT\$\$BOOLEAN
32.         testb   %al,%al
33.         seteb   %bl
34.         movl    \$VMT_\$CHECKLST_\$\$_TCHECKLISTBOX,%eax
35.         movl    %esi,%edx
36.         call    fpc_do_as
37.         movl    (%eax),%edx
38.         call    *1172(%edx)
39.         movl    %eax,%edx
40.         movl    %edi,%eax
41.         movb    %bl,%cl
42.         call    CHECKLST\$_\$TCUSTOMCHECKLISTBOX_\$__\$\$_SETCHECKED\$LONGINT\$BOOLEAN
43. .Lj13:
44.         popl    %edi
45.         popl    %esi
46.         popl    %ebx
47.         ret

All compiled with max optimization with exact same settings.

#### wp

• Hero Member
• Posts: 11482
##### Re: Clicking on a CheckListBox
« Reply #6 on: September 24, 2023, 01:39:50 pm »
I have a CheckListBox which changes fine from checked to unchecked and vice versa when the box is clicked.  However, if I click on the text, the CheckListBox  doesn't change.
I don't like this:
• It makes the Listbox's ItemIndex obsolete because you cannot select an item without checking/unchecking it.
• When a checklistbox contains a longer list which must be scrolled the risk is too high that an item it clicked incidentally and thus changes its checked state.

#### Fibonacci

• Full Member
• Posts: 219
• #PDK
##### Re: Clicking on a CheckListBox
« Reply #7 on: September 24, 2023, 01:50:57 pm »
@wp: Depends on the use case. The 2 working samples can be moved to DblClick event, just remove the X checking

EDIT: 3 samples, @KodeZwerg's code works fine in DblClick event And its most reliable
« Last Edit: September 24, 2023, 01:54:56 pm by Fibonacci »

#### KodeZwerg

• Hero Member
• Posts: 1720
##### Re: Clicking on a CheckListBox
« Reply #8 on: September 24, 2023, 02:48:42 pm »
I actually was not testing the checkboxes to my shame.
To still have my own way shown, here tested: (uses LCLIntf, LCLType)
Code: Pascal  [Select][+][-]
1. procedure TForm1.CheckListBox1Click(Sender: TObject);
2. var
3.   ClickPos: TPoint;
4.   ItemIndex: Integer;
5.   CheckboxRect: TRect;
6.   CheckListBox: TCheckListBox;
7. begin
8.   if (Sender is TCheckListBox) then
9.     begin
10.       CheckListBox := (Sender as TCheckListBox);
11.       ClickPos := CheckListBox.ScreenToClient(Mouse.CursorPos);
12.       ItemIndex := CheckListBox.ItemAtPos(ClickPos, True);
13.       if (ItemIndex <> -1) then
14.       begin
15.         CheckboxRect := CheckListBox.ItemRect(ItemIndex);
16.         CheckboxRect.Right := CheckboxRect.Left + GetSystemMetrics(SM_CXMENUCHECK);
17.         if not PtInRect(CheckboxRect, ClickPos) then
18.           CheckListBox.Checked[ItemIndex] := not CheckListBox.Checked[ItemIndex];
19.       end;
20.     end;
21. end;
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

• Full Member
• Posts: 144
##### Re: Clicking on a CheckListBox
« Reply #9 on: September 24, 2023, 02:50:55 pm »
I can see wp's reasoning and I bow to the logic.  My reason for wanting to have clicking on the text change the checkbox was that the users of the application would be using it to select a number of settings from a list. They would probably expect it to act like a series of check boxes in a CheckGroup.  (I can't use a checkgroup because of the number of choices)
My users will just have to get used to it.
If you guys still want to discuss I'll leave the topic open but it's solved as far as I'm concerned.
(A bad tempered, grumpy animal that sleeps most of the winter!)

If at first you don't succeed - you're running about average!

I'm using Windows 10 Lazarus v2.4.4  FPC 3.2.2   Win 32/64

#### jamie

• Hero Member
• Posts: 5851
##### Re: Clicking on a CheckListBox
« Reply #10 on: September 24, 2023, 02:52:01 pm »
Please don't suggest modifications of the LCL, it works perfectly has documented to Delphi and it works fine.

There is already too much code in the LCL that is broken and hard to work with due to hit and run ideas.

The only true wisdom is knowing you know nothing