Archived

This topic is now archived and is closed to further replies.

Lalle

Double Buffering

Recommended Posts

Yesterday I posted a question to finish my double buffering drawing routine. The reply I got was only in theory (It wasn't a bad answer), but when I tried to write the routine I couldn't get it to work. Here is the code for my drawing function:
    
HDC hdcWindow = GetDC(hWindow);
HDC hdcMemory = CreateCompatibleDC(hdcWindow);
HDC hdcBitmap = CreateCompatibleDC(0);

HBITMAP testBitmap1 = LoadBitmap(...);
HBITMAP testBitmap2 = LoadBitmap(...);

BITMAP bmp1, bmp2;


GetObject(testBitmap1, sizeof(bmp1), &bmp1);
GetObject(testBitmap2, sizeof(bmp2), &bmp2);


SelectObject(hdcBitmap, testBitmap1);	
BitBlt(hdcMemory, 50, 50, bmp1.bmWidth, bmp1.bmHeight, hdcBitmap, 0, 0, SRCCOPY);


SelectObject(hdcBitmap, testBitmap2);
BitBlt(hdcMemory, 100, 100, bmp2.bmWidth, bmp2.bmHeight, hdcBitmap, 0, 0, SRCCOPY);


BitBlt(hdcWindow, 20, 20, bmp1.bmWidth, bmp1.bmHeight, hdcMemory, 0, 0, SRCCOPY);



DeleteObject(hdcMemory);
DeleteObject(hdcBitmap);

ReleaseDC(hWindow, hdcWindow);
    
This should make two bitmaps, load them one at a time into a memory DC(hdcBitmap) and BitBlt them to another memory DC(hdcMemory). Then it BitBlts from hdcMemory to hdcWindow. This should draw two images at the same time. But it doesn't. WHY? Please point out any errors both in C++ syntax and in double buffering technique Some example code would be great! Thank you. Lalle Edited by - Lalle on June 9, 2001 10:14:18 AM

Share this post


Link to post
Share on other sites
I don''t know exactly what you want this routine to do but I am guessing you want to display 2 bitmaps on your memory context and then flip the memory context to the screen.

Ok here are your blit to memory dc code:

BitBlt(hdcMemory, 50, 50, bmp1.bmWidth, bmp1.bmHeight, hdcBitmap, 0, 0, SRCCOPY);

BitBlt(hdcMemory, 100, 100, bmp2.bmWidth, bmp2.bmHeight, hdcBitmap, 0, 0, SRCCOPY);

This draws 1 bitmap starting at 50, 50 and another bitmap starting at 100, 100. As long as bmp1 is no larger than 50x50 that should be ok.

BitBlt(hdcWindow, 20, 20, bmp1.bmWidth, bmp1.bmHeight, hdcMemory, 0, 0, SRCCOPY);

This line is a problem. You are blittling to screen from 0, 0 on your memory context and only using width and height of bmp1. More than likely this is drawing nothing on your screen right? That is because you started drawing on your memory context at 50, 50 and not 0, 0.

If you want to flip the entire memory context to screen you should do:

BitBlt( hdcWindow, 0, 0, width, height, hdcMemory, 0, 0, SRCCOPY );

where width and height are the dimensions of your window.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
What you are doing is not exactly double buffering, but loading in a bitmap and blitting it to the screen. To do this, you should :

a) Get the window DC (dcWindow)
b) Create a compatible DC (dcBuffer)
c) Select the bitmap in dcBuffer and keep the handle from the old bitmap
d) Blit from dcBuffer to dcWindow
e) Select the old bitmap back in dcBuffer
f) Delete dcBuffer

  
HDC dcWindow = GetDC(hWindow);
HDC dcBuffer = CreateCompatibleDC(dcWindow);
HBITMAP hBitmap = LoadBitmap(...);
HBITMAP hOldBmp = (HBITMAP) SelectObject(dcBuffer, hBitmap);

BitBlt(dcWindow, tx, ty, width, height, dcBuffer, sx, sy, SRCCOPY);

SelectObject(dcBuffer, hOldBmp);
DeleteDC(dcBuffer);
ReleaseDC(hWindow, dcWindow);
DeleteObject(hBitmap);

Didn''t check it, so there could be several errors, but it should look something like this.

Double buffering is something like this :
  
HDC dcWindow = GetDC(hWindow);
HDC dcBuffer = CreateCompatibleDC(dcWindow);

// Create the actual buffer

HBITMAP hBuffer = CreateCompatibleBitmap(dcWindow, width, height);

// Select it

HBITMAP hOldBmp = (HBITMAP) SelectObject(dcBuffer, hBuffer);

// Clear the buffer (it''s full of garbage)

RECT r = {0, 0, width, height};
FillRect(dcBuffer, &r, (HBRUSH) GetStockObject(BLACK_BRUSH));

// Draw whatever you need


// Blit it to the screen

BitBlt(dcWindow, tx, ty, width, height, dcBuffer, sx, sy, SRCCOPY);

// Clean up

SelectObject(dcBuffer, hOldBmp);
DeleteObject(hBuffer);
DeleteDC(dcBuffer);
ReleaseDC(hWindow, dcWindow);

Share this post


Link to post
Share on other sites
I don''t think what he was trying to do is just blit 1 bitmap to the screen. I think he wants to blit multiple bitmaps to a memory context and then blit the entire memory context to the screen.

So he would load his first bitmap into hdcBitmap, blit it to a certain position on hdcMemory. Then load his second bitmap into hdcBitmap and blit it to a different position on hdcMemory and then blit the entire hdcMemory to the screen in a single pass which is basically what double buffering is. You draw everything to an off-screen buffer and then flip it to the display area.

Share this post


Link to post
Share on other sites
I couldn''t have said it better Krippy2k.
But I tried to change the BitBlt call to what you said and its still not working, just a white window.
I think the error lies in the two BitBlt calls from hdcBitmap to hdcMemory.
If anyone get my code to compile or see an error it would be great.

Lalle

Share this post


Link to post
Share on other sites
this should work:

    
HDC hDC, hDCBmp, hDCBuffer;
HBITMAP hBmp1, hBmp2, hBmpOld, hBmpBuffer, hBmpBufferOld;
BITMAP bmp1, bmp2;
RECT clientarea;

GetClientRect(m_handle, &clientarea);

//initialize DC's

hDC = GetDC(m_handle);
hDCBmp = CreateCompatibleDC(hDC);
hDCBuffer = CreateCompatibleDC(NULL);

//load images

hBmp1 = (HBITMAP)LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP, 0, 0, LR_COPYFROMRESOURCE);
hBmp2 = (HBITMAP)LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDB_BITMAP2),
IMAGE_BITMAP, 0, 0, LR_COPYFROMRESOURCE);

GetObject(hBmp1, sizeof(BITMAP), &bmp1);
GetObject(hBmp2, sizeof(BITMAP), &bmp2);

//initialize buffer

hBmpBufferOld = (HBITMAP)SelectObject(hDCBuffer, hBmp1);
hBmpBuffer = CreateCompatibleBitmap(hDCBuffer, clientarea.right, clientarea.bottom);
SelectObject(hDCBuffer, hBmpBuffer);

//draw images to buffer

FillRect(hDCBuffer, &clientarea, (HBRUSH)GetStockObject(GRAY_BRUSH));

hBmpOld = (HBITMAP)SelectObject(hDCBmp, hBmp1);
BitBlt(hDCBuffer, 0, 0, bmp1.bmWidth, bmp1.bmHeight,
hDCBmp, 0, 0, SRCCOPY);

SelectObject(hDCBmp, hBmp2);
BitBlt(hDCBuffer, 50, 50, bmp2.bmWidth, bmp2.bmHeight,
hDCBmp, 0, 0, SRCCOPY);

//draw buffer to screen

BitBlt(hDC, 0, 0, clientarea.right, clientarea.bottom,
hDCBuffer, 0, 0, SRCCOPY);

//cleanup

SelectObject(hDCBmp, hBmpOld);
SelectObject(hDCBuffer, hBmpBufferOld);

DeleteObject(hBmp1);
DeleteObject(hBmp2);
DeleteObject(hBmpBuffer);

DeleteDC(hDCBmp);
DeleteDC(hDCBuffer);

ReleaseDC(m_handle, hDC);


remember to save the old objects returned by SelectObject() or you'll be leaking resources!

Edited by - kvh on June 10, 2001 8:00:09 AM

Share this post


Link to post
Share on other sites