我现在做的一个项目中涉及绘制地图的问题,有个定时刷新的问题,如每个0.5秒钟刷新一次。为了不出现界面绘制有延迟闪烁的问题,我使用了双缓冲来绘制,但是不到3个小时的时间就耗光堆栈了。我参照网上人家写的MemDC类,里面每次都要CreateCompatibelDC和DeleteDC,还有CreateCompatibleBitmap和DeleteObject。这样很恼火。请问大家尤其是做游戏开发的同志们是怎么解决这些问题的啊,能给点参考意见吗?代码:
OnPaint()
{
CPaintDC dc(this);
XMemDC MemDC(&dc); // Paint function
PaintImage(dc.m_hWnd);
}
下面是XMemDC的代码:class XMemDC
{
public:
// Constructor sets up the memory DC
XMemDC(CWnd* pWnd)
{
ASSERT(pWnd != NULL);
BOOL bResult = FALSE;
m_pWnd = pWnd;
m_hOldDC = ::GetDC(pWnd->GetSafeHwnd());
m_pOldBitmap = NULL;
m_hDC = NULL; ASSERT(m_hOldDC);
::GetClipBox(m_hOldDC, &m_rect);
m_hDC = CreateCompatibleDC(m_hOldDC);
ASSERT(m_hDC != NULL);
m_bitmap = CreateCompatibleBitmap(m_hOldDC, m_rect.right - m_rect.left,
m_rect.bottom - m_rect.top);
ASSERT(m_bitmap != NULL);
m_pOldBitmap = (HBITMAP)::SelectObject(m_hDC, m_bitmap);
// #ifndef _WIN32_WCE
// ::SetWindowOrg(m_hDC, m_rect.left, m_rect.top);
// #endif
// EFW - Bug fix - Fill background in case the user has overridden
// WM_ERASEBKGND. We end up with garbage otherwise.
// CJM - moved to fix a bug in the fix.
FillSolidRect(&m_rect, ::GetBkColor(m_hOldDC));
} XMemDC(HDC hSrcDC)
{
BOOL bResult = FALSE; ASSERT(hSrcDC != NULL);
m_pWnd = NULL;
m_hOldDC = hSrcDC;
m_pOldBitmap = NULL;
m_hDC = NULL;
ASSERT(m_hOldDC);
::GetClipBox(m_hOldDC, &m_rect);
m_hDC = CreateCompatibleDC(m_hOldDC);
ASSERT(m_hDC != NULL);
m_bitmap = CreateCompatibleBitmap(m_hOldDC, m_rect.right - m_rect.left,
m_rect.bottom - m_rect.top);
ASSERT(m_bitmap != NULL);
m_pOldBitmap = (HBITMAP)::SelectObject(m_hDC, m_bitmap);
// #ifndef _WIN32_WCE
// ::SetWindowOrg(m_hDC, m_rect.left, m_rect.top);
// #endif
// EFW - Bug fix - Fill background in case the user has overridden
// WM_ERASEBKGND. We end up with garbage otherwise.
// CJM - moved to fix a bug in the fix.
FillSolidRect(&m_rect, ::GetBkColor(m_hOldDC));
}
// Destructor copies the contents of the mem DC to the original DC
~XMemDC()
{
// Copy the offscreen bitmap onto the screen.
BitBlt(m_hOldDC, m_rect.left, m_rect.top, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top,
m_hDC, m_rect.left, m_rect.top, SRCCOPY);
//Swap back the original bitmap.
::SelectObject(m_hDC, m_pOldBitmap); // Delete m_bitmap
::DeleteObject(m_bitmap); m_bitmap = NULL; // Delete DC
DeleteDC(m_hDC); m_hDC = NULL; if (m_pWnd)
{
int iRet = ::ReleaseDC(m_pWnd->GetSafeHwnd(), m_hOldDC);
ASSERT(iRet != 0);
}
m_hOldDC = NULL;
}
HDC GetSafeHdc() { return m_hDC; } void FillSolidRect(RECT* pRect, COLORREF color)
{
HBRUSH hBrush = ::CreateSolidBrush(color); ::FillRect(m_hDC, pRect, hBrush);
::DeleteObject(hBrush); hBrush = NULL;
}
private:
HBITMAP m_bitmap; // Offscreen bitmap
HBITMAP m_pOldBitmap; // bitmap originally found in CMemDC
HDC m_hOldDC; // Saves DC passed in constructor
RECT m_rect; // Rectangle of drawing area.
HDC m_hDC;
CWnd* m_pWnd;
};
OnPaint()
{
CPaintDC dc(this);
XMemDC MemDC(&dc); // Paint function
PaintImage(dc.m_hWnd);
}
下面是XMemDC的代码:class XMemDC
{
public:
// Constructor sets up the memory DC
XMemDC(CWnd* pWnd)
{
ASSERT(pWnd != NULL);
BOOL bResult = FALSE;
m_pWnd = pWnd;
m_hOldDC = ::GetDC(pWnd->GetSafeHwnd());
m_pOldBitmap = NULL;
m_hDC = NULL; ASSERT(m_hOldDC);
::GetClipBox(m_hOldDC, &m_rect);
m_hDC = CreateCompatibleDC(m_hOldDC);
ASSERT(m_hDC != NULL);
m_bitmap = CreateCompatibleBitmap(m_hOldDC, m_rect.right - m_rect.left,
m_rect.bottom - m_rect.top);
ASSERT(m_bitmap != NULL);
m_pOldBitmap = (HBITMAP)::SelectObject(m_hDC, m_bitmap);
// #ifndef _WIN32_WCE
// ::SetWindowOrg(m_hDC, m_rect.left, m_rect.top);
// #endif
// EFW - Bug fix - Fill background in case the user has overridden
// WM_ERASEBKGND. We end up with garbage otherwise.
// CJM - moved to fix a bug in the fix.
FillSolidRect(&m_rect, ::GetBkColor(m_hOldDC));
} XMemDC(HDC hSrcDC)
{
BOOL bResult = FALSE; ASSERT(hSrcDC != NULL);
m_pWnd = NULL;
m_hOldDC = hSrcDC;
m_pOldBitmap = NULL;
m_hDC = NULL;
ASSERT(m_hOldDC);
::GetClipBox(m_hOldDC, &m_rect);
m_hDC = CreateCompatibleDC(m_hOldDC);
ASSERT(m_hDC != NULL);
m_bitmap = CreateCompatibleBitmap(m_hOldDC, m_rect.right - m_rect.left,
m_rect.bottom - m_rect.top);
ASSERT(m_bitmap != NULL);
m_pOldBitmap = (HBITMAP)::SelectObject(m_hDC, m_bitmap);
// #ifndef _WIN32_WCE
// ::SetWindowOrg(m_hDC, m_rect.left, m_rect.top);
// #endif
// EFW - Bug fix - Fill background in case the user has overridden
// WM_ERASEBKGND. We end up with garbage otherwise.
// CJM - moved to fix a bug in the fix.
FillSolidRect(&m_rect, ::GetBkColor(m_hOldDC));
}
// Destructor copies the contents of the mem DC to the original DC
~XMemDC()
{
// Copy the offscreen bitmap onto the screen.
BitBlt(m_hOldDC, m_rect.left, m_rect.top, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top,
m_hDC, m_rect.left, m_rect.top, SRCCOPY);
//Swap back the original bitmap.
::SelectObject(m_hDC, m_pOldBitmap); // Delete m_bitmap
::DeleteObject(m_bitmap); m_bitmap = NULL; // Delete DC
DeleteDC(m_hDC); m_hDC = NULL; if (m_pWnd)
{
int iRet = ::ReleaseDC(m_pWnd->GetSafeHwnd(), m_hOldDC);
ASSERT(iRet != 0);
}
m_hOldDC = NULL;
}
HDC GetSafeHdc() { return m_hDC; } void FillSolidRect(RECT* pRect, COLORREF color)
{
HBRUSH hBrush = ::CreateSolidBrush(color); ::FillRect(m_hDC, pRect, hBrush);
::DeleteObject(hBrush); hBrush = NULL;
}
private:
HBITMAP m_bitmap; // Offscreen bitmap
HBITMAP m_pOldBitmap; // bitmap originally found in CMemDC
HDC m_hOldDC; // Saves DC passed in constructor
RECT m_rect; // Rectangle of drawing area.
HDC m_hDC;
CWnd* m_pWnd;
};
{
CPaintDC dc(this);
XMemDC MemDC(&dc); // Paint function
PaintImage(dc.m_hWnd);
}
你这里根本没有用到MemDC进行绘制啊。另外,你的问题可能出在绘制代码上没有释放GDI资源或者其他地方的内存泄漏。
if (::IsWindow(m_hWnd))
{
PAINTSTRUCT ps;
HDC hPaintDC = ::BeginPaint(m_hWnd, &ps);
if (hPaintDC)
{
XMemDC MemDC(hPaintDC);
Paint(MemDC.GetSafeHdc());
}
::EndPaint(m_hWnd, &ps);
}
#define _XATTACHDC_Hclass XStabMemDC
{
public:
XStabMemDC(CWnd* pWnd)
{
ASSERT(pWnd != NULL); // Zero memory values first at the beginning.
_pCltDC = NULL;
_hDC = NULL;
_hBitmap = NULL;
_hOldMap = NULL;
::SetRect(&_rtRender, 0, 0, 0, 0); pWnd->GetClientRect(&_rtRender); _pCltDC = new CClientDC(pWnd);
ASSERT(_pCltDC != NULL); if (!_hDC && !_hBitmap && !_hOldMap)
{
_hDC = ::CreateCompatibleDC(_pCltDC->m_hDC);
ASSERT(_hDC != NULL); _hBitmap = ::CreateCompatibleBitmap(_pCltDC->m_hDC,
_rtRender.right - _rtRender.left, _rtRender.bottom - _rtRender.top);
ASSERT(_hBitmap != NULL); _hOldMap = (HBITMAP)::SelectObject(_hDC, _hBitmap);
}
} ~XStabMemDC()
{
if (_hDC && _hBitmap && _hOldMap)
{
::SelectObject(_hDC, _hOldMap); _hOldMap = NULL;
::DeleteObject(_hBitmap); _hBitmap = NULL;
::DeleteDC(_hDC); _hDC = NULL;
} if (_pCltDC)
{
delete _pCltDC; _pCltDC = NULL;
}
} BOOL Export()
{
if (_pCltDC->m_hDC && _hDC)
{
return ::BitBlt(_pCltDC->m_hDC, _rtRender.left, _rtRender.top,
_rtRender.right - _rtRender.left, _rtRender.bottom - _rtRender.top,
_hDC, _rtRender.left, _rtRender.top, SRCCOPY);
} return FALSE;
} HDC GetSafeHdc()
{
return _hDC;
}private:
CClientDC* _pCltDC; // Screen device.
HDC _hDC; // Memory device.
HBITMAP _hBitmap; // Memory device selected bitmap.
HBITMAP _hOldMap; // the old bitmap that select from _hDC. RECT _rtRender; // The rendering rectangle.
};#endif//_XATTACHDC_H
使用方法:在窗口创建时,将XStabMemDC* _pStabDC = NULL; // 类成员..._pStabDC = new XStabMemDC(this);
void OnPaint()
{
Paint(_pStabDC.GetSageHdc());
_pStabDC->Export();
}