Recent

Author Topic: CheckListBox with lbOwnerDrawFixed does not draw check boxes  (Read 2137 times)

Aidex

  • Jr. Member
  • **
  • Posts: 82
CheckListBox with lbOwnerDrawFixed does not draw check boxes
« on: April 07, 2020, 11:39:57 am »
When I set CheckListBox.Style :=  lbOwnerDrawFixed, no check boxes are drawn.
But in Delphi the boxes are shown.
How can I get the boxes to be drawn with the lbOwnerDrawFixed style?
I'm using Lazarus 2.0.6 on Win64.

martijnn

  • New Member
  • *
  • Posts: 16
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #1 on: April 07, 2020, 02:49:02 pm »
I've also encountered this a while ago when porting a Delphi application. Strange thing is that with Lazarus 2.0.6 on Mac (with Carbon WidgetSet) a glimpse of the check boxes can be noticed when clicking the items at the position you would expect the checkbox. As there's no TCarbonWSCustomCheckListBox.GetCheckWidth override the rectangle to draw the actual item will not be adjusted correctly.

So indeed it would be good to know if one is expected to draw check boxes manually -or- not (as is the case with Delphi) when using TCheckListBox with owner drawing. Maybe someone can clarify.

(Btw, I ended up by replacing the control instance with a treeview and stateimages)

Bart

  • Hero Member
  • *****
  • Posts: 5265
    • Bart en Mariska's Webstek
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #2 on: April 07, 2020, 03:09:35 pm »
Already reported as Issue 29525.

Bart

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #3 on: April 07, 2020, 04:45:06 pm »
Hmmm... When delphi draws the checkboxes, this is an argument, of course, that we should do it as well. But on the other hand, then there is no way for the component user to draw the checkboxes by himself.

Aidex

  • Jr. Member
  • **
  • Posts: 82
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #4 on: April 07, 2020, 06:13:39 pm »
If a user wants to paint the boxes himself, he can simply take a TListBox with lbOwnerDrawFixed.
The advantage of a CheckListBox is that you don't have to draw the boxes yourself.

Or introduce an option like .DrawCheckBoxes: Boolean;
« Last Edit: April 07, 2020, 06:20:41 pm by Aidex »

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #5 on: April 07, 2020, 10:48:49 pm »
No the check mark should not be drawn in this state, that is a fault of Delphi doing that because it uses the OS...

  Using  a Tlistbox is not the answer because it has no previsions for the check hot spot and event calls. The TCheckListBox does.

 I think the best would be to provide a option flag to draw it instead..

 So my question here is why do you need ownerdraw when  you still want the check mark to be drawn? Kind of makes the whole purpose of ownerdraw useless in my eyes..

 ALso while we are talking about this, there should be a property to set the spacing of the check mark hot spot area. That is also annoying … A TRect that fits within the TREct given would be nice.

The only true wisdom is knowing you know nothing

Aidex

  • Jr. Member
  • **
  • Posts: 82
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #6 on: April 08, 2020, 06:36:21 am »
I use OwnerDraw here for the same reason that this option exists in TListBox, namely to format the text (in my case, to indent the text lines differently).
I converted my program from Delphi, and now I have no solution for this.

furious programming

  • Hero Member
  • *****
  • Posts: 836
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #7 on: April 08, 2020, 08:53:34 am »
I like to render the checkbox myself, because I can do it as I want — on the top, center or bottom of the item, enabled or disabled, checked, unchecked or mixed. In my bigger project, I have multiple instances of TCheckListBox and I'm rendering checkboxes always on the left top corner (not vertical centered). It is few lines of code, but I have a freedom of choice. 8)
« Last Edit: April 08, 2020, 08:56:16 am by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #8 on: April 08, 2020, 10:21:14 am »
Use the ThemeServices to draw native checkboxes. Here is some tested code:

Code: Pascal  [Select][+][-]
  1. uses
  2.   Themes;
  3.  
  4. procedure TForm1.CheckListBox2DrawItem(Control: TWinControl; Index: Integer;
  5.   ARect: TRect; State: TOwnerDrawState);
  6. var
  7.   listbox: TCheckListbox;
  8.   details: TThemedElementDetails;
  9.   R: TRect;
  10.   wcheck: Integer;
  11. begin
  12.   if not (Control is TCheckListbox) then
  13.     exit;
  14.   listbox := TCheckListbox(Control);
  15.  
  16.   if listbox.Selected[Index] then
  17.   begin
  18.     listbox.Canvas.Brush.Color := clHighlight;
  19.     listbox.Canvas.Font.Color := clHighlightText;
  20.   end else
  21.   begin
  22.     listbox.Canvas.Brush.Color := clWindow;
  23.     listbox.Canvas.Font.Color := clWindowText;
  24.   end;
  25.   if not listbox.ItemEnabled[Index] then
  26.     listbox.Canvas.Font.Color := clGrayText;
  27.   listbox.Canvas.FillRect(ARect);
  28.  
  29.   if listbox.Checked[Index] then
  30.   begin
  31.     if listbox.ItemEnabled[Index] then
  32.       details := ThemeServices.GetElementDetails(tbCheckboxCheckedNormal)
  33.     else
  34.       details := ThemeServices.GetElementDetails(tbCheckboxCheckedDisabled)
  35.   end else
  36.   begin
  37.     if listbox.ItemEnabled[Index] then
  38.       details := ThemeServices.GetElementDetails(tbCheckBoxUncheckedNormal)
  39.     else
  40.       details := ThemeServices.GetElementDetails(tbCheckboxUncheckedDisabled);
  41.   end;
  42.   wcheck := ARect.Height - 2;
  43.   R := Rect(ARect.Left + 2, ARect.Top + 2, ARect.Left + wcheck, ARect.Top + wcheck);
  44.   ThemeServices.DrawElement(listbox.Canvas.Handle, details, R, nil);
  45.  
  46.   listbox.Canvas.TextOut(R.Left + wcheck + 2, ARect.Top + 2, listbox.Items[Index]);
  47. end;

Playing with the TCheckCombobox to prepare this code I noticed that the CheckListbox does display the text in the ownerdraw styles, but not the checkbox, while no OnDrawItem handler is assigned. I think this really is a bug. It makes sense to set Style to lbOwnerdrawFixed in order to change for example the ItemHeight for some reason but to keep the original drawing process.

As already discussed, however, the checkbox should not be drawn automatically in the ownerdraw styles once an OnDrawItem handler is assigned.
« Last Edit: April 08, 2020, 10:33:55 am by wp »

Aidex

  • Jr. Member
  • **
  • Posts: 82
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #9 on: April 08, 2020, 11:27:56 am »
Thanks for the code example!  :)
Do I then also have to evaluate the mouse coordinates when clicking? To distinguish whether the text has been clicked on (to mark the entry) or if the box has been clicked on? (to un/tick the box)

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #10 on: April 08, 2020, 02:13:03 pm »
I use my old check boxes from a TimageList, I like fancy looking Xes and checkmarks ,.,.,.

But one issue to consider is the option to adjust the hot spot for the check area so that it can be read for drawing code to work around it there for saving it for your checkmark drawing. also this area information should be in a property as a Rect for instance so that it can be adjusted initially if the default position and size is not desirable .


The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #11 on: April 08, 2020, 02:31:13 pm »
Do I then also have to evaluate the mouse coordinates when clicking? To distinguish whether the text has been clicked on (to mark the entry) or if the box has been clicked on? (to un/tick the box)
I think the checkbox in my code is positioned close to the default. Therefore the click point is handled correctly by the control internally. No extra code is needed to distinguish between clicks on the checkbox and clicks on the text.

However, since we are allowed/forced to draw the item completely on our own we could draw the checkmark at a completely different position, maybe at the right- why not? In such a case, there should be a property to define the checkmark position within the item rect, just as jamie noted.

The TCheckListBox looks more and more incomplete the closer I look...

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: CheckListBox with lbOwnerDrawFixed does not draw check boxes
« Reply #12 on: April 08, 2020, 03:49:56 pm »
Sounds great to me! Thanks..

make sure its an OFFSET type of property that way it will fluidly fit in any location of drawing and does not need to be updated during the Pant Event calls, one only needs to reference the property from a fixed location. No Added event calls that way


The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018