Sign in to follow this  
kingpinzs

Need help with bitblt a bitmap object to the hdc

Recommended Posts

the code below draws my bitmap object to the window. but I have to use FillRect so I dont gets a trail of images. but it mess up other thing I am trying to do. So what other ways can I bitblt my bmitmap object to the window hdc?
  RECT rcTemp;
     GetClientRect(hwnd,&rcTemp);
       HDC hdc=GetDC(hwnd);
      BitBlt(hdc,0,0,x,y,bmoMap,xoff,yoff,SRCCOPY);
//issue is with fillrect
	FillRect(bmoMap,&rcTemp,(HBRUSH)GetStockObject(BLACK_BRUSH));
   ReleaseDC(hwnd,hdc);

Share this post


Link to post
Share on other sites
I used this code from what Evil_Greven posted when making his tetris game.

how can I add a draw screen to this class?
I thinck it whould be much easyer.


BitMapObject::BitMapObject()
{
hdcMemory=NULL;
hbmNewBitMap=NULL;
hbmOldBitMap=NULL;
iWidth=0;
iHeight=0;
}

BitMapObject::~BitMapObject()
{
//if the hdcMemory hasn't been destroyed, do so
if(hdcMemory)
Destroy();
}
//___________________________________________________________
void BitMapObject::Load(HDC hdcCompatible, LPCTSTR lpszFilename)
{
//if hdcMemory isn't null, make it so captain!
if(hdcMemory)
Destroy();

//create memory dc.
hdcMemory=CreateCompatibleDC(hdcCompatible);

//load the bitmap
hbmNewBitMap=(HBITMAP)LoadImage(NULL,lpszFilename,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

//shove the image into the dc
hbmOldBitMap=(HBITMAP)SelectObject(hdcMemory,hbmNewBitMap);

//grab the bitmap's properties
BITMAP bmp;
GetObject(hbmNewBitMap,sizeof(BITMAP),(LPVOID)&bmp);

//grab the width & height
iWidth=bmp.bmWidth;
iHeight=bmp.bmHeight;
}

//-----------------------------------------------------
void BitMapObject::Create(HDC hdcCompatible, int width, int height)
{
//if hdcMemory isn't null, blow it up!
if(hdcMemory)
Destroy();

//create the memory dc.
hdcMemory=CreateCompatibleDC(hdcCompatible);

//create the bitmap
hbmNewBitMap=CreateCompatibleBitmap(hdcCompatible, width, height);

//shove the image into the dc
hbmOldBitMap=(HBITMAP)SelectObject(hdcMemory, hbmNewBitMap);

//change the width and height.
iWidth=width;
iHeight=height;
}
//create a mask


//-----------------------------------------------------
void BitMapObject::Destroy()
{
//restore old bitmap.
SelectObject(hdcMemory, hbmOldBitMap);

//delete new bitmap.
DeleteObject(hbmNewBitMap);

//delete device context.
DeleteDC(hdcMemory);

//set members to 0/NULL
hdcMemory=NULL;
hbmNewBitMap=NULL;
hbmOldBitMap=NULL;
iWidth=0;
iHeight=0;
}
// -----------------------------------------------------
BitMapObject::operator HDC()
{
//return hdcMemory.
return(hdcMemory);
}

int BitMapObject::GetWidth()
{
//return width
return(iWidth);
}

int BitMapObject::GetHeight()
{
//return height
return(iHeight);
}



this is what I have come up with so far


void BitMapObject::PaintScreen(HWND hwnd, int width,int height)
{
//PaintScreen(hwndChildB,bmoB_Map,XValue,YValue,scroll_origin_x,scroll_origin_y);
HDC hdcCompatible =GetDC(hwnd);
HANDLE hOld;

// Create an off-screen DC for double-buffering
hdcMemory= CreateCompatibleDC(hdcCompatible);
hbmNewBitMap = CreateCompatibleBitmap(hdcCompatible, width, height);
hOld = SelectObject(hdcMemory, hbmNewBitMap);

// Draw into hdcMem

// Transfer the off-screen DC to the screen
BitBlt(hdcCompatible, 0, 0, width, height, hdcMemory, 0, 0, SRCCOPY);

// Free-up the off-screen DC
SelectObject(hdcMemory, hOld);
DeleteObject(hbmNewBitMap);
DeleteDC (hdcMemory);
}



but it is not working yet.

any one have any sugestions?

Share this post


Link to post
Share on other sites
this hack works for now



//ObjSelToPlace (if object is moved on to the map
//MapObjSel (if object already on the map is moved
if(ObjSelToPlace == true ||MapObjSel == true)
{
FillRect(bmoMap,&rcTemp,(HBRUSH)GetStockObject(BLACK_BRUSH));
}




But I still would liketo figure out how to draw to the window with out haveing to use FillRect when an object is moved on the hdc surface

the reason is becuase if I put a background on the surface there will be a black bbox ontop of it every time I move an object on the map

Share this post


Link to post
Share on other sites
I am not erasing the back buffer before re bitblt to it. So I just need to figure out how to erase the back buffer. Right now I am filling it with black which won’t work if I am going to use a bitmap for the background.

Share this post


Link to post
Share on other sites
Well, in simple terms, you can't.

Consider - if the only place your background image exists is on the surface you want to draw the image on top of, once you draw the image, the background underneath it is gone. Simple as that.

When you want to erase the object, you have to redraw the part of the background that the object covered up from somewhere before you draw the object in its new position. So you have to store a separate copy of the background somewhere else so it is not lost when you draw your object.

Assuming the background is an image and not generated procedurally, you need to store the image in memory in an off-screen bitmap. When you erase the object, you can pick the part of the background being revealed from this off-screen buffer and redraw it over the object. Now you are back to unaltered background and you can draw your object in the new position.

However, this creates flicker as the user perceives the object briefly vanishing then appearing again.

The solution is to use another off-screen buffer. Draw your background to it, then draw your object to it. Then draw this entire buffer to the screen.

When you move your object, copy the background image over the object on the off-screen buffer, draw the object in its new position on the off-screen buffer then copy the entire buffer to the screen.

There is an optimisation called "dirty rectangle animation" where you work out only the parts of the screen buffer that have changed (a bounding rectangle that covers both the old and new position of the object) and just copy this to the screen buffer, but this is less commonly used now on faster computers.

In fact, for most purposes now, you can literally just regenerate your entire off-screen buffer each frame (i.e. draw the whole background to the offscreen buffer then draw your object in its current position, then render the whole offscreen buffer to the screen) which simplifies things a great deal.

Offscreen surfaces are (like many things) a pain to work with in GDI. You may like to consider using GDI+ with native C++ to simplify everything tremendously.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this