Baby Scroller 101 Help Please

T

Tom

My user defined vertical scroll bar does not respond properly. :(

public VScrollBar vs;
....
vs = new VScrollBar();
vs.Parent = this;
vs.Dock = DockStyle.Right;

I intercept the scrollbar events using the Visual Studio's very nice
automated event handler: >>

vs.Scroll += new ScrollEventHandler(vs_Scroll);

Then I programmatically calculate and set the desired new position for
the thumb in the LargeDecrement event: >>

public void vs_Scroll(object sender, ScrollEventArgs e)
{
if (e.Type == ScrollEventType.LargeDecrement)
{
vs.Value = iThumbLocation(); //The calculated result.
return;
}
}

The observed behavior is the thumb moves by the "LargeChange" amount
from the _original_ position. Upon losing focus, it then snaps to the
calculated value.

What is the smart solution here?

Do you somehow trap out the automated scrollbar behavior?

Or, should I be programmatically calculating and setting a new
"LargeChange" value to keep the "while still in focus scrollbar"
visually in sync with the calculated new position?

Unfortunately the false value also triggers another scroll event! What
a mess. It really had(has) me dumbfounded and the amount of time I've
spent writing out values to understand what was causing the visually
observed problem is good for a laugh. Please enlighten me! This is one
more learning adventure I'll very much enjoy having completed.

Thanks!!

-- Tom
 
P

Peter Duniho

[...]
Then I programmatically calculate and set the desired new position for
the thumb in the LargeDecrement event: >>

public void vs_Scroll(object sender, ScrollEventArgs e)
{
if (e.Type == ScrollEventType.LargeDecrement)
{
vs.Value = iThumbLocation(); //The calculated result.
return;
}
}

The observed behavior is the thumb moves by the "LargeChange" amount
from the _original_ position. Upon losing focus, it then snaps to the
calculated value.

What is the smart solution here?

I'm not sure I understand your use of the control.

Typically you would set the LargeChange value when creating the scroll bar
and/or when your document or view changes size, depending on how you want
the scrollbar to work.

Generally all you'd do in response to a scroll event is update the window
based on the new value for the scroll bar, which is set automatically
based on the scroll bar's current settings.

Why are you setting the scroll bar's value in the handler for the scroll
event?

Pete
 
T

Tom

I'm not sure I understand your use of the control.
Typically you would set the LargeChange value when creating the scroll bar
and/or when your document or view changes size, depending on how you want
the scrollbar to work.

Generally all you'd do in response to a scroll event is update the window
based on the new value for the scroll bar, which is set automatically
based on the scroll bar's current settings.

Why are you setting the scroll bar's value in the handler for the scroll
event?

Pete

Hi Pete --

You are always here! Amazing!! And your advice has always been equally
impressive!! :)

I am using the scrollbar to set the beginning point of a buffer for
reading/viewing only a portion of a very large file.

I've worked through a few basic examples of using scrollbars and
understand the basic usage of "LargeChange".

In my particular case ... the scrollbar control does not allow easy
and precise placement. On the largest files ... I set the LargeChange
to approximately 100 screen buffers and the SmallChange to 1/10'th the
LargeChange. PageDown & PageUp are used for single paging and the
up/down arrows are for line-by-line.

On typical tiny to small files ... the conventional usage of
LargeChange works easily. Its the control over the very large files
that is a bit challenging. I like where this project is heading ...
but I am ALWAYS receptive to better approaches.

When I open a large file in NotePad I often have to wait 2 minutes.
With this buffer program it's open and positioned in a blink ... and
without consuming memory as if a black hole fell through the roof and
landed on the desktop. :)

The behavior of the scrollbar when programmatically setting its
"Value" is certainly a bit bizarre for this newb. The complications of
having many other events also interacting made finding the problem
very challenging for me. Tons of console write statements and more
hours than I should admit too.

Once I get this little utility fully working ... my plans are to post
the source. For now the source is too messy with my debugging write
statements cluttering it up.

I hope the above sheds some light on my predicament and the peculiar
scrollbar behavior I am trying to work around.

-- Tom
 
P

Peter Duniho

You are always here! Amazing!!

You can generally tell how my other programming projects are going by how
often I find a need to distract myself with a newsgroup. :)
And your advice has always been equally impressive!! :)

Flattery will get you everywhere. Even if I am painfully aware that I've
made plenty of goofs myself. "Always"? How is that even possible? :)

Anyway...thanks for the kind words. But about your question...
[...]
In my particular case ... the scrollbar control does not allow easy
and precise placement. On the largest files ... I set the LargeChange
to approximately 100 screen buffers and the SmallChange to 1/10'th the
LargeChange. PageDown & PageUp are used for single paging and the
up/down arrows are for line-by-line.

Typically, you'd set SmallChange to 1, and LargeChange to the number of
"units" you can display at once. In the case of displaying lines of text,
the "unit" is a single line of text and LargeChange would be set to the
number of lines you can display in a window. (Other applications would
use the numbers differently...for example, an image display control might
define its "units" as pixels).

Then the maximum value would generally be set to the total number of
"units" (lines of text in a file, for example).

Large text files can be a bit problematic for a couple of reasons. One is
that you only have an int to use as the value for the scroll bar. Files
with more than 2 billion lines will exceed the values possible. Another
issue is that you'd need to parse the entire file in order to count the
lines (assuming it's a plain text file...some files might have a
line-count as part of their file format, which makes that part easier).

There are ways to work around these issues, but IMHO you'll be better off
getting the "under 2 billion lines" case to work first. Unfortunately,
that does mean a delay when you first open a file and have to figure out
how many lines are in it. Baby steps. :)
[...]
The behavior of the scrollbar when programmatically setting its
"Value" is certainly a bit bizarre for this newb.

But why are you setting the Value property? If you're trying to react to
user input that's done via the scrollbar, you should be reading the Value
property, not setting it. Depending on how you're displaying the text,
this might happen in the scrollbar event handler or it might not even
happen until some custom paint handler for the window is called. But in
either case, the Value property is set by the user's actions, not your own
code.
[...]
I hope the above sheds some light on my predicament and the peculiar
scrollbar behavior I am trying to work around.

I apologize if I'm missing something, but unfortunately, no. It doesn't
shed light on the question I asked. I still don't understand why you're
setting the Value property in your handler.

Pete
 
T

Tom

[...]
I apologize if I'm missing something, but unfortunately, no. It doesn't
shed light on the question I asked. I still don't understand why you're
setting the Value property in your handler.

Pete

Pete -- Have you ever seen the movie "Kill Bill" (Two Parts: 1 & 2)?
One of my favorite lines is >> "I must warn you ... I am very
susceptible to flattery." Awesome movie ... but now to my coding
challenge.

I set the vertical scrollbar(vs) "Maximum" to the file size in bytes.
^^ See! I do learn. The above is from some previously received help in
here!! :)) Before, I was even more scrollbar dumbfounded!

vs.Maximum = (int)myFile.Length;

When I drag and drop the thumb ... no problems at all. The vs.Value
works precisely and allows the buffer to be filled at that placement.

However, when I click for a LargeIncrement change ... the file is so
large that the thumb just sits there as the pages fly by. I am use to
being able to traverse the scrollbar rapidly by holding down on the
area above and below the thumb (instead of dragging the thumb). To
gain this type of behavior requires larger step sizes. And is
accompanied with "jumps" in the very large files. Non-contiguous
scrolling is not ideal ... but my goal is a minimal footprint viewer
that is fast. Minimal footprint defined as reasonably conservative
memory usage. On small files I programmatically set the LargeIncrement
to the conventional one page size. On the large files accurate control
requires using the PageDown & PageUp buttons for paging and the
Up/Down Arrows for moving the caret one line at a time. I intend to
implement CTRL-Home & CTRL-End too.

High performance for most folks is having the entire file in memory
and smoothly scrolling from begin to end with no flickering. In my
case ... high performance is loading speed and minimal usage of
memory. Tough compromises thus were required. Typical usage will be to
observe either the beginning or end of a log or data file while other
memory intensive and higher priority programs are running. An example
being a stock tick data file stored in bulky ASCII format. A data
vendor I use follows that format and there are some benefits in it
being easily read.

I have found a "hack" solution that produces less than perfect
results. >>

int tempValue = vs.Value;
.... perform buffer loading and new vs.Value calculation
vs.LargeChange = Math.Abs(tempValue - vs.Value);

The above is definitely a "hack". :((

The old "Value" is retained by the scrollbar while it has focus and it
reacts to the freshly calculated "LargeChange".

The thumb expands and contracts along its rapid traverse. The thumb
size changing is disconcerting ... but at least the travel time is
quick.

I've tried using 'Focus', 'Refresh', 'Invalidate' ... all to no avail
as yet.

I was hoping for some sort of C# solution that perhaps used the base
class somehow? I am clueless and speculating further about things
beyond my skill level are senseless. One thing for certain is the
focus that scrollbar retains even after the mouse is hovering
elsewhere. I have to click in the textbox to relinquish the scrollbar
focus.

Hopefully the above fills in some gaps on my challenge. If only there
was some way to disable the automated scrollbar behavior and be fully
in control!

Interestingly I saw a recent conversation about a 3 pane scrollbar
challenge another is up against. ;) (And I thought scrollbars issues
only concerned newbs!) I also noticed some commercial scrollbars at
outrageous prices for the fancy eyecandy stuff.

Thanks for listening and any suggestions thrown my way.

-- Tom
 
P

Peter Duniho

[...]
However, when I click for a LargeIncrement change ... the file is so
large that the thumb just sits there as the pages fly by. I am use to
being able to traverse the scrollbar rapidly by holding down on the
area above and below the thumb (instead of dragging the thumb). To
gain this type of behavior requires larger step sizes. And is
accompanied with "jumps" in the very large files. Non-contiguous
scrolling is not ideal ... but my goal is a minimal footprint viewer
that is fast. Minimal footprint defined as reasonably conservative
memory usage. On small files I programmatically set the LargeIncrement
to the conventional one page size. On the large files accurate control
requires using the PageDown & PageUp buttons for paging and the
Up/Down Arrows for moving the caret one line at a time. I intend to
implement CTRL-Home & CTRL-End too.

I agree that non-contiguous scrolling is not ideal, but if you're okay
with that design even so, let's consider that the design goal here.

In that case, large files are still handled the same as small files,
except that you set LargeChange differently. Basically, you should have
some code like this when you choose a new file for the viewer:

// calculate what the LargeChange value would be based on file size
int scrollLargeChange = cbFile / 100; // for example
int scrollViewChange = cbOnePage;

LargeChange = Math.Max(cbFile, cbOnePage);

The first value is how much you'd want to scroll for large files. In the
example, it means that 100 large-change scrolling actions will be required
to page through the whole file. Obviously this calculation is dependent
on the actual length of the file.

The second value is the nominal amount you'd page for smaller files,
corresponding to how much data you can fit on the screen at once. It's
completely independent of the actual length of the file, and relates only
to the display of the data.

Then, you want the large of the two values for your LargeChange property..
You always want to page at least one screen's worth of data, but if that's
less than 100th of the file, you want to page an even larger amount, equal
to 100th of the file.

At no point should you be setting the Value property of the scrollbar
directly, at least not with respect to this part of the code (obviously to
support your custom handling of the PageUp and PageDown buttons and any
other key-specific handling, you'll need to do so).

Pete
 
T

Tom

At no point should you be setting the Value property of the scrollbar
directly, at least not with respect to this part of the code (obviously to
support your custom handling of the PageUp and PageDown buttons and any
other key-specific handling, you'll need to do so).

Pete

Thanks Pete !!

I have already implemented a linear calculation (and considered
non-linear) with a lower limit very similar to your suggestion. The
trap I fell into was "the setting" of the scrollbar's Value!!

Implementing the PageUp, PageDown, and ThumbPosition events first
(where I needed to be "directly" involved with setting or using the
"Value") made me feel I should _always_ position the thumb for every
event. That is just the wrong approach for Large and Small Increments.
The light is on now!!

Golden Scroll Bar Rule #1:

When programmatically responding to Large or Small Increment events
that differ from the traditional One Page or One Line movement ...
simply adjust the viewing area however you need and let the
scrollbar's built in tracking methods work as they are designed.

Amazing how hours of writing trap code drew me in so tight my nose was
on the tree's bark and I could not see the forest. I just could not
force myself to think outside making adjustments to those two critical
parameters! Now if only I could quit saying "dumb dumb dumb" to
myself!!

Geez, I had begun to be obsessed with needing an "e.Handled" method
similar to keystroke trapping. I was also starting down the path of
wanting to intercept the Window Message traffic. A newb gets exposed
to more new things when traveling the endless wrong paths once sight
of the logical approach is lost.

Pete -- You recognized my problem and kindly got me pointed right.
Thank you again !!!

-- Tom (alias: tweedle dee tweedle dumb) LOL
 
P

Peter Duniho

[...]
Pete -- You recognized my problem and kindly got me pointed right.
Thank you again !!!

You're welcome. And I'll offer the "bigger picture" rule that your
"Golden Scroll Bar Rule #1" is a corallary of: if you find yourself
writing code that seems overly complicated and difficult to understand or
to get to work right, you're probably doing it wrong. Find another way.
:)

This comes up a lot. In this particular situation, it's relevant to the
use of framework class that's supposed to make your life easier. If using
the class makes your life hard, you're probably using it wrong. :)
Likewise even if it's all just your own code, if it seems like a design
you've come with is forcing you to write ever-more-complicated code to
work within that design, it's likely that the design itself is flawed and
should be reworked to make the implementation easier.

Simple programming is good programming. I see too many people way too
eager to just introduce hack after hack into their code, tweaking it until
they get it "just right", when what they really should have done is
re-frame the problem so that implementing the solution is easier and
hack-free.

Now and then, there's just no choice. Complication is the order of the
day. But most of the time, if it seems too hard, it's because it is
literally too hard. Do it easy instead and you'll be much happier (and
the code will be better too). :)

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top