Re: TextOut prints a little late?
- From: "Joe Butler" <ffffh.no.spam@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 26 Sep 2007 17:57:14 +0100
there are 2 messages that are sent to your application whenever it needs to
repaint its display. The first is WM_ERASEBKGND. This gives your app a
chance to put the correct 'background' in place - normally it's just solid
white or it might be yellow if it were a tooltip, for example. Next it
sends you the WM_PAINT where you are supposed to then put your content
down - and you can assume that the background is clean at this point. Now,
due to the erasing and then painting, you'll get flicker - sometimes if it's
only a small area that's being erased and redrawn, and the data doesn't
change frequently, you'll not notice the flicker. For me, zero-flicker is a
personal mandatory requirement.
You can see flicker, btw, on the Networking tab on the Windows Task Manger
when you resize the task manager. Compare that to the type of flicker you
see on the Performance tab when resizing. It's no so ugly, but there's
still some perceptable flicker. Now look at the Processes tab, and you'll
see there is no flicker apparent.
The reason the Networking tab looks so bad when resizing is that each time
the window is resized, the background is being erased to blank (probably by
using InvalidateRect() with a TRUE for the erase background parameter and
then the new image is being drawn in. So, you get a rapid
grey/green/grey/green sequence.
The Performance tab is drawing over the old performance image without
erasing the current image first - InvalidateRect() with a FALSE for erase
background (i.e. it tells windows not to send a WM_ERRASEBKGND message). I
guess it's drawing each graticle line and then then the final graph directly
onto the display surface, which is why there is some low-level flickering
apparent.
Lastly, the Processes tab is probably drawing all teh info on an off-screen
dc and then blitting the data directly to the screen during wm_paint and
again, ignoring the wm_erasebackground. When the highlighed process
flickers for each update, it's only repainting that area and not touching
the rest of teh data.
The actual methods described my not be what task manager uses, but the
visual result would be the same.
Drawing a line (with a 1-pixel-wide pen) is a fast process. There are
algorithms optimised to draw the line from point A to point B. Ask for the
same to be done with a 2-pixel or more wide pen and things will get terribly
slow. Drawing text is also quite intensive, especially if it is drawn in
transparent mode and is anti-aliased or smoothed. I don't know how long it
takes to draw x number of characters compared to, say a diagonal line of n
pixels in length. Some things are just slower than others.
You call InvalidateRect(), not to clean up, but to mark and area as needing
to be re-displayed - because you changed the data that is displayed in that
area - not that you drew something there or output some text there, just
that you know the data that is currently displayed there is now out of date,
and until you do something to change what's shown there, it will show the
old data. Some areas will be invalidated without your saying so because the
user has moved a winodow off of your window and now the exposed area needs
to be redrawn, because no one has got a copy of it anywhere.
What you can try is to call InvalidateRect() with a the erase background
parameter as true and then you may see when your window is being erased due
to the flickering.
"deostroll" <deostroll@xxxxxxxxx> wrote in message
news:1190821459.059286.96060@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
On Sep 26, 7:50 pm, "Joe Butler" <ffffh.no.s...@hotmail-spammers-
paradise.com> wrote:
You use InvalidateRect() to tell windows that the rectangular area you
specified is 'dirty' and needs to be re-drawn. When windows is not busy
doing more important things, it'll get around to telling your app, via a
WM_PAINT message that you need to repaint your window's client area.
The idea is that when you app needs to output new information on the
screen,
you can calculate where that information is displayed (which may only be
a
very small area in your entire application) and mark the area as needing
to
be re-drawn by using InvalidateRect().
Then, in your paint handler, you can get the dirty area from from the
paint
structure and update that area only, which will reduce flicker and
generally
be more efficient than repainting the entire application each time some
small thing changes.
Why do you need to create a delay between making 2 TextOut() calls? Are
you
outputing these direct to the screen? Do you simply need to wait for new
information before the second TextOut() call can be made?
"deostroll" <deostr...@xxxxxxxxx> wrote in message
news:1190814036.173510.74060@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
On Sep 26, 9:15 am, "Joe Butler" <ffffh.no.s...@hotmail-spammers-
paradise.com> wrote:
Presumably it's the GDI batching?
Try with GdiSetBatchLimit(1)
or try: GdiFlush() immediatly after your first TextOut() call.
The batching should make drawing faster overall, so, you'd only want
to
do
this for special occations. On my XP, it seems that 20 is the default
batching limit and it cannot be raised above this amount. Not sure if
that's specific to my graphics card/hardware, or an XP fixed limit.
"deostroll" <deostr...@xxxxxxxxx> wrote in message
news:1190772470.352419.149250@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Inside a function I have a Sleep() in between 2 TextOut() calls.
When
I call the 1st one I expect it to print immediately before Sleep()
is
executed; but instead I get the output of both calls at the same
time
after the Slee() and after the funtion has exited...!
Why does this happen?
What is the proper way to print immediately?
--deostroll
I've used InvalidateRect() with the last parameter FALSE. That seems
to work. Is this actually recommended? I just don't seem to understand
what InvalidateRect() does...where do you normally use it?
--deostroll
I am just learning through experimenting. When I draw lines using
Polyline() it draws quickly. Where as TextOut() did not work as
quickly as expected. Therefore I was wondering why this is so?
Ok. If the sole pupose of InvalidateRect() is to clean up why do we
have to pass a FALSE as the last parameter - to say not to clean up?
If that was my objective I would simple not call InvalidateRect() !.
--deostroll
.
- References:
- TextOut prints a little late?
- From: deostroll
- Re: TextOut prints a little late?
- From: Joe Butler
- Re: TextOut prints a little late?
- From: deostroll
- Re: TextOut prints a little late?
- From: Joe Butler
- Re: TextOut prints a little late?
- From: deostroll
- TextOut prints a little late?
- Prev by Date: Re: TextOut prints a little late?
- Next by Date: Re: Drawing parallel lines?
- Previous by thread: Re: TextOut prints a little late?
- Next by thread: gdiplus causes memory error in windows 2000 redistribute
- Index(es):
Relevant Pages
|