Do you want to know what kind of bug I hate the absolute most? (I'm sure you do, because you're still reading this.) The side-effect bug with otherwise correct-looking code.
Let me set the stage so you can understand what I'm talking about.
There was a bug where the PropertiesListbox in the IDE was flashing when you would select a control. The way you would reproduce it was quite simple: 1) Open up a window editor with multiple controls in it. 2) Select a control. 3) Select another control. Repeat steps 2 and 3 rapidly and you'll notice that the listbox flickers. This is especially true if your IDE was sized such that you'd have an enabled scrollbar in the listbox after selecting each control.
The reason for this flicker was because of premature redrawing. What would happen is that we would remove all of the rows in the listbox (from the old control) and refill all of the rows with properties of the new control. This normally doesn't cause problems because we don't actually do any visual changes until we get a paint event (internal to the listbox) -- so you can remove all the rows and add thousands of rows. It'll all be shown as one operation instead of many (flickery) operations.
So the usual suspects boiled down to looking for calls to Refresh, or the dreaded App.DoEvents. Except there were no such calls! So then I did some visual code inspection to see if I could spot the issue. That was no avail. Finally, I had to use Remote Debugging to track down the issue.
The issue was narrowed down (eventually), to this:[rbcode]
DeleteAllRows
Redim mSubjects( -1 )
ScrollPosition = 0[/rbcode]
Did you spot the bug? It took me a long while, so don't feel bad.
Assigning to ScrollPosition forces the listbox to redraw itself because the user is saying "I want you to scroll here, right now!" In order to satisfy that command, we have to visually display where "right here" is, which is why the refresh. This in itself is not a bug. However, because we are deleting all of the rows of the listbox, this causes the listbox to be drawn empty (which would then disable the scrollbar in it). Then we go and add all the rows back to it, and eventually get around to drawing the listbox full. So what you end up with is a flickery mess.
It took me four hours to track down the bug with very legit-looking code. The fix was to set the scrollposition and the delete all of the rows -- the ultimate effect is the same, but the flickery mess is gone. This is the kind of bug I hate the most. When code looks fine, but due to side effects, it really isn't fine. And all you have to do to fix the bug is move some of the code around. Ug!
These little things are what make the beta IDE so much smoother. Even if it isn't consciously noticeable, the changes are definite improvements!
So let the bug-hunting continue. Good work. :-)
Yeah, I spotted the bug right away... of course you made it easy since I had a one in three chance to get it right. =)
Yep. I've run into that one myself. Always set the scroll position and then delete the rows. ;)
Hi Aaron,
I see where the problem is. IMHO there are 2 possible solutions:
1)first set the scrollposition before deleting all rows or
2)treat the scrollposition equal to the rownumber: nonexisting = -1, so if there are no rows, there isn't a scrollposition and set that to -1 and no redraw is necessary.
An equal problem is in the example below:
create a window with a listbox (height about 10 rows), a statictext below that and below that a pushbutton and enter this code:
Window1 Control ListBox1:
Sub Open() Handles Event
For i as integer = 1 to 20
me.AddRow Str(i)
Next
End Sub
Sub MouseMove(X As Integer, Y As Integer) Handles Event
StaticText1.Text = Str(me.RowFromXY(x,y))+" "+Str(x)+" "+Str(y)
End Sub
Window1 Control PushButton1:
Sub Action() Handles Event
ListBox1.ScrollPosition = 25
End Sub
If you run this and hoover the mouse over the vertical scrollbar you will see that the x- and y-values are changing while you are not above the listbox.
Now click on the button so the last rows of the listbox will be visible, after that resize the window twice as large as originally by pulling down the lower windowborder (don't use the right-low-corner) and then click in the upper part of the scrollbar to show the full contents of the listbox.
Now you can see that the place where the scrollbar was, there is a gray background that hasn't been redrawn (I have the desktop setting set to classic )
It feels to me that this is caused by the way RB implements the scrollbar, not as an independant element stearing a listbox, but as a kind of a property of the listbox OR that the controlorder of the scrollbar is behind the listbox while it's visibility is in front of the listbox. Both ways IMHO you can expect redraw-problems.
I would like to hear your opinion as an expert.
I don't think option #2 is truly an option. There's a concept of "no selected row" but there's not a clear concept of "no current scrollposition." Would that mean "don't do anything?" Or "Scroll to the top?" Or "Scroll to the bottom?" It's unclear.
As for the steps you provided, you should file them as a bug report.
> ... so don’t feel bad.
Quick writing rant. Don't bother to manage your audiences emotions. In social terms, never tell a person what to feel, and with extreme caution, how they feel.
Although unintended, it's an easy interpreted as condescension or worse. ...And man will it piss your significant other off! ;-)
@DeanG -- lol, ok ok, settle down. ;-)
@Andre -- btw, as for my opinion on the listbox design: I think the scrollbar is a part of the listbox, and so the behavior sounds correct with regards to MouseMove messages. It's no different than an EditField which sometimes has a scroller and sometimes doesn't. But I can also see cases where it as an independent control might make sense as well. So I'm on the fence, but leaning towards it being the correct design.
It's not the first time I've seen code order cause weird bugs
I've filed a couple of others as well
Hi Aaron,
I am in doubt, I agree with you that the behaviour should be the same in an editfield and in a listbox. But suppose you have an editfield filled with longer lines and more lines than visible so both scrolbars are showing. If you click on the vertical scrolbar, not replacing the visible part, where do you expect the cursor to show, hidden under the scrollbar or at the right side of the visible part?
Do you see my problem, so I am still in doubt, is it a bug or solely a visual glitch as part of an implementation decission?
For the rest it's such a small issue that I prefer RS puts its efforts in more important things.
Anyway thanks for your comments.