Is there a way to detect if a listbox’s vertical scrollbar is showing after being drawn?
I have two listboxes stacked vertically, the top most acting as column headers (so a single row), the lower holding results of a query as a data listbox. The data listbox could potentially have a vertical and horizontal scrollbar. I have both listbox’s horizontal scrollbars linked to scroll together. But if the data listbox has a vertical scrollbar, when scrolling horizontally, the column header listbox cumulative width is shorter than the data listbox’s cumulative width. So when scrolling to the far right in the data listbox, the column listbox’s last two columns aren’t visible and there’s a small white gap equivalent to the data listbox’s scrollbar width.
What I want to know if is there is a way to detect if the data listbox’s vertical scrollbar is showing, so I can add a buffer to calculate the header listbox’s scroll values?
I have code for this, I worked on it a while back, both horizontal and vertical detection, I even found a crash causing bug when developing it that will hopefully be fixed on the next release. I’m not at my computer for the rest of the day, I’ll post the code as soon as I get back.
I have done it before but it was awhile back and don’t have the code with me so don’t recall which way I did way I did it…
But this should work
Dim VScrollBarVisble as Boolean
If me.HasHeading then
VScrollBarVisble = me.ListCount > 0 AND me.ColumnFromXY(me.Width-4, me.HeaderHeight + 3) = -1
Else
VScrollBarVisble = me.ListCount > 0 AND me.ColumnFromXY(me.Width-4, 3) = -1
End if
I guess I did a workaround, which may be similar to what you’ve done. I was hoping for a quick check.
//Account for scrollbars
Dim theight As Integer = lbRH.ListCount * lbRH.RowHeight
If theight > lbRH.Height Then
lbCH.Width = lbCH.Width - 20
End
Dim twidth As Integer
For i As Integer = 0 To colwidths.Ubound
twidth = twidth + colwidths(i).Val
Next
If twidth > lbCH.Width Then
lbRH.Height = lbRH.Height - 20
End
It gets the job done, but a simple boolean built into a listbox would be helpful.
When I was writing my listbox subclass having booleans to see if either scrollbar was visible would have simplified things!
BTW if you are going to do it you should be dynamically getting the columns widths if you allow the user to either resize the columns or resize the listbox with the window.
@Karen Atkocius Thanks. I know I’m operating on specifics, so I know there are no headings (hence the additional listboxes), and the listboxes have equal borders. I’m also measuring the text in each header to draw the column width’s string, so I additionally can loop through that array to get the full width as well. I wasn’t familiar with the ColumnFromXY. Just for my understanding, you’re checking to make sure the mouse clicked inside of the listbox but not a cell?
[quote=332709:@Jason Fink]@Dave S I guess we had similar ideas.
@Karen Atkocius Thanks. I know I’m operating on specifics, so I know there are no headings (hence the additional listboxes), and the listboxes have equal borders. I’m also measuring the text in each header to draw the column width’s string, so I additionally can loop through that array to get the full width as well. I wasn’t familiar with the ColumnFromXY. Just for my understanding, you’re checking to make sure the mouse clicked inside of the listbox but not a cell?[/quote]
Does not have to be in a cell just in the content area where a Cell COULD be . For example this still works if you have one column with a width of 100 and the listbox has width of 200…
But I would recommend you subclass the listbox and do this generically as a calculated property… That way you never have to worry about the logic again for other projects!
And as Dave pointed out you should be using COLUMN(x).ActualWidth… The listbox has a lot of subtleties and that will help make sure you don’t trip over them in edge cases.
[quote=332708:@Karen Atkocius]When I was writing my listbox subclass having booleans to see if either scrollbar was visible would have simplified things!
BTW if you are going to do it you should be dynamically getting the columns widths if you allow the user to either resize the columns or resize the listbox with the window.[/quote]
I determine the column widths from preloaded text as an integer value (not percentage) and don’t allow them to be resized. While the window can be resized, I’m using Xojo’s IDE locks on the listbox elements to keep relative spacing from window edges to listboxes. With that, shouldn’t their attributes retain relativity to the window while the window is adjusted? The columns themselves don’t change in width, only the listbox itself, correct?
BTW FWIW it annoys the heck out of me that Listbox. HeaderHeight does NOT return 0 if there is no heading!
When that was first introduced I tripped over that a few times before I remembered I also have to check listbox.HasHeading… We REALLY should not have to do that!
I was going to go make a feedback request because I like that idea, Karen.
But then I saw they’ve been ignoring you for 8 years: <https://xojo.com/issue/7693>
[quote=332724:@Tim Parnell]I was going to go make a feedback request because I like that idea, Karen.
But then I saw they’ve been ignoring you for 8 years: <https://xojo.com/issue/7693>[/quote]
I forgot I did that… That was back when I was first writing my listbox subclass and trying to deal with all the possible permutations of listbox settings and content!
BTW Thanks Norm… that is one request I never got around to making after I solved it in my code… but maybe VerticalScrollbarWidth and HorizontalScrollbarHeight that return 0 when they are not present would be better… More future proof if UI’s change!
[quote=332705:@Karen Atkocius]But this should work
[/quote]
The previous code does not consider all cases. It assumes both that :
ScrollBarVertical Is true
And
AutoHideScrollbars = True
That means that code can produce a wrong result if AutoHideScrollBars is false and the listbox has no entries (the vertical ScrollBar will be visible in that case- may matter if you are doing something on CellBackgroundPaint)
So the code should read: (me refers to the listbox)
Dim VScrollBarVisble as Boolean
If me.ScrollBarVertical Then
If NOT me.AutohideScrollBars Then
VScrollBarVisble = True
ElseIf me.HasHeading Then
VScrollBarVisble = me.ListCount > 0 AND me.ColumnFromXY(me.Width-4, me.HeadingHeight + 3 ) = -1
Else
VScrollBarVisble = me.ListCount > 0 AND me.ColumnFromXY(me.Width-4, 3 ) = -1
End if
Else
VScrollBarVisble = False
End if
Or as a computed property on a listbox subclass:
[code]Public Property VerticalScrollBarVisibleNow as Boolean
Get
If ScrollBarVertical Then
If NOT AutohideScrollBars Then Return True
If HasHeading Then
Return ListCount > 0 AND ColumnFromXY(Width-4, HeadingHeight + 3 ) = -1
Else
Return ListCount > 0 AND ColumnFromXY(Width-4, 3 ) = -1
End if
End if