?
Solved

Flicker drawing with GDI+

Posted on 2005-05-10
12
Medium Priority
?
646 Views
Last Modified: 2012-05-05
I wrote a scrolling text marquee that renders text into a memory buffer (a System.Drawing.Bitmap) and uses a timer to update the scrolling text by rendering the buffer with Graphics.DrawImage.

I have tried everything and no matter what I always get flickers.

I enabled double buffering:

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


The Graphics object is created from a panel, which is used as canvas.

_oGraphics = oDest.CreateGraphics(); // oDest is a System.Windows.Forms.Panel


I created a memory buffer for the background and

// render the buffer
_oGraphics.DrawImage(_oImageBackground, 0, 0);

// Render canvas
if(_oCanvas != null)
     _oGraphics.DrawImage(_oCanvas.Canvas, _iCursor, 0);


Clearing the Graphics object is worse. I'm at loss...


Refresh is based on a timer at a 30 millisecond interval and _iCursor moves 2 pixels at a time. Display is otherwise smooth.


Thanks,
Rich.
0
Comment
Question by:mannycalaveras
11 Comments
 
LVL 10

Expert Comment

by:smegghead
ID: 13974150
Where is your code for refreshing ?

Have you tried putting the code for 'drawimage' in the Paint event of the control, then calling invalidate() for that control, that will cause the paint event to be fired, which contains the relevant graphics object. It might be that the panel is refreshing itself anyway.

Smg.
0
 
LVL 1

Author Comment

by:mannycalaveras
ID: 13974720
// Code for refreshing, called by
gr.DrawImage(_oImageBackground, 0, 0);

if(_oCanvas != null)
      gr.DrawImage(_oCanvas.Canvas, _iCursor, 0);


I tried calling invalidate on the Panel in the timer Tick and using the control's Graphics object but it didn't work either.

Next try... refresh thread...
0
 
LVL 1

Author Comment

by:mannycalaveras
ID: 13974944
Refresh thread obviously did not make a difference...

Here's my refresh method

public void Render(/*System.Drawing.Graphics gr*/)
{
      do
      {
            try
            {
                  if(_bRunning && _oGraphics != null && _oCanvas != null)
                  {
                              _oGraphics.DrawImage(_oImageBackground, 0, 0); // oImageBackground is a System.Drawing.Bitmap
                        _oGraphics.DrawImage(_oCanvas.Canvas, _iCursor, 0); // Canvas is a System.Drawing.Bitmap

                        if((_iCursor = _iCursor-2) < -Convert.ToInt32(_oCanvas.Width))
                              _iCursor = Convert.ToInt32(_width);
                  }

                  Thread.Sleep(1000 / _iInterval);
            }
            catch(Exception/* ex*/)
            {
                  //clsUtils.NotifyException(ex);
                  Thread.CurrentThread.Abort();
            }
      }
      while(true);
}
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Expert Comment

by:smegghead
ID: 13976308
Are you able to email me your code? my address is in my profile.
0
 
LVL 11

Expert Comment

by:Agarici
ID: 13976836
i think somewere in your code the background gets erased

so i would say it is worth trying this:

add an override to wndproc and handle the erase background there
protected override void WndProc(ref Message messg)
{
        // We do not want to erase the background,
        if ((int)WM.WM_ERASEBKGND == messg.Msg)
            messg.Msg = (int) WM.WM_NULL;
 
        base.WndProc(ref messg);
}


hth,
A.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 13977356
You could add the ControlStyles.UserPaint, and use the Paint event (persistent), instead of using CreateGraphics (non-persistent).

Bob
0
 
LVL 1

Author Comment

by:mannycalaveras
ID: 13979231
Tried blocking the WM_ERASEBKGND for the panel control or the main window and it did not help.

I already tried using the Graphics object from the OnPaint message without any difference.

Problem seems to be that double buffering or any other display setting doesn't seem to be working.

This is supposed to turn on double buffering as well as styles that minimize flickering...

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


But it doesn't do anything. Whether I put this or not doesn't change anything.
0
 
LVL 10

Expert Comment

by:smegghead
ID: 13979334
Have you overridden the OnPaintBackground

            protected override void OnPaintBackground(PaintEventArgs e)
            {
                  // This section should be left blank - so that it doesn't draw the background..
                  //base.OnPaintBackground(e);
            }
0
 
LVL 22

Expert Comment

by:_TAD_
ID: 13980419

Take a look at this link:
http://www.codeproject.com/cs/media/sprites.asp

This link actually refers to moving sprites/animated graphics, but it may hold the key to a flickerless scrolling textbox for you.

In a nutshell, it uses rectangles and only refreshes a small region.  At any rate, take look... at worst it will cost you 20 minutes of your life.  I found it rather interesting and easy to follow.
0
 
LVL 1

Author Comment

by:mannycalaveras
ID: 13980448
Yes. I have found the problem.

Rendering on the panel caused the problem.

The idea was to have the panel as a delimiter for the canvas.

Double buffering is enabled on the main application and controls do not support double buffering, only the main app.

So instead I use the panel as a bounding box, invisible, and display on the main application's using the panel's bounds as limits.

All examples I found used the main form window as render area so the case was never handled. There might be a way to enable double buffering on individual controls, however the SetStyle requires to be called from a Control control, which only the application window is.

Don't understand why it's not possible for any control as they windows anyway.
0
 

Accepted Solution

by:
PAQ_Man earned 0 total points
ID: 14023945
Question Closed, 200 points refunded.
PAQ_Man
Community Support Moderator
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question