-
Notifications
You must be signed in to change notification settings - Fork 991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ListBox.IndexFromPoint should be Int32 but currently is Int16 #12637
Comments
ListBox.IndexFromPoint uses the LB_ITEMFROMPOINT message for which this is a documented limitation:
I suppose it would be possible to work around the limitation by making ListBox.IndexFromPoint use other messages. For example, send LB_GETITEMRECT and check whether the rectangle is close enough to the specified point; if it isn’t, then do a binary search with more LB_GETITEMRECT messages. Alternatively, change the application to use the ListView control. |
ChatGPT suggestion based on @KalleOlaviNiemitalo /// <summary>
/// Retrieves the index of the item at the given coordinates, without being limited to 65,535 items.
/// </summary>
public int IndexFromPoint(int x, int y)
{
// Check if the point is within the client rectangle
PInvokeCore.GetClientRect(this, out RECT clientRect);
if (!(clientRect.left <= x && x < clientRect.right && clientRect.top <= y && y < clientRect.bottom))
{
return NoMatches; // Point is outside the client area
}
// Get the total number of items in the list box
int itemCount = (int)PInvokeCore.SendMessage(this, PInvoke.LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
if (itemCount <= 0)
{
return NoMatches; // No items in the list box
}
// Binary search for the item at the specified point
int low = 0;
int high = itemCount - 1;
while (low <= high)
{
int mid = low + (high - low) / 2;
// Get the rectangle of the item at index `mid`
RECT itemRect;
if (PInvokeCore.SendMessage(this, PInvoke.LB_GETITEMRECT, (IntPtr)mid, out itemRect) == IntPtr.Zero)
{
return NoMatches; // Failed to retrieve item rectangle
}
if (itemRect.top <= y && y < itemRect.bottom)
{
// Found the item containing the point
return mid;
}
else if (y < itemRect.top)
{
// Point is above this item
high = mid - 1;
}
else
{
// Point is below this item
low = mid + 1;
}
}
return NoMatches; // No matching item found
} |
If LB_GETCOUNT shows that the list box has so few items that no overflow is possible, then I think ListBox.IndexFromPoint can keep using LB_ITEMFROMPOINT as before. That strategy would minimise the compatibility risk. |
This is a limitation of the underlying native control - https://learn.microsoft.com/en-us/windows/win32/controls/lb-setcount |
According to the LB_SETCOUNT page, the 32767-item limit applies to "Windows 95/Windows 98/Windows Millennium Edition (Windows Me)". .NET doesn't even run on those operating systems any more so their problems should not prevent this from being fixed. |
I have submitted the same problem several days ago. It was taken into consideration and flushed here (as already submitted). And here, as I see, it is flushed by MS further into a drain. Regardless of it being an obvious and irritating bug left from jolly Int16 days. It is not a first case of me submitting something and MS disdaining me and disregarding the problem. Possibly, some day, when hell freezes... Meanwhile, I used a standalone vertical scrollbar to mask the false one, and used Topindex (which is Long) and adding 65536 several times to substitute for Indexfrompoint. |
.NET version
.NET 10
Did it work in .NET Framework?
No
Did it work in any of the earlier releases of .NET Core or .NET 5+?
No, this issue can repro on .NET 6.0
Issue description
According to documentation, List Box IndexFromPoint should be Int32 but in tested result is Int16 because the max value is 65535.
Current behavior
IndexFromPointIssue.mp4
Expected behavior
Steps to reproduce
More Info
This issue is from feedback ticket FeedbackTicket 2318021 Visual Studio 2022 Visual Basic Listbox bug
The text was updated successfully, but these errors were encountered: