Thread: BitBlt() Only draws once - Help!

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

    Angry BitBlt() Only draws once - Help!

    Ive been experimentin with GDI a bit and drawing things to the screen. One of my main problems is that I can only draw to the screen once. Once I have drawn to the screen (for example) Image X, I cannot move and redraw Image X in another location. I do, in my code, Have the functionality to change the X/Y coords of my image, then call me Render function (Which simulates a WM_PAINT message).

    Here is my render function for my Image:

    Code:
    void Image::RenderImage(HWND Hwnd, HDC DevContext, HDC Context)
    {
    	HBITMAP OldBitmap;
    	BITMAP Bitmap;
    	BITMAPINFOHEADER BitmapInfo;
    	int BorderData = RGB(10, 10, 200);
    
    	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, Img.ImageData, (BITMAPINFO *) &BitmapInfo, DIB_RGB_COLORS);
    
    		// Set the position and Draw data
    		OldBitmap = (HBITMAP) SelectObject(Context, ImgMap);
    		GetObject(ImgMap, sizeof(Bitmap), &Bitmap);
    		BitBlt(DevContext, RasterX, RasterY, Bitmap.bmWidth, Bitmap.bmHeight, Context, 0, 0, MERGECOPY);
    
    		// Swap buffers
    		SelectObject(Context, OldBitmap);
    	}
    }
    This function is called from my WndProc function that recieves the WM_PAINT message:

    Code:
    void GDIHandler::Render()
    {
    	POINT MousePos;
    	PAINTSTRUCT Paint;
    
    	// Start the Drawing Process
    	HDC CurrentDeviceContext = BeginPaint(WindowHwnd, &Paint);
    	HDC DeviceContextMem = CreateCompatibleDC(CurrentDeviceContext);
    
    	GetCursorPos(&MousePos);
    	SetBkMode(CurrentDeviceContext, TRANSPARENT);
    
    	MyImage->RenderImage(WindowHwnd, CurrentDeviceContext, DeviceContextMem);
    
    	DeleteDC(DeviceContextMem);
    
    	// Finish the drawing process
    	EndPaint(WindowHwnd, &Paint);
    }
    Ive been trying to debug this all weekend, Can someone please shed some insight on what Im doing wrong?
    Founder and avid member of the Internationsl Typo Associateion

  2. #2
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    what values are RasterX and RasterY?

    Kuphryn

  3. #3
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Those are the X and Y coordinates of where to place the image. currently they are initially set to 100, 100. then its rendered, moved to 500, 500, and rendered agian. The RasterX and RasterY values get changed but bitblt() does not render them in thier new place.
    Founder and avid member of the Internationsl Typo Associateion

  4. #4
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    increment coordinates by 10

    bitmap is empty after initial render?

    Kuphryn

  5. #5
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    I incremented by 10, and still the same problem. the bitmap sits in its initial position in the window. What i noticed is that after this line of code:

    Code:
    GetObject(ImgMap, sizeof(Bitmap), &Bitmap);
    Bitmap.bmBits is equal to NULL. Shouldnt that variable in that struct point to some array of RGB values?
    Founder and avid member of the Internationsl Typo Associateion

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    A few ideas.
    • You don't seem to be deleting your bitmap(ImgMap). If this function is called often, as it will be if called from WM_PAINT, then your system will very quickly run out of memory. You can delete your bitmap with DeleteObject (after it is selected out of the DC). However, if ImageData does not change, I would suggest that you only create the bitmap once and use it as needed.
    • Is there a reason that you are using MERGECOPY rather than the the usual SRCCOPY?
    • The DC obtained from BeginPaint should be left in the same state as it was obtained. Therefore, if you call SetBkMode on it, you should restore the back mode before calling EndPaint.
    • If none of the above suggestions solve the problem, make sure the rendering code is actually being called.
      Code:
      	if (Loaded && Renderable && ImgHeader.BitsPerPixel == 32)
      	{
      		// Make sure you are getting here...

    Bitmap.bmBits is equal to NULL. Shouldnt that variable in that struct point to some array of RGB values?
    No, this member is only valid for dib sections, which are a special type of bitmap which make their memory available to user mode code (created with CreateDIBSection).
    Last edited by anonytmouse; 07-24-2006 at 12:16 PM.

  7. #7
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Quote Originally Posted by anonytmouse
    A few ideas.

    You don't seem to be deleting your bitmap(ImgMap). If this function is called often, as it will be if called from WM_PAINT, then your system will very quickly run out of memory. You can delete your bitmap with DeleteObject (after it is selected out of the DC). However, if ImageData does not change, I would suggest that you only create the bitmap once and use it as needed.
    Yes I changed this right after posting the original post. Doesnt Fix anything (I assumed it wouldnt)

    Quote Originally Posted by anonytmouse
    Is there a reason that you are using MERGECOPY rather than the the usual SRCCOPY?
    The reason im using merge copy is because Im using a layered window (to create a translucent window) so that whatever I paint onto the window, if its a certain color, it will be fully transparent, else t would be translucent. Essentialy a translucent skinned window.

    Quote Originally Posted by anonytmouse
    The DC obtained from BeginPaint should be left in the same state as it was obtained. Therefore, if you call SetBkMode on it, you should restore the back mode before calling EndPaint.
    I also Deleted this line of code. Didnt help.

    Quote Originally Posted by anonytmouse
    If none of the above suggestions solve the problem, make sure the rendering code is actually being called.
    Indeed it does.

    Any other suggestions?
    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
    More ideas.

    - It sounds like the background isn't being erased when you move the image. This is the first thing you should fix.

    - The correct area may have not been invalidated. Make sure the entire window is invalidated (using InvalidateRect with NULL). You can optimise later, if required.

    - Just for debugging purposes, try using SRCCOPY.

  9. #9
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Quote Originally Posted by anonytmouse
    More ideas.
    - The correct area may have not been invalidated. Make sure the entire window is invalidated (using InvalidateRect with NULL). You can optimise later, if required.
    This worked. But now the problem becomes that I get alot of flicker. Is there a way of double buffering the client area?
    Founder and avid member of the Internationsl Typo Associateion

  10. #10
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Catch22 has an excellent article on preventing flicker. The solution that you should consider is clipping:

    1. Turn off background drawing in WM_ERASEBKGND. You can do the background in the render function.
    2. At the start of your render function, call ExcludeClipRect to exclude the area of your bitmap.
    3. Paint the background using FillRect.
    4. Turn off clipping by calling SelectClipRgn with NULL.
    5. Paint your bitmap.

  11. #11
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Im still having probems with double buffering. This is what I have before i draw any of my bitmaps. Unfortunately its not painting the screen the color I want it, it just leaves it back.

    Code:
    // Erase Background
    memset(&EraseRect, 0, sizeof(RECT));
    EraseRect.bottom = WindowWidth;
    EraseRect.right = WindowHeight;
    BackGrnd = CreateSolidBrush(RGB(255, 0, 255));
    FillRect(DeviceContextMem, &EraseRect, BackGrnd);
    Founder and avid member of the Internationsl Typo Associateion

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Quote Originally Posted by Mastadex
    Code:
    // Erase Background
    memset(&EraseRect, 0, sizeof(RECT));
    EraseRect.bottom = WindowWidth;
    EraseRect.right = WindowHeight;
    BackGrnd = CreateSolidBrush(RGB(255, 0, 255));
    FillRect(DeviceContextMem, &EraseRect, BackGrnd);
    Other than you seem to have got width and height mixed up, your code looks fine. Is DeviceContextMem valid at the time? I see that it is a memory DC rather than a window DC so does it have an appropriately sized bitmap selected into it?

    As outlined in my previous post, if you just want to paint a bitmap onto a window, double buffering is probably overkill.

  13. #13
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    Hmm, that might have been a goof on my part, but even tho, should that have painted on part of the screen? Ill swap the Mem HCD to the window DC and see if that helps.

    The DC is correct because its the same one i use to write the bitmaps on.

    I have many bitmaps being rendered now, im getting lots of flicker
    Founder and avid member of the Internationsl Typo Associateion

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. BitBlt()
    By Gordon in forum Windows Programming
    Replies: 2
    Last Post: 05-29-2008, 12:38 AM
  2. Which BitBlt Raster Op?
    By SMurf in forum Windows Programming
    Replies: 1
    Last Post: 03-01-2006, 01:52 PM
  3. another BitBlt question..
    By btq in forum Windows Programming
    Replies: 6
    Last Post: 10-11-2002, 04:28 PM
  4. bitblt
    By canine in forum Windows Programming
    Replies: 3
    Last Post: 07-10-2002, 12:17 AM
  5. Problems with BitBlt
    By Isometric in forum Windows Programming
    Replies: 6
    Last Post: 02-05-2002, 09:20 PM