2 bernardyuan bernardyuan 于 2014.11.24 11:40 提问

MFC小游戏,使用双缓冲技术但是有些位图无法释放,导致GDI泄露

用MFC写了一个类似于魔塔的小游戏,但是发现会产生GDI泄露,运行一段时间就会崩掉,但是有些位图文件不能通过deleteObject释放,自己搞不太明白,请教一下各位。

5个回答

happyparrot
happyparrot   Ds   Rxr 2014.11.24 16:09
已采纳

hero等对象应该是成员变量吧。从代码来看,hero中的picture载入的图片是固定的,那么完全没有必要在OnPaint函数中进行重复调用,完全是浪费,应该将这些代码放到hero对象初始化的地方,一次性完成就可以了。
另外,cDC指针最好也ReleaseDC释放掉。

bernardyuan
bernardyuan   2014.11.24 11:41

我是题主,不好意思第一次提问不太会问,下面是比较详细的问题描述:
我的双缓冲的实现是:
先使用一个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泄露?

hzq20081121107
hzq20081121107   2014.11.24 12:00

申请DC后记得releaseDC(),希望能够帮到你

bernardyuan
bernardyuan DC有释放掉,但是CBitmap没办法释放。。
大约 3 年之前 回复
happyparrot
happyparrot   Ds   Rxr 2014.11.24 13:03

代码还是不完整,资源的创建和释放代码未提供。
特别注意CDC资源,很有限的,位图资源也很浪费

bernardyuan
bernardyuan 我的画图代码在下面我自己的回答里面贴出来了。。
大约 3 年之前 回复
bernardyuan
bernardyuan 资源创建的时候添加了很多位图,但是在资源删除的时候只能释放缓冲CDC关联的位图,其他无法释放,否则在屏幕上就不会显示该位图的内容。我觉得是位图没有释放导致的,但是又不知道怎么解决。。。
大约 3 年之前 回复
bernardyuan
bernardyuan   2014.11.24 15:51

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);
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!