Nasty flickering by OnPaint Graphics.Invalidate

M

Mark Johnson

Using: VS 2003 NET C# for Framework and Framework Compact
Trying : Moving a Card (Bitmap) as in Solitare (PC + WinCe) Version on
OnMouseMove
Problem : The affected drawing Area by Invalidate (or Invalidate(Rectangle))
flickers in a nasty way when repainting.

This does not happen in the Solitare (PC + WinCe) Versions a well as in a
Card game where I have the C++ Source.

The use of an empty OnPaintBackground brings no visable results.

The OnPaint calls a Method, which builds a new Bitmap with a local Graphics.
When finished OnPaint does one DrawImage Command (flicker).

OnPaint is painting to a Panel.

Is this a Framework problem ?

Can a flicker free Painting only be done with some sort of Win-API.
- Goal is for this Class to run with the same code on both Systems.

If yes, what would it look like inside a Framework program ?

This seems to the last major problem (as of yet) that I have in realising a
game programm
and it would be very nice if this problem could be solved.

Thank you for any help

Mark Johnson, Berlin Germany
(e-mail address removed)
 
C

Chris Tacke, eMVP

I'd have to see your code, but I've done quite a bit of flicker-free drawing
with the CF.
 
1

100

If it is for the full framework (not CF) you can set panel control style to
do double buffering which will remove the flickering. CF doesn't support
control styles, though.

B\rgds
100
 
M

Mark Johnson

public virtual void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
p_Graphics = e.Graphics;
OnPanel(0); // This calls OnCreateWorkScreenBitmap()

p_Graphics.DrawImage(bmp_Work[i_Work_Screen],0,0);
}
public void OnCreateWorkScreenBitmap()
{ // First create our Bitmap and the Graphic to Draw
bmp_Work[i_Work_Empty] = new
Bitmap(bmp_Work[i_Work_Back].Size.Width,bmp_Work[i_Work_Back].Size.Height);
Graphics gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Empty]);
gs_Graphics.Clear(cl_Work);
gs_Graphics.Dispose();
if (bmp_Work[i_Work_Screen]!=null)
bmp_Work[i_Work_Screen].Dispose();
bmp_Work[i_Work_Screen] = new
Bitmap((i_Screen_Width_Diff+i_Screen_Width_Real),

(i_Screen_Height_Diff+i_Screen_Height_Real));
gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Screen]);
gs_Graphics.Clear(cl_Work);

// a lot of code chosing which Bitmap at what position should be painted
into the Image with the local Graphics, then

// This Paints Work Bitmap at the desired Position
#if !COMPACT
gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work);
#else
// For Compact the Bitmap cannot be resised
Rectangle srcRect = new
Rectangle(0,0,rt_Work.Width,rt_Work.Height+10);

gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work,srcRect,GraphicsUnit.Pi
xel);
#endif
gs_Graphics.Dispose();
} // public void OnCreateWorkScreenBitmap()

I can send you the full code if you give a e-mail adress.

Mark Johnson, Berlin Germnay
(e-mail address removed)
 
1

100

Hi Mark,
I'm might be able to help you. You can send me the code at
(e-mail address removed).
remove nospam stuff from the address.

B\rgds
100
 
C

Chris Tacke, eMVP

Offhand I don't see anything glaring, though you are createing a graphics
object a lot, and I tend to create and use one and only one for all my work.
I have a pretty complex control (a dial-indicator gauge) that essentailly
uses triple-buffering by generating a static image for the areas that don't
change, then drawing it and the changing stuff to another image, which I
then blit to the screen. I've run several instances on a 640x480 display
without any flicker at all.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Mark Johnson said:
public virtual void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
p_Graphics = e.Graphics;
OnPanel(0); // This calls OnCreateWorkScreenBitmap()

p_Graphics.DrawImage(bmp_Work[i_Work_Screen],0,0);
}
public void OnCreateWorkScreenBitmap()
{ // First create our Bitmap and the Graphic to Draw
bmp_Work[i_Work_Empty] = new
Bitmap(bmp_Work[i_Work_Back].Size.Width,bmp_Work[i_Work_Back].Size.Height);
Graphics gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Empty]);
gs_Graphics.Clear(cl_Work);
gs_Graphics.Dispose();
if (bmp_Work[i_Work_Screen]!=null)
bmp_Work[i_Work_Screen].Dispose();
bmp_Work[i_Work_Screen] = new
Bitmap((i_Screen_Width_Diff+i_Screen_Width_Real),

(i_Screen_Height_Diff+i_Screen_Height_Real));
gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Screen]);
gs_Graphics.Clear(cl_Work);

// a lot of code chosing which Bitmap at what position should be painted
into the Image with the local Graphics, then

// This Paints Work Bitmap at the desired Position
#if !COMPACT
gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work);
#else
// For Compact the Bitmap cannot be resised
Rectangle srcRect = new
Rectangle(0,0,rt_Work.Width,rt_Work.Height+10);

gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work,srcRect,GraphicsUnit.Pi
xel);
#endif
gs_Graphics.Dispose();
} // public void OnCreateWorkScreenBitmap()

I can send you the full code if you give a e-mail adress.

Mark Johnson, Berlin Germnay
(e-mail address removed)



Chris Tacke said:
I'd have to see your code, but I've done quite a bit of flicker-free drawing
with the CF.
in
a realising
 
M

Mark Johnson

I tried the following:
a counter was added so that the Bitmap Methode is only call once:

public override void OnPanel(int i_Event)
{
i_Test++;
base.OnPanel(i_Event);
if (i_New_Game == 1)
Setup_Basic_Logic();
if (i_Test == 1)
OnCreateWorkScreenBitmap();
if (sbStatusBarMainFrame != null)
sbStatusBarMainFrame.Text = "TryGame_Cards.OnPanel("+i_Test+")";
}

This means the Bitmap is only being repainted without being build again.

It still flickers.

I then turned off the OnMouseMove/Up/Down Events and took out the counter.
(i.e. OnPaint runs when resizing)

no flicker !

Only the when the events are turned on where the Invalidate() is done does
it flicker (for the Card only a flicker on the Card being moved).

Mark Johnson, Berlin Germany
(e-mail address removed)



Chris Tacke said:
Offhand I don't see anything glaring, though you are createing a graphics
object a lot, and I tend to create and use one and only one for all my work.
I have a pretty complex control (a dial-indicator gauge) that essentailly
uses triple-buffering by generating a static image for the areas that don't
change, then drawing it and the changing stuff to another image, which I
then blit to the screen. I've run several instances on a 640x480 display
without any flicker at all.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Mark Johnson said:
public virtual void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
p_Graphics = e.Graphics;
OnPanel(0); // This calls OnCreateWorkScreenBitmap()

p_Graphics.DrawImage(bmp_Work[i_Work_Screen],0,0);
}
public void OnCreateWorkScreenBitmap()
{ // First create our Bitmap and the Graphic to Draw
bmp_Work[i_Work_Empty] = new
Bitmap(bmp_Work[i_Work_Back].Size.Width,bmp_Work[i_Work_Back].Size.Height);
Graphics gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Empty]);
gs_Graphics.Clear(cl_Work);
gs_Graphics.Dispose();
if (bmp_Work[i_Work_Screen]!=null)
bmp_Work[i_Work_Screen].Dispose();
bmp_Work[i_Work_Screen] = new
Bitmap((i_Screen_Width_Diff+i_Screen_Width_Real),

(i_Screen_Height_Diff+i_Screen_Height_Real));
gs_Graphics = Graphics.FromImage(bmp_Work[i_Work_Screen]);
gs_Graphics.Clear(cl_Work);

// a lot of code chosing which Bitmap at what position should be painted
into the Image with the local Graphics, then

// This Paints Work Bitmap at the desired Position
#if !COMPACT
gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work);
#else
// For Compact the Bitmap cannot be resised
Rectangle srcRect = new
Rectangle(0,0,rt_Work.Width,rt_Work.Height+10);
gs_Graphics.DrawImage(bmp_Work[i_Work_Paint],rt_Work,srcRect,GraphicsUnit.Pi
xel);
#endif
gs_Graphics.Dispose();
} // public void OnCreateWorkScreenBitmap()

I can send you the full code if you give a e-mail adress.

Mark Johnson, Berlin Germnay
(e-mail address removed)



in
 
A

Alex Yakhnin [MVP]

Mark,

Did you override OnPaintBackground with no code in it?

-Alex

-----Original Message-----
public virtual void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
p_Graphics = e.Graphics;
OnPanel(0); // This calls OnCreateWorkScreenBitmap()

p_Graphics.DrawImage(bmp_Work[i_Work_Screen],0,0);
}
public void OnCreateWorkScreenBitmap()
{ // First create our Bitmap and the Graphic to Draw
bmp_Work[i_Work_Empty] = new
Bitmap(bmp_Work[i_Work_Back].Size.Width,bmp_Work [i_Work_Back].Size.Height);
Graphics gs_Graphics = Graphics.FromImage(bmp_Work [i_Work_Empty]);
gs_Graphics.Clear(cl_Work);
gs_Graphics.Dispose();
if (bmp_Work[i_Work_Screen]!=null)
bmp_Work[i_Work_Screen].Dispose();
bmp_Work[i_Work_Screen] = new
Bitmap((i_Screen_Width_Diff+i_Screen_Width_Real),

(i_Screen_Height_Diff+i_Screen_Height_Real));
gs_Graphics = Graphics.FromImage(bmp_Work [i_Work_Screen]);
gs_Graphics.Clear(cl_Work);

// a lot of code chosing which Bitmap at what position should be painted
into the Image with the local Graphics, then

// This Paints Work Bitmap at the desired Position
#if !COMPACT
gs_Graphics.DrawImage(bmp_Work [i_Work_Paint],rt_Work);
#else
// For Compact the Bitmap cannot be resised
Rectangle srcRect = new
Rectangle(0,0,rt_Work.Width,rt_Work.Height+10);

gs_Graphics.DrawImage(bmp_Work [i_Work_Paint],rt_Work,srcRect,GraphicsUnit.Pi
xel);
#endif
gs_Graphics.Dispose();
} // public void OnCreateWorkScreenBitmap()

I can send you the full code if you give a e-mail adress.

Mark Johnson, Berlin Germnay
(e-mail address removed)



I'd have to see your code, but I've done quite a bit of
flicker-free
drawing
with the CF.
Versions a well as in
a
with a local
Graphics.
I have in
realising


.
 
M

Mark Johnson

Since the Invalidate seems to cause the flicker, I tried to call DrawImage
on the saved Grafics from OnPaint.
This failed (crash).
I have howver taken an IntPtr from this Grafics and used it to withe the
Cards.dll Function which take
the IntPtr to draw directly to the Panel.

How then could I use this IntPrt (Hdc to Grafics) to draw a Bitmap to the
Panel as Cards.dll does ?
Maybe this, maybe, would not flicker.

Mark Johnson, Berlin Germany
(e-mail address removed)
 
M

Mark Johnson

Yes.

Mark Johnson, Berlin Germany
(e-mail address removed)


Alex Yakhnin said:
Mark,

Did you override OnPaintBackground with no code in it?

-Alex

-----Original Message-----
public virtual void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
p_Graphics = e.Graphics;
OnPanel(0); // This calls OnCreateWorkScreenBitmap()

p_Graphics.DrawImage(bmp_Work[i_Work_Screen],0,0);
}
public void OnCreateWorkScreenBitmap()
{ // First create our Bitmap and the Graphic to Draw
bmp_Work[i_Work_Empty] = new
Bitmap(bmp_Work[i_Work_Back].Size.Width,bmp_Work [i_Work_Back].Size.Height);
Graphics gs_Graphics = Graphics.FromImage(bmp_Work [i_Work_Empty]);
gs_Graphics.Clear(cl_Work);
gs_Graphics.Dispose();
if (bmp_Work[i_Work_Screen]!=null)
bmp_Work[i_Work_Screen].Dispose();
bmp_Work[i_Work_Screen] = new
Bitmap((i_Screen_Width_Diff+i_Screen_Width_Real),

(i_Screen_Height_Diff+i_Screen_Height_Real));
gs_Graphics = Graphics.FromImage(bmp_Work [i_Work_Screen]);
gs_Graphics.Clear(cl_Work);

// a lot of code chosing which Bitmap at what position should be painted
into the Image with the local Graphics, then

// This Paints Work Bitmap at the desired Position
#if !COMPACT
gs_Graphics.DrawImage(bmp_Work [i_Work_Paint],rt_Work);
#else
// For Compact the Bitmap cannot be resised
Rectangle srcRect = new
Rectangle(0,0,rt_Work.Width,rt_Work.Height+10);

gs_Graphics.DrawImage(bmp_Work [i_Work_Paint],rt_Work,srcRect,GraphicsUnit.Pi
xel);
#endif
gs_Graphics.Dispose();
} // public void OnCreateWorkScreenBitmap()

I can send you the full code if you give a e-mail adress.

Mark Johnson, Berlin Germnay
(e-mail address removed)



I'd have to see your code, but I've done quite a bit of
flicker-free
drawing
with the CF.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


online.net...
Using: VS 2003 NET C# for Framework and Framework Compact
Trying : Moving a Card (Bitmap) as in Solitare (PC + WinCe) Version on
OnMouseMove
Problem : The affected drawing Area by Invalidate (or
Invalidate(Rectangle))
flickers in a nasty way when repainting.

This does not happen in the Solitare (PC + WinCe)
Versions a well as in
a
Card game where I have the C++ Source.

The use of an empty OnPaintBackground brings no visable results.

The OnPaint calls a Method, which builds a new Bitmap with a local
Graphics.
When finished OnPaint does one DrawImage Command (flicker).

OnPaint is painting to a Panel.

Is this a Framework problem ?

Can a flicker free Painting only be done with some sort of Win-API.
- Goal is for this Class to run with the same code on both Systems.

If yes, what would it look like inside a Framework program ?

This seems to the last major problem (as of yet) that
I have in
realising
a
game programm
and it would be very nice if this problem could be solved.

Thank you for any help

Mark Johnson, Berlin Germany
(e-mail address removed)


.
 
B

BMermuys

Hi,

2 things you could try:
- call update after calling invalidate (force synchronous repainting)

- draw direct in the mouse move event, you can get a valid graphics object
by calling
CreateGraphics, then draw, and don't forget to Dispose() it when done
drawing

HTH
greetings
 

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