Control: TAdvSmoothListBox (in TMSSmoothControlsPack V5.3.0.0)
IDE: Delphi 10.3.2 Rio
Problem:
I have the TAdvSmoothListBox.OnItemDraw event assigned for some 'on demand' processing when an item becomes visible and found that it was sometimes fired for all items in the list during a scroll operation - not just the visible ones as I expected.
Creating a quick test app with a TAdvSmoothListBox dropped on a form seemed to work. Since I had some appearance properties overridden, I traced the program into the TAdvSmoothListBox.DrawItems procedure.
It turns out that any non-zero value for ItemAppearance.VerticalSpacing meant that the GetBottomIndex() function was, on occasion, missing the item (in YToItem() function) and returning the last index.
In other words, YToItem() was returning -1 because the loop with the PtInRect(ItemRect,Point()) test did not account for the vertical gap between items.
Steps to reproduce:
Drop a TAdvSmoothListBox on a form and set OnItemDraw to trace the itemindex.
eg. OutputDebugString the itemindex value
Add additional items if required to ensure the list will scoll.
Run and scroll list. This will work (with the default ItemAppearance.VerticalSpacing := 0)
Set ItemAppearance.VerticalSpacing to any non-zero value. I had 2, but using a large value, say 20, will make the problem obvious.
Run again. The initial trace will be correct, but thereafter all items will sometimes be listed even with minor scrolling.
My temporary fix:
In function TAdvSmoothListBox.YToItem() - Line 2562 of AdvSmoothListBox.pas
A) Add a local variable:
var
lItemRect: TRect; //<<< ADDED
B) Insert before the PtInRect() text (around line 2586)
lItemRect := FDisplayList.GetItem(i).ItemRect; //<<< ADDED
lItemRect.Top := lItemRect.Top - ItemAppearance.VerticalSpacing; //<<< ADDED
if PtInRect(lItemRect, Point(X, Y + GetPosition)) and check then //<<< CHANGE
This worked for me but you may arrive at a more elegant solution.
Regards, Ian