AFAIK 您可以在所有版本的 Windows 上获得 GDI 功能的硬件加速(如果有人可以更详细地解释它,我很乐意对此进行纠正)。但无论哪种方式,您都是正确的,双缓冲(这就是您所说的)相对于直接绘制到屏幕而言提供了巨大的性能提升(更重要的是没有闪烁)。
我已经做了很多这样的工作,并提出了一种方法,允许您在绘图功能中同时使用 GDI 和 GDI+,但受益于 BitBlt 在屏幕绘图中的硬件加速。GDI+ 不是硬件加速的 AFAIK,但在许多更复杂的绘图技术中非常有用,因此可以选择。
因此,我的基本视图类将具有以下成员:
Graphics *m_gr;
CDC *m_pMemDC;
CBitmap *m_pbmpMemBitmap;
然后类本身将有类似这样的代码
/*======================================================================================*/
CBaseControlPanel::CBaseControlPanel()
/*======================================================================================*/
{
m_pMemDC = NULL;
m_gr = NULL;
m_pbmpMemBitmap = NULL;
}
/*======================================================================================*/
CBaseControlPanel::~CBaseControlPanel()
/*======================================================================================*/
{
// Clean up all the GDI and GDI+ objects we've used
if(m_pMemDC)
{ delete m_pMemDC; m_pMemDC = NULL; }
if(m_pbmpMemBitmap)
{ delete m_pbmpMemBitmap; m_pbmpMemBitmap = NULL; }
if(m_gr)
{ delete m_gr; m_gr = NULL; }
}
/*======================================================================================*/
void CBaseControlPanel::OnPaint()
/*======================================================================================*/
{
pDC->BitBlt(rcUpdate.left, rcUpdate.top, rcUpdate.Width(), rcUpdate.Height(),
m_pMemDC, rcUpdate.left, rcUpdate.top, SRCCOPY);
}
/*======================================================================================*/
void CBaseControlPanel::vCreateScreenBuffer(const CSize szPanel, CDC *pDesktopDC)
// In :
// szPanel = The size that we want the double buffer bitmap to be
// Out : None
/*======================================================================================*/
{
// Delete anything we're already using first
if(m_pMemDC)
{
delete m_gr;
m_gr = NULL;
delete m_pMemDC;
m_pMemDC = NULL;
delete m_pbmpMemBitmap;
m_pbmpMemBitmap = NULL;
}
// Make a compatible DC
m_pMemDC = new CDC;
m_pMemDC->CreateCompatibleDC(pDesktopDC);
// Create a new bitmap
m_pbmpMemBitmap = new CBitmap;
// Create the new bitmap
m_pbmpMemBitmap->CreateCompatibleBitmap(pDesktopDC, szPanel.cx, szPanel.cy);
m_pbmpMemBitmap->SetBitmapDimension(szPanel.cx, szPanel.cy);
// Select the new bitmap into the memory DC
m_pMemDC->SelectObject(m_pbmpMemBitmap);
// Then create a GDI+ Graphics object
m_gr = Graphics::FromHDC(m_pMemDC->m_hDC);
// And update the bitmap
rcUpdateBitmap(rcNewSize, true);
}
/*======================================================================================*/
CRect CBaseControlPanel::rcUpdateBitmap(const CRect &rcInvalid, const bool bInvalidate, const bool bDrawBackground /*=true*/)
// Redraws an area of the double buffered bitmap
// In :
// rcInvalid - The rect to redraw
// bInvalidate - Whether to refresh to the screen when we're done
// bDrawBackground - Whether to draw the background first (can give speed benefits if we don't need to)
// Out : None
/*======================================================================================*/
{
// The memory bitmap is actually updated here
// Then make the screen update
if(bInvalidate)
{ InvalidateRect(rcInvalid); }
}
因此,您可以直接绘制到内存 DC 并调用 InvalidateRect() 或将所有绘图代码放在 rcUpdateBitmap() 中,这对于我使用它的方式更方便。您需要在 OnSize() 中调用 vCreateScreenBuffer()。
无论如何,希望这能给你一些想法。双缓冲绝对是提高速度和不闪烁 UI 的方法。开始可能需要一点努力,但绝对值得。