Recent

Author Topic: Clicking on a CheckListBox  (Read 1134 times)

Badger

  • Full Member
  • ***
  • Posts: 153
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?
Badger
(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.2.4  FPC 3.2.2   Win 32/64

Fibonacci

  • Hero Member
  • *****
  • Posts: 595
  • Internal Error Hunter
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: 1344
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: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
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 xm by KodeZwerg »

Paolo

  • Hero Member
  • *****
  • Posts: 538
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

  • Hero Member
  • *****
  • Posts: 595
  • Internal Error Hunter
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 :D

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: 12457
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

  • Hero Member
  • *****
  • Posts: 595
  • Internal Error Hunter
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 :D And its most reliable
« Last Edit: September 24, 2023, 01:54:56 pm by Fibonacci »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
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 xm by KodeZwerg »

Badger

  • Full Member
  • ***
  • Posts: 153
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.
Badger
(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.2.4  FPC 3.2.2   Win 32/64

jamie

  • Hero Member
  • *****
  • Posts: 6734
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

 

TinyPortal © 2005-2018