Tuesday, February 27, 2007

TListBox bug

Another one of those bugs that make our life difficult. I have been trying to make a list box with variable item height. I wanted the height of each item to vary, depending on the item, so I thought I would associate a dummy object with each string of the list box, using code like this:

MyListBox.AddItem(aStr, Pointer(theHeight));

Then I would use an OnMeasureItem event to set the height:

procedure MyForm.MyListBoxMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer);
begin
Height := integer(MyListBox.Items.Objects[Index]);
end;

However, this does not work. The reason is rather interesting. When the AddItem procedure is called, the string is first added to the list box, then Delphi triggers the OnMeasureItem event, BEFORE the object has been added, so the event finds no object in the Items.Objects collection.
My workaround was to add the height as the first character of the string:

MyListBox.Items.Add(Char(theHeight) + aStr);

Then, in the OnMeasureItem procedure, I strip the character and convert it to an integer value:

Height := byte(MyListBox.Items[Index][1]);

Note that this will only work if the variable stored in the first character of the string is not zero, otherwise it will be mistaken as a string termination character and a null string will be added to the list box.

1 comment:

  1. Anonymous5:03 PM

    Encountered this post via a google search on the same problem. For what it's worth I can tell you that the problem is even more annoying: you can't access the Objects array values during onMeasure at all, no matter when you initialized it. You can check this by keeping the listbox as lbOwnerDrawFixed style while you insert the strings/objects and setting it to lbOwnerDrawVariable afterwards. During OnDrawItem you can access the objects fine, but during onMeasureItem they're all nil.
    Very annoying bug indeed.

    ReplyDelete