Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / November 2006

Tip: Looking for answers? Try searching our database.

Scrolling text that doesn't flicker

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
pigeonrandle - 12 Nov 2006 22:03 GMT
Hi,
I have seen loads of different ways to do this, but the all seem to
yield the same result - text that doesn't flicker when it's moving too
slowly!
Does anyone know 'the best way' to make text scroll...

eg
Override OnPain and OnPaintBackground

Override WndProc

Use GDI

Use API

Or do i need to create some weird control in c++?!

Thanks in advance,
James
Peter Duniho - 13 Nov 2006 00:08 GMT
> Hi,
> I have seen loads of different ways to do this, but the all seem to
> yield the same result - text that doesn't flicker when it's moving too
> slowly!

"Flicker" is generally caused by a single problem, regardless of what you're
drawing: erasing the previous image on-screen before drawing the new image.

Typically, this is addressed using an off-screen buffer to actually draw the
image, which is then copied directly to the screen without erasing whatever
was there previously.  The reason you need to erase in the first place is to
get rid of whatever was there previously, but if you are always copying a
whole new bitmap (or portion of a bitmap) on top of every part of the
display that needs changing, then no erasing is necessary, and no flicker
occurs.

In .NET, I've been told one can enable "double-buffering" to address this.
The term "double-buffering" isn't correct, IMHO (it more correctly refers to
a related but different idea in which the entire screen buffer is switched
back and forth), but knowing that that's the phrase some .NET people use may
help you find the technique in the .NET documentation.  I haven't used it
myself, so I can't tell you the specifics.

Pete
Dave Sexton - 13 Nov 2006 00:40 GMT
Hi James,

As Peter suggested, double buffering is an option to reduce flickering (the
only one I'm aware of as well).  In the constructor of a class that derives
from Control (including the Form class) you can use the following code to
enable double buffering for that control (1.* applications):

this.SetStyle(ControlStyles.DoubleBuffer
| ControlStyles.AllPaintingInWmPaint
| ControlStyles.UserPaint, true);

In 2.0 apps, just set the Control.DoubleBuffered property to true (it uses the
new ControlStyles.OptimizedDoubleBuffer flag internally).

Signature

Dave Sexton

> Hi,
> I have seen loads of different ways to do this, but the all seem to
[quoted text clipped - 15 lines]
> Thanks in advance,
> James
Michael C - 13 Nov 2006 04:28 GMT
> Hi James,
>
> As Peter suggested, double buffering is an option to reduce flickering
> (the only one I'm aware of as well).

The other option is to just draw everything once. If you are doing something
like a chessboard this is easy, just draw each square onto the screen. If
the chessboard has pieces you could use regions to draw the pieces and then
draw the square around them. Unfortunately for text I don't think this is
possible. You have to use double buffering because it's not possible to draw
text with a background and it is not possible to find the region surrounding
this text. This also applies to many of the features of GDI+ such as
anti-aliasing and transparencies, it's no longer possible to draw in one go
so double buffering is almost mandatory these days.

Michael
Dave Sexton - 13 Nov 2006 04:45 GMT
Hi Michael,

But for scrolling text you can't draw everything only once.  It's scrolling!

BTW, you can draw text with a background color in the 2.0 framework using the
TextRenderer class, which I believe uses GDI, not GDI+.

Signature

Dave Sexton

>> Hi James,
>>
[quoted text clipped - 12 lines]
>
> Michael
Michael C - 13 Nov 2006 04:58 GMT
> Hi Michael,
>
> But for scrolling text you can't draw everything only once.  It's
> scrolling!

Yes, you can (assuming you can draw the background with the text as you
described). There will be x frames per second, for each frame if you draw
each pixel on the surface only once then you don't need double buffering.

> BTW, you can draw text with a background color in the 2.0 framework using
> the TextRenderer class, which I believe uses GDI, not GDI+.

If that's the case then it would be possible to use the API directly in 1.1,
although I don't recall there being an API that would let you draw text with
a background.

Michael
Dave Sexton - 13 Nov 2006 05:06 GMT
Hi Michael,

>> But for scrolling text you can't draw everything only once.  It's
>> scrolling!
>
> Yes, you can (assuming you can draw the background with the text as you
> described). There will be x frames per second, for each frame if you draw
> each pixel on the surface only once then you don't need double buffering.

I really don't understand what you mean.  How would that prevent Windows from
clearing the render target before the next operation?

I always thought double-buffering worked like the swap chain in DirectX, where
the back buffer is simply presented instead of the target being cleared.
Without the buffer, I assumed Windows will clear the target automatically for
each WM_PAINT message, causing a flicker.

Care to explain in more detail?

>> BTW, you can draw text with a background color in the 2.0 framework using
>> the TextRenderer class, which I believe uses GDI, not GDI+.
>
> If that's the case then it would be possible to use the API directly in 1.1,
> although I don't recall there being an API that would let you draw text with
> a background.

Yea, I'm not sure how they do it but it's there and it works (and it's GDI
according to the MSDN docs :)

Signature

Dave Sexton

Peter Duniho - 13 Nov 2006 05:28 GMT
>>> But for scrolling text you can't draw everything only once.  It's
>>> scrolling!
[quoted text clipped - 5 lines]
> I really don't understand what you mean.  How would that prevent Windows
> from clearing the render target before the next operation?

He's saying that, if you had a way to ensure that each pixel on the screen
that has changed is drawn only once, setting it to the exact desired new
value, you can, once per frame, draw everything only once.

Obviously something animated has to be drawn multiple times.  But the
flicker doesn't result from that.  It results from drawing things multiple
times *per frame*.  That's what he means to avoid.

In theory, it's even possible to do so (see my other post, about using
regions to mask the text area while filling the remaining background).  In
reality, that's a) a much more complicated solution than using an off-screen
buffer, and b) may not even perform as well (since it would rely on using
regions to mask the text area while the background is being drawn).

> I always thought double-buffering worked like the swap chain in DirectX,
> where the back buffer is simply presented instead of the target being
> cleared. Without the buffer, I assumed Windows will clear the target
> automatically for each WM_PAINT message, causing a flicker.
>
> Care to explain in more detail?

This is why I dislike the use of the term "double buffering" to describe
this.  It's similar to, but not exactly the same as, the existing
double-buffering (or even triple-buffering, as is sometimes the case) used
in DirectDraw.  In DirectDraw, double-buffering means there are two entire
frame buffers.  One is always being used by the video card's RAMDAC to
display an image on the monitor, and the other is the one being drawn to at
that given moment.  Once drawing has been completed, the entire active frame
buffer is switched (flipped), and the process starts anew.

This is kind of what the .NET "double buffering" is doing, except that it's
not a low-level hardware thing.  There's an alternate, off-screen buffer and
rather than flipping the actively displayed buffer, the off-screen buffer is
simply copied to the active on-screen buffer.  I don't like using the same
term for both, because it confuses the issue.

By doing this, any pixel that changes on the screen is drawn exactly once
for a given change (frame).  Which is what needs to happen to avoid flicker.
And it certainly can happen that way, even as the text is scrolling.  The
requirement is that the drawing happens once for each change, not that it
only happen once period.

Pete
Dave Sexton - 13 Nov 2006 05:39 GMT
Hi Peter,

Great explanation, thanks.

(You're not going to start billing me, right? ;)

Signature

Dave Sexton

>>>> But for scrolling text you can't draw everything only once.  It's
>>>> scrolling!
[quoted text clipped - 49 lines]
>
> Pete
Peter Duniho - 13 Nov 2006 05:50 GMT
> Hi Peter,
>
> Great explanation, thanks.

You're welcome, of course.

> (You're not going to start billing me, right? ;)

No way...if I started charging for this kind of stuff, I'd have to work a
lot harder to make sure I knew what I was writing about.  :)

Pete
Dave Sexton - 13 Nov 2006 06:10 GMT
Hi Peter,

Work a lot harder?

I'm not sure why you're even working at all.  You could be completely making
stuff up on some of these topics and I wouldn't be the wiser.

And you'd still get the credit ;)

Signature

Dave Sexton

>> Hi Peter,
>>
[quoted text clipped - 8 lines]
>
> Pete
Peter Duniho - 13 Nov 2006 18:05 GMT
> Hi Peter,
>
[quoted text clipped - 4 lines]
>
> And you'd still get the credit ;)

Now you're catching on...  :)
Michael C - 13 Nov 2006 05:07 GMT
> But for scrolling text you can't draw everything only once.  It's
> scrolling!

The other thing you can do with scrolling text is use the ScrollWindow API
to move the contents of the window towards the left and then fill in the
invalid areas.

Michael
Peter Duniho - 13 Nov 2006 05:27 GMT
> The other thing you can do with scrolling text is use the ScrollWindow API
> to move the contents of the window towards the left and then fill in the
> invalid areas.

But those invalidated areas are cleared by the scrolling (or need to be
cleared when you fill them in), so that portion will still flicker.
Michael C - 13 Nov 2006 07:31 GMT
> But those invalidated areas are cleared by the scrolling (or need to be
> cleared when you fill them in), so that portion will still flicker.

That's true, I guess all the same issues of double buffering or drawing with
a background would apply to those areas. This could still be useful as it
really speeds up scrolling, although could also complicate the issue.
Peter Duniho - 13 Nov 2006 18:08 GMT
>> But those invalidated areas are cleared by the scrolling (or need to be
>> cleared when you fill them in), so that portion will still flicker.
[quoted text clipped - 3 lines]
> as it really speeds up scrolling, although could also complicate the
> issue.

It does speed up scrolling quite a lot (especially on large areas), and IMHO
is the appropriate method any time you simply need to scroll something on
the screen.  I was just pointing out that it doesn't avoid other aspects of
the problem.

That said, because the flickering region is so small when using that
technique, the flicker is MUCH less noticable.  In some cases, it might be
an appropriate solution...not because it eliminates flicker altogether, but
just because the user can barely notice what flicker does exist.

It really just depends on the particular situation.  Funny how that keeps
coming up in these programming topics.  :)

Pete
Peter Duniho - 13 Nov 2006 05:14 GMT
> Hi Michael,
>
> But for scrolling text you can't draw everything only once.  It's
> scrolling!

As Michael notes, in theory as long as you ensure that every pixel that
needs to change is drawn, you can avoid the flickering.

However...it's MUCH harder to accomplish this, and in some cases may be
impossible of course.  Even with the original GDI, while it might have been
theoretically possible to draw the text, and fill the region outside the
text with the background color, that would have been such an expensive
drawing operation, no one sensible person would have done it that way.

The most common solution would have been to simply maintain a bitmap the
same size as the on-screen window, drawing into that and then blting the
results to the screen.  Another solution would be to use smaller bitmaps,
the size of whatever it is you want to draw, blt those as they are drawn to
the appropriate spot on the screen.  Of course, as was noted in Michael's
earlier post, if the kinds of things that are being drawn lend themselves to
simply copy an entire image to fill a specific area on the screen, then that
works too.

The key in all solutions is to avoid first clearing an area on the screen
and then drawing something else on top of that.

> BTW, you can draw text with a background color in the 2.0 framework using
> the TextRenderer class, which I believe uses GDI, not GDI+.

It's been awhile, but my recollection is that this doesn't make a
difference.  That is, when drawing text with a background color (using the
opaque style), GDI would first fill in the background and then draw the
text, all directly to the destination DC.  It didn't avoid flickering...it
just was more convenient than calling FillRect directly yourself (and also
had the advantage that you didn't have to measure the text first, since the
TextOut function handled the whole thing for you).

Even if using "double buffering" (sorry, I still hate that term as applied
here) could be avoided and dealing with updating screen graphics could be
solved some other way, IMHO there's not really any great reason to do so.
Using an off-screen bitmap, as in "double buffering", is a reasonably
elegant way to address a variety of complications that come up with any sort
of animated or changing display, and with the amount of RAM available on
most systems these days, doesn't incur much of a penalty.

Pete
Dave Sexton - 13 Nov 2006 05:46 GMT
Hi Peter,

Thank you.

So is there some double-buffer implementation in WPF that uses the hardware?

(I heard that WPF uses DirectX)

Signature

Dave Sexton

>> Hi Michael,
>>
[quoted text clipped - 42 lines]
>
> Pete

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.