Determine where in a listbox row the mouse moved

I have a “button” that I draw in a single column listbox row. When I draw it, I compute its local bounds so I can decide if it’s clicked on.

I use the DesktopListbox.MouseMoved() event to capture the absolute position of the mouse within the listbox when it moved. I can compute the row moved over in this event with the RowFromXY() method. How do I determine the Y coordinate for the row being moved over. The Y coordinate provided in the event is relative to the top left corner of the control but what if the listbox has scrolled?

Have you tried offsetting your Y coordinate by the number of rows scrolled x the row height.

X,Y in the mouseMove is top-lelf of the listBox

The first row of the lisbox is already 0

Yes I but I have this in my MouseMove event:

mLastMouseMoveX  = x
mLastMouseMoveY = y

mLastMouseOverRow = Me.RowFromXY(x, y)
If mLastMouseOverRow > Me.LastRowIndex Then mLastMouseOverRow = -1

// Calculate the absolute Y coordinate of the top of this row: visible row offset * row height
Var rowTopY As Integer = (row - ScrollPosition) * DefaultRowHeight

mLastMouseMoveLocalY = absoluteY - rowTopY

But I think ScrollPosition doesn’t account for fractional row scrolling (i.e. the Listbox doesn’t scroll one line at a time).

It is not possible

RowFromXY always returns -1 if the pointer is beyond the last row

Var rowTopY As Integer = (row - ScrollPosition) * DefaultRowHeight

It will be difficult to have the right number because you also have to take into account the thickness of the separators

Do you want to know if the user has changed cell?

I can’t ever remember seeing the listbox not scroll by an entire row unless this is a new DesktopListbox feature.

I’ve just pulled this bit of code from one of our projects. This should calculate the local Y position within a row.

row = Self.RowFromXY(pX, pY)

localY = pY - ((row - Self.ScrollPosition) * Self.DefaultRowHeight)

This can happen when the listbox is scrolled to the very bottom and the height of the listbox isn’t a multiple of the row’s height (disregarding the header, of course).

You’ll notice the top row is perfectly even because Listboxes only scroll a whole row at a time. This makes the RowFromXY related math quite easy.

I’m not sure where Garry got the misinformation that Listboxes scrolled partial rows, but I have An Intuition.

You guys are right. For some reason I thought partial scrolling was a thing but I’m wrong. The DesktopListbox definitely only scrolls one row at a time.

This works for me in MouseMove():

mLastMouseMoveX  = x
mLastMouseMoveY = y

mLastMouseOverRow = Me.RowFromXY(x, y)
If mLastMouseOverRow > Me.LastRowIndex Then mLastMouseOverRow = -1

// Calculate the absolute Y coordinate of the top of this row: visible row offset * row height
If mLastMouseOverRow <> -1 Then
  Var rowTopY As Integer = (mLastMouseOverRow - ScrollPosition) * DefaultRowHeight
  mLastMouseMoveLocalY = Max(-1, y - rowTopY)
Else
  mLastMouseMoveLocalY = -1
End If

Me.Refresh

Oh, you’re right. It’s the bottom which stays empty in such cases.

Sorry.