Thread: Flicker in GDI

  1. #1
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195

    Question Flicker in GDI

    I went through several tutorials covering double buffering and flickerless GDI animations. I just cant get them to work. Every time i render, there is alot of flicker because I have to erase the entire screen and redraw everything on to it. switching to OpenGL or directX is not an option (due to time constriants etc).

    The way i traied it was to catch WM_ERASEBKGND and do my own erasing when i render. this still causes flicker regardless. Anyone have any explanation why this is happening to me??

    Here is some of the code I use:

    Code:
    	POINT MousePos;
    	PAINTSTRUCT Paint;
    	HDC CurrentDeviceContext;
    	HDC DeviceContextMem;
    	RECT EraseRect;
    	HBRUSH BackGrnd;
    
    	// Invalidate the Window
    	InvalidateRect(WindowHwnd, NULL, true);
    
    	// Start the Drawing Process
    	CurrentDeviceContext = BeginPaint(WindowHwnd, &Paint);
    
    	DeviceContextMem = CreateCompatibleDC(CurrentDeviceContext);
    
    	// Erase Background
    	memset(&EraseRect, 0, sizeof(RECT));
    	EraseRect.bottom = WindowHeight;
    	EraseRect.right = WindowWidth;
    	BackGrnd = CreateSolidBrush(RGB(255, 0, 255));
    	FillRect(CurrentDeviceContext, &EraseRect, BackGrnd);
    
    	GetCursorPos(&MousePos);
    
    	// Specify which primitive type is to be drawn 
    	for (int i = 0; i < NumPanel; i++)
    	{
    		if (PanelList[i])
    		{
    			PanelList[i]->Render(WindowHwnd, CurrentDeviceContext, DeviceContextMem);
    		}
    	}
    
    	DeleteDC(DeviceContextMem);
    
    	// Finish the drawing process
    	EndPaint(WindowHwnd, &Paint);

    Here is my "Panel" rendering code:

    Code:
    void Panel::Render(HWND Hwnd, HDC DevContext, HDC Context)
    {
    	HBITMAP OldBitmap;
    	BITMAP Bitmap;
    	BITMAPINFOHEADER BitmapInfo;
    	HBITMAP ImgMap;
    
    	if (Loaded && Renderable && ImgHeader.BitsPerPixel == 32)
    	{
    		// Clear our Bitmap
    		memset(&Bitmap, 0, sizeof(BITMAP));
    
    		// Create a struct ot hold the info about the image
    		BitmapInfo.biSize = sizeof(BitmapInfo);
    		BitmapInfo.biHeight = ImgHeader.Height;
    		BitmapInfo.biWidth = ImgHeader.Width;
    		BitmapInfo.biPlanes = 1;
    		BitmapInfo.biBitCount = ImgHeader.BitsPerPixel;
    		BitmapInfo.biCompression = BI_RGB;
    		BitmapInfo.biSizeImage = 0;
    		BitmapInfo.biXPelsPerMeter = BitmapInfo.biYPelsPerMeter = 10000;
    		BitmapInfo.biClrUsed = BitmapInfo.biClrImportant = 0;
    
    		// Create a DIB from our TGA data
    		ImgMap = CreateDIBitmap(DevContext, &BitmapInfo, CBM_INIT, 
    	            (KeyPressed ? Img.ClickData : Img.ImageData), (BITMAPINFO *) &BitmapInfo, DIB_RGB_COLORS);
    
    		// Set the position and Draw data
    		OldBitmap = (HBITMAP) SelectObject(Context, ImgMap);
    		BitBlt(DevContext, RasterX, RasterY, ImgHeader.Width, ImgHeader.Height, Context, 0, 0, MERGECOPY);
    
    		// Swap buffers
    		SelectObject(Context, OldBitmap);
    
    		// Delete our GDI Data
    		DeleteObject(ImgMap);
    	}
    }
    Last edited by Mastadex; 08-15-2006 at 12:38 PM. Reason: reduced horizontal extent of code
    Founder and avid member of the Internationsl Typo Associateion

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Assuming the first block of code is in response to a WM_PAINT, why are you using InvalidateRect there?

    What are you doing in response to a WM_ERASEBKGND message?

    Does your registered window class have a class brush?

    You also seem to be creating and allocating bitmaps with each render cycle; creating them once and destroying them when done will probably be more efficient.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    as an experiment removed the call to InvalidateRect()

    Kuphryn

  4. #4
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Quote Originally Posted by Ken Fitlike
    Assuming the first block of code is in response to a WM_PAINT, why are you using InvalidateRect there?

    What are you doing in response to a WM_ERASEBKGND message?

    Does your registered window class have a class brush?

    You also seem to be creating and allocating bitmaps with each render cycle; creating them once and destroying them when done will probably be more efficient.

    Code:
    		case WM_ERASEBKGND:
    			// Erase Background
    			Rtrn = 1;
    			break;
    
    ....
    
    
    		case WM_PAINT:
    			Render(); // Calls the code posted above
    			break;

    Im not worried about efficiency just yet. I will do as you suggested, but once the problem has been fixed.
    The window is crated without using a background brush. I erase the background manually inside the render function.
    Last edited by Mastadex; 08-15-2006 at 12:42 PM.
    Founder and avid member of the Internationsl Typo Associateion

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Why would you need to erase the on-screen copy if you're just going to copy all over it with the new data?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Just a thought: I had a similar problem and found that EVEN THOUGH I was using EndPaint I still needed to ValidateRect(hwnd, NULL) at the end of my WM_PAINT. -- it's worth the 1.2 minutes to try it.

  7. #7
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Quote Originally Posted by Salem
    Why would you need to erase the on-screen copy if you're just going to copy all over it with the new data?
    Im not drawing to the whole screen all the time, else i wouldnt bother with erasing the background. the code where im erasing the background is basically just painting the window a certain color before i start painting the "panels" onto the screen.

    Ill try validaterect().
    Founder and avid member of the Internationsl Typo Associateion

  8. #8
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Haven't we already done this? As the Catch22 article says, the rule to avoid flicker is: You must never draw over the same pixel twice. I suggest you try:
    - Call ExcludeClipRect after painting every bitmap with the same coordinates.
    - Paint the background after the bitmaps have been painted. Having excluded them from the clipping region, they will not be painted over.

  9. #9
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Ill try this.
    If it doesnt work, is there a way to use double buffering with GDI?

    EDIT: Got it working but the problem now is that my rendering is incredably slow. I might have to consider other options, such as double bufering.

    EDIT 2.0: I got double bufering to work. The problem was 1 line of code that was commented out during my debugging.
    Last edited by Mastadex; 08-17-2006 at 12:19 PM.
    Founder and avid member of the Internationsl Typo Associateion

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Windows GDI vs. Java Graphics
    By Perspective in forum Windows Programming
    Replies: 7
    Last Post: 05-07-2007, 10:05 AM
  2. GDI object lifetime and C++ object lifetime
    By VirtualAce in forum Windows Programming
    Replies: 4
    Last Post: 06-16-2006, 05:26 AM
  3. Whats Peoples Problem With the GDI?
    By MicroFiend in forum Game Programming
    Replies: 6
    Last Post: 07-28-2003, 07:52 PM
  4. Drawing without flicker?
    By Aidman in forum Windows Programming
    Replies: 5
    Last Post: 06-25-2003, 12:23 PM
  5. Double buffering in GDI -- easy?
    By fusikon in forum Game Programming
    Replies: 17
    Last Post: 02-15-2003, 10:03 PM