私の知る限り、すべてのバージョンの Windows で GDI 関数のハードウェア アクセラレーションが得られます (誰かが詳しく説明してくれれば、喜んで訂正します)。しかし、いずれにせよ、ダブル バッファリング (これはあなたが話していることです) は、画面に直接描画する場合と比較して、パフォーマンスを大幅に向上させます (さらに重要なことに、ちらつきはありません)。
私はかなり多くのことを行い、描画関数で GDI と GDI+ を同時に使用できる方法を考え出しましたが、画面への描画では BitBlt のハードウェア アクセラレーションの恩恵を受けます。GDI+ は、知る限りハードウェア アクセラレーションではありませんが、より多くの複雑な描画手法で非常に役立つ可能性があるため、オプションがあると便利です。
したがって、私の基本的なビュー クラスには次のメンバーが含まれます。
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 を実現するための確実な方法です。始めるには少し手間がかかるかもしれませんが、それだけの価値があることは間違いありません。