用MFC写了一个类似于魔塔的小游戏,但是发现会产生GDI泄露,运行一段时间就会崩掉,但是有些位图文件不能通过deleteObject释放,自己搞不太明白,请教一下各位。
hero等对象应该是成员变量吧。从代码来看,hero中的picture载入的图片是固定的,那么完全没有必要在OnPaint函数中进行重复调用,完全是浪费,应该将这些代码放到hero对象初始化的地方,一次性完成就可以了。
另外,cDC指针最好也ReleaseDC释放掉。
我是题主,不好意思第一次提问不太会问,下面是比较详细的问题描述:
我的双缓冲的实现是:
先使用一个m_cacheDC作为缓冲DC,所有的内容先用m_cacheDC.BitBlt 画在这个DC的位图上面,然后再一下子画到主屏幕上。代码示例如下
m_cacheDC.CreateCompatibleDC(cDC);
m_cacheBitmap.CreateCompatibleBitmap(cDC, m_Client.Width(), m_Client.Height());
m_cacheDC.SelectObject(&m_cacheBitmap);
m_cacheBitmap.LoadBitmap(IDB_BITMAP1);
herotemp.CreateCompatibleDC(NULL); //hero
herotemp.SelectObject(&(hero.picture));
hero.picture.LoadBitmap(IDB_BITMAP4);
但是在最后释放内存时,只有m_cacheDC的关联位图可以释放,其他的位图如果释放那么那一块内容在屏幕上就是缺失的。这个地方就搞不明白了。请问一下如何解决这个问题带来的GDI泄露?
申请DC后记得releaseDC(),希望能够帮到你
代码还是不完整,资源的创建和释放代码未提供。
特别注意CDC资源,很有限的,位图资源也很浪费
OnPaint函数代码:
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CDC *cDC = this->GetDC(); //get the window pointer
GetClientRect(&m_Client); //get the size of Client area
//set the cache DC
m_cacheDC.CreateCompatibleDC(cDC);
m_cacheBitmap.CreateCompatibleBitmap(cDC, m_Client.Width(), m_Client.Height());
m_cacheDC.SelectObject(&m_cacheBitmap);
m_cacheBitmap.LoadBitmap(IDB_BITMAP1);
//set the elements and bitmaps
herotemp.CreateCompatibleDC(NULL); //hero
herotemp.SelectObject(&(hero.picture));
hero.picture.LoadBitmap(IDB_BITMAP4);
floortemp.CreateCompatibleDC(&m_cacheDC); //floor
floortemp.SelectObject(&floor);
floor.LoadBitmap(IDB_BITMAP2);
keytemp.CreateCompatibleDC(&m_cacheDC); //keys
keytemp.SelectObject(key);
key.LoadBitmap(IDB_BITMAP3);
doortemp.CreateCompatibleDC(&m_cacheDC);//doors
doortemp.SelectObject(&door);
door.LoadBitmap(IDB_BITMAP5);
walltemp.CreateCompatibleDC(&m_cacheDC); //wall
walltemp.SelectObject(&wall);
wall.LoadBitmap(IDB_BITMAP2);
uptemp.CreateCompatibleDC(&m_cacheDC);//upstairs
uptemp.SelectObject(&upstair);
upstair.LoadBitmap(IDB_BITMAP5);
downtemp.CreateCompatibleDC(&m_cacheDC);//downstairs
downtemp.SelectObject(&downstair);
downstair.LoadBitmap(IDB_BITMAP5);
wintemp.CreateCompatibleDC(&m_cacheDC); //winning picture
wintemp.SelectObject(&winbmp);
winbmp.LoadBitmap(IDB_BITMAP8);
dietemp.CreateCompatibleDC(&m_cacheDC); //dying picture
dietemp.SelectObject(&diebmp);
diebmp.LoadBitmap(IDB_BITMAP7);
int i;
for (i = 0; i < 6; i++) { //the monsters
monstertemp[i].CreateCompatibleDC(&m_cacheDC);
monstertemp[i].SelectObject(&(monster[i].picture));
monster[i].picture.LoadBitmap(IDB_BITMAP6);
}
int xx = 0, yy = 0;
for (xx = 0; xx < 10; xx++) { //draw the map of each floor
for (yy = 0; yy < 10; yy++) {
if (map[hero.index][xx][yy] == WALL) m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &walltemp, 6 * 32, 0, SRCCOPY);
else if (map[hero.index][xx][yy] == FLOOR) m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &floortemp, 0, 0, SRCCOPY);
else if (map[hero.index][xx][yy] == DOOR) m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &doortemp, 4 * 32, 0, SRCCOPY);
else if (map[hero.index][xx][yy] == KEY) m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &keytemp, 2 * 32, 0, SRCCOPY);
else if (map[hero.index][xx][yy] == UPSTAIR) m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &uptemp, 0, 3 * 32, SRCCOPY);
else if (map[hero.index][xx][yy] == DOWNSTAIR)m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &downtemp, 32, 3 * 32, SRCCOPY);
else if (map[hero.index][xx][yy] == MONSTER&&!heroarrive) {
monster[hero.index].x = xx;
monster[hero.index].y = yy;
map[hero.index][xx][yy] = FLOOR;
m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &floortemp, 0, 0, SRCCOPY);
}
else if (map[hero.index][xx][yy] == MONSTER2&&!heroarrive) {
monster[hero.index + 1].x = xx;
monster[hero.index + 1].y = yy;
map[hero.index][xx][yy] = FLOOR;
m_cacheDC.BitBlt(32 * xx, 32 * yy, 32, 32, &floortemp, 0, 0, SRCCOPY);
}
else if (map[hero.index][xx][yy] == GIRL) m_cacheDC.BitBlt(32 * xx, 32 * yy , 32, 32, &doortemp, 4 * 32, 7 * 32, SRCCOPY);
}
}
heroarrive = 1;
m_cacheDC.BitBlt(32 * monster[hero.index].x, 32 * monster[hero.index].y, 32, 32, &monstertemp[hero.index], 32 * monster[hero.index].direction, 32 * monster[hero.index].film, SRCCOPY);
if (hero.index == 4) m_cacheDC.BitBlt(32 * monster[hero.index + 1].x, 32 * monster[hero.index + 1].y, 32, 32, &monstertemp[hero.index + 1], 32 * monster[hero.index + 1].direction, 32 * monster[hero.index + 1].film, SRCCOPY);
m_cacheDC.BitBlt(32 * hero.x , 32 * hero.y, 32, 32, &herotemp, 32 * hero.film, 32 * hero.direction, SRCCOPY);
int life,key;
for (life = 0; life < hero.life; life++)
m_cacheDC.BitBlt(32 * life, 10*32, 32, 32, &herotemp, 0, 0, SRCCOPY);
for (key = 0; key < hero.key; key++)
m_cacheDC.BitBlt(32 * (9-key), 32*10, 32, 32, &keytemp, 2 * 32, 0, SRCCOPY);
//draw the cache pictures on the screen
cDC->BitBlt(0, 0, m_Client.Width(), m_Client.Height(), &m_cacheDC, 0, 0, SRCCOPY);
ValidateRect(&m_Client);