之前的文章,我提到了GDI双缓冲绘图,代码比较复杂,或许应用的时候有点麻烦,所以这里推荐一个CMemDC类;
注意:在VC2010中,已经有CMemDC类了,所以我添加了命名空间;
// MemDC.h : header file
//
#ifndef MEMDC_H
#define MEMDC_H
//
// CMemDC - memory DC
//
// Author: Keith Rule
// Email: keithr@europa.com
// Copyright 1996-1997, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// History - 10/3/97 Fixed scrolling bug.
// Added print support.
// 25 feb 98 - fixed minor assertion bug
//
// This class implements a memory Device Context
namespace MyMemDC
{
class CMemDC : public CDC
{
public:
// constructor sets up the memory DC
CMemDC(CDC* pDC) : CDC()
{
ASSERT(pDC != NULL);
m_pDC = pDC;
m_pOldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();
if (m_bMemDC) // Create a Memory DC
{
pDC->GetClipBox(&m_rect);
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
SetWindowOrg(m_rect.left, m_rect.top);
}
else // Make a copy of the relevent parts of the current DC for printing
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
// Destructor copies the contents of the mem DC to the original DC
~CMemDC()
{
if (m_bMemDC)
{
// Copy the offscreen bitmap onto the screen.
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
//Swap back the original bitmap.
SelectObject(m_pOldBitmap);
} else {
// All we need to do is replace the DC with an illegal value,
// this keeps us from accidently deleting the handles associated with
// the CDC that was passed to the constructor.
m_hDC = m_hAttribDC = NULL;
}
}
// Allow usage as a pointer
CMemDC* operator->() {return this;}
// Allow usage as a pointer
operator CMemDC*() {return this;}
private:
CBitmap m_bitmap; // Offscreen bitmap
CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC
CDC* m_pDC; // Saves CDC passed in constructor
CRect m_rect; // Rectangle of drawing area.
BOOL m_bMemDC; // TRUE if CDC really is a Memory DC.
};
}
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif //MEMDC_H
简单说明:
1:
CMemDC关联的是一个DC,一般是我们的对话框DC,可以通CClient获取; 会在内存创建一个和指定DC一样大小的内存DC;
然后可以在CMemDC对象上直接绘图,可以通过GDI或者GDI+的方式,一般可以用GDI+的方式绘图;
在CMemDC析构的时候就将图像绘制到对话框上了;
2:
如果CMemDC是长期存在的,为了提高效率,可以将CMemDC作为全局或者成员变量等,然后在CMemDC中添加一个绘图函数,就是析构中的代码;
这个可以自行添加;
简单应用:
#include <gdiplus.h>
using namespace Gdiplus;
#include "MemDC.h"
void Ctmfc1Dlg::OnBtnDrawImage()
{
// TODO: 在此添加控件通知处理程序代码
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CClientDC dc(this);
MyMemDC::CMemDC memdc1(&dc);
Graphics g(memdc1->m_hDC);
g.Clear( Gdiplus::Color::White );
//GDI绘图
memdc1->MoveTo(0,0);
memdc1->LineTo(1000,1000);
//GDI+绘图
Gdiplus::Bitmap bmp(L"t.bmp");
g.DrawImage( &bmp, 0,0 );
}