Recent

Author Topic: CheckListBox - Detect checkbox click  (Read 451 times)

gii

  • New Member
  • *
  • Posts: 28
CheckListBox - Detect checkbox click
« on: October 23, 2019, 10:20:06 pm »
I have a CheckListBox and in the OnMouseDown event I need to know if the user clicked on the text or Checkbox.

I currently use the following code:

Code: Pascal  [Select]
  1. procedure TForm1.CheckListBox1MouseDown(Sender: TObject; Button: TMouseButton;
  2.   Shift: TShiftState; X, Y: Integer);
  3. var
  4.     ARect : TRect;
  5.     AIndex : Integer;
  6. begin
  7.   AIndex := CheckListBox1.GetIndexAtXY( X, Y );
  8.  
  9.   if AIndex >= 0 then
  10.   begin
  11.     ARect := CheckListBox1.ItemRect( AIndex );
  12.     ARect.Left := ARect.Left + TWSCustomCheckListBoxClass(CheckListBox1.WidgetSetClass).GetCheckWidth(CheckListBox1);
  13.  
  14.     if PtInRect( ARect, Point( x, y ) ) = False then
  15.       Caption := 'Checkbox'
  16.     else
  17.       Caption := 'Text';
  18.   end;
  19. end;
  20.  

But the code:

Code: Pascal  [Select]
  1. TWSCustomCheckListBoxClass(CheckListBox1.WidgetSetClass).GetCheckWidth(CheckListBox1)
  2.  

Always returns zero.

This code was taken from the CheckLst.pas > TCustomCheckListBox.GetCheckWidth unit.

Code: Pascal  [Select]
  1. function TCustomCheckListBox.GetCheckWidth: Integer;
  2. begin
  3.   if HandleAllocated then
  4.     Result := TWSCustomCheckListBoxClass(WidgetSetClass).GetCheckWidth(Self)
  5.   else
  6.     Result := 0;
  7. end;  
  8.  

Can someone help me?

wp

  • Hero Member
  • *****
  • Posts: 6301
Re: CheckListBox - Detect checkbox click
« Reply #1 on: October 23, 2019, 10:40:33 pm »
Don't do it yourself. Use the OnClickCheck event instead of OnMouseDown.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

gii

  • New Member
  • *
  • Posts: 28
Re: CheckListBox - Detect checkbox click
« Reply #2 on: October 23, 2019, 10:52:51 pm »
The OnClickCheck event does not detect text clicks.

fmc

  • New Member
  • *
  • Posts: 23
Re: CheckListBox - Detect checkbox click
« Reply #3 on: October 23, 2019, 11:44:23 pm »
I've had this same problem.
« Last Edit: October 23, 2019, 11:56:51 pm by fmc »
Win X Pro / Lazarus 2.0.6 / FPC 3.0.4

jamie

  • Hero Member
  • *****
  • Posts: 2068
Re: CheckListBox - Detect checkbox click
« Reply #4 on: October 23, 2019, 11:49:21 pm »
There seems to be a bug in there, I just made the GetCheckWidth visible as a property , tracked to its widgetset call and it always returns 0.

 So I guess there is a missing system call somewhere..

 This is with the 2.0.4 64 bit windows Widget
Number 1 at blue screen app creations!

jamie

  • Hero Member
  • *****
  • Posts: 2068
Re: CheckListBox - Detect checkbox click
« Reply #5 on: October 24, 2019, 12:59:06 am »
I did this but it only works for windows..
Code: Pascal  [Select]
  1. procedure TForm1.CheckListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3. Var
  4.   R:Trect;
  5. begin
  6.   With TCheckListBox(Sender) do
  7.     begin
  8.      R := ItemRect(0);
  9.      Inc(R.Left, GetSystemMetrics(SM_CXSMSIZE));
  10.      if PtInRect(R, Point(X,Y)) then Beep;
  11.     end;
  12. end;                                                  
  13.  

And I can't guarantee this will work across the board but it seems to match what I is currently being used in windows as size etc.

Number 1 at blue screen app creations!

gii

  • New Member
  • *
  • Posts: 28
Re: CheckListBox - Detect checkbox click
« Reply #6 on: October 24, 2019, 01:13:22 am »
I did this but it only works for windows..
Code: Pascal  [Select]
  1. procedure TForm1.CheckListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3. Var
  4.   R:Trect;
  5. begin
  6.   With TCheckListBox(Sender) do
  7.     begin
  8.      R := ItemRect(0);
  9.      Inc(R.Left, GetSystemMetrics(SM_CXSMSIZE));
  10.      if PtInRect(R, Point(X,Y)) then Beep;
  11.     end;
  12. end;                                                  
  13.  

And I can't guarantee this will work across the board but it seems to match what I is currently being used in windows as size etc.

Even being part of LCLType and LCLIntF would not work on other platforms?

Unfortunately it is not entirely accurate, if I click on the space between the text and the checkbox, it detects the click as if it were in the checkbox.

I would like to click on the text, and check / uncheck the checkbox. Perhaps there is an easier way to do this.

jamie

  • Hero Member
  • *****
  • Posts: 2068
Re: CheckListBox - Detect checkbox click
« Reply #7 on: October 24, 2019, 01:25:41 am »
Well of course it would, its the width from the start to the start of the text.

 GetSystemMetrics(SM_CXMENUCHECK) reports the width of the check mark which is smaller than the small button size.

 You need to build the Rectangle based on these values.

 So if you take the first value I gave you and DIV 2 that gives you the center mark of the check mark, then take the Second value MENUCHECK and use that div 2 as the +/- position of that center and that will give you the check mark target. At Least it works out that way..

 I'll see If I can work out the math for that one too...

 Like I said, there is no sure bet this is correct but it seems to work out with my windows 10 this way.
Code: Pascal  [Select]
  1. procedure TForm1.CheckListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3. Var
  4.   R:Trect;
  5. begin
  6.   With TCheckListBox(Sender) do
  7.     begin
  8.      R := ItemRect(0);
  9.      Inc(R.Left, GetSystemMetrics(SM_CXSMSIZE) DiV 2);
  10.      R.Right := R.Left;
  11.      InflateRect(R, GetSystemMetrics(SM_CXMENUCHECK) Div 2,0);
  12.      if PtInRect(R, Point(X,Y)) then Beep;
  13.     end;
  14. end;                                                            
  15.  

Now if you want vertical narrowing then follow the example here for the horizontal but use
SM_CY... instead when fetching values.

 As for the other targets, maybe the checkWidth works there and its also possible the API call I used here is also supported there in the LCLintf.
« Last Edit: October 24, 2019, 01:38:00 am by jamie »
Number 1 at blue screen app creations!

gii

  • New Member
  • *
  • Posts: 28
Re: CheckListBox - Detect checkbox click
« Reply #8 on: October 24, 2019, 03:52:16 am »
Thanks for your efforts, but I still didn't get 100% accuracy.

I ended up using a simpler code that met my need.

Code: Pascal  [Select]
  1. procedure TForm1.CheckListBox1ItemClick(Sender: TObject; Index: integer);
  2. begin
  3.   FCheckByMouse := True;
  4. end;
  5.  
  6. procedure TForm1.CheckListBox1MouseDown(Sender: TObject; Button: TMouseButton;
  7.   Shift: TShiftState; X, Y: Integer);
  8. begin
  9.   FCheckByMouse := False;
  10. end;
  11.  
  12. procedure TForm1.CheckListBox1MouseUp(Sender: TObject; Button: TMouseButton;
  13.   Shift: TShiftState; X, Y: Integer);
  14. var
  15.     AIndex : Integer;
  16. begin
  17.   if FCheckByMouse = False then
  18.   begin
  19.     AIndex := CheckListBox1.ItemAtPos( Point( X, Y ), True );
  20.  
  21.     if AIndex >= 0 then
  22.       CheckListBox1.Checked[ AIndex ] := ( CheckListBox1.Checked[ AIndex ] = False );
  23.   end;
  24. end;