views:

453

answers:

2

I have a downloaded images app in mobile. Every times an image is download successful, it auto draw on to a temp bitmap and then onPaint method draw the whole temp bitmap. It caused the flikering happened to much.

My instructor advised me to use GDI functions to draw the temp bitmap onto the screen every times one image loaded. But his suggestion is so general with the two method.

    [DllImport("coredll.dll")]
    static extern IntPtr GetDC(IntPtr hwnd);

    [DllImport("coredll.dll")]
    static extern void ReleaseDC(IntPtr dc);

So any more clearer advice for me in this situation in what he suggested? Thanks in advance.

UPDATE

    //This is my buffer bitmap
    private Graphics offGraph;
    private Bitmap offBitmap;

    //everytime an image is loaded, it raise an event and then I draw it on buffer.
    private void ImageLoadDone(object sender, EventArgs e)
    {
        ImageObj LoadedImg = (ImageObj)sender;
        LoadedImg.Render(offGraph);
        this.BeginInvoke(new EventHandler(ImageUpdate));
    }

    private void ImageUpdate(object sender, EventArgs myE)
    {
        this.Render();
    }

    //and then onPaint draw the offbitmap.
     private void Render()
    {
       CtrlGraph.DrawImage(offBitmap,0,0);
    }
A: 

IIRC, and if your tags are correct, if you're using C# then you can use GDI+. GDI comes from Win32 and is essentially legacy for WinForms.

Check this out for information on GDI+.

And fyi, the flickering you describe sounds like a product of not having double-buffered form. Read here to learn how to double-buffer your forms.

acron
Maybe I misunderstood you but your link just mentioned about drawing methods in Graphics and that's not what I needed. I think that what I want is getDC of my current Graphic and use it to draw the temp bitmap, but not know how.And as I said, I draw all in a temp bitmap before use the Onpaint method to draw it, so I think it already had double buffered.
Thyphuong
Double-buffering draws your bitmaps to a buffer, rather than directly during an onPaint. Give the article a read dude, you won't be disappointed. Also, my first point is that you don't need getDC/releaseDC when using GDI+ and using GDI with WinForms is a bad idea.
acron
+2  A: 

Yes - you need to do double-buffering to prevent the flicker problem, but you can do this in GDI+ without needing to resort to the API. Here's essentially what you need to do:

private Bitmap backgroundBitmap;
private Graphics backgroundGraphics;
private Rectangle rect;
private Rectangle srcRect;

// create background bitmap the same size as your screen
backgroundBitmap = new Bitmap(this.Width, this.Height);
// create background buffer
backgroundGraphics = Graphics.FromImage(backgroundBitmap);
// get current screen graphics
g = this.CreateGraphics();

rect = new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
srcRect = new Rectangle(0, 0, bmp.Width, bmp.Height);


Then when you receive your event and need to update the screen, call your own method:

Render();

private void Render()
    {            
        // draw your image onto the background buffer
        backgroundGraphics.DrawImage(bmp, rect, srcRect, GraphicsUnit.Pixel);
        // draw whatever you need to on the background graphics
    backgroundGraphics.DrawImage(.....)


        // after all images are drawn onto the background surface
        // blit back buffer to on the screen in one go
        g.DrawImage(backgroundBitmap, this.ClientRectangle,
            new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height), GraphicsUnit.Pixel);

    }

DONT call this.Refresh() or the paint event when you are trying to update the screen since this is what causes the flicker, just call the Render() method directly when you need to update the screen. You just call the Paint method when the screen is first drawn when the application loads

I took this code from my compact framework game

Tim MacLachlan
Make sure you dispose the IDisposable objects. Especially Bitmap.http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx
Bryan
I've just updated my code. That helped much. Btw, is this.CreateGraphics() the best choice when we want to avoid flicker, ignore the onPaint method?
Thyphuong
Thyphuong - Yes, ignore onPaint and call Render() every time you need to update the screen... The only time you need to call onPaint is when you a) initially draw the screen b) if the window is resized c) if another form appears over it Eg it might be called on the onResize or onActivated event
Tim MacLachlan