WTL-双缓冲(double buffer)绘图

WTL中有两个Mix-in类: CDoubleBufferImpl和CDoubleBufferWindowImpl,用于创建双缓冲绘图窗口,用法非常简单。

下面创建了一个普通的WTL窗口类,在窗口的客户区中有大量的绘图工作,使用CDoubleBufferImpl类来消除绘图时的闪烁现象:

const COLORREF WHITE_COLOR = RGB(255,255,255);

const COLORREF BLUE_COLOR = RGB(0,0,255);

class CMainWindow :

	public CWindowImpl<CMainWindow,CWindow,CSimpleWinTraits>,

	public CDoubleBufferImpl<CMainWindow>

{

public:

	typedef CMainWindow _thisClass;

	typedef CDoubleBufferImpl<_thisClass> _baseDblBufImpl;

	BEGIN_MSG_MAP(CMainWindow)

		MSG_WM_CREATE(OnCreate)

		MSG_WM_DESTROY(OnDestroy)

		CHAIN_MSG_MAP(_baseDblBufImpl)

	END_MSG_MAP()

	int OnCreate(LPCREATESTRUCT lpCreateStruct)

	{

		m_RectPen.CreatePen(PS_SOLID,1,BLUE_COLOR);

		return 0;

	}

	void OnDestroy()

	{

		PostQuitMessage(0);

	}

	

	void OnPaint(CDCHandle)

	{

		CPaintDC dc(m_hWnd);

		DoPaint(dc.m_hDC);

	}

	void DoPaint(CDCHandle dc)

	{

		CRect rc;

		GetClientRect(&rc);

		dc.FillRect(&rc,WHITE_COLOR);

		HPEN hOldPen = dc.SelectPen(m_RectPen);

		const int width = 5;

		int x = 0;

		int count = rc.Width()/width;

		int height = 0;

		for (int i=0; i<count; i++)

		{

			height = (int)((double)rand()*rc.Height())/RAND_MAX;

			dc.Rectangle(x,rc.Height(),x+width,rc.Height()-height);

			x += width;

		}

		dc.SelectPen(hOldPen);

	}

	/*

	void DoPaint(CDCHandle dc)

	{

		CRect rc;

		GetClientRect(&rc);

		int width = rc.Width(), height = rc.Height();

		//use GDI+ to draw in the client area

		Graphics g(dc.m_hDC);

		SolidBrush whiteBrush(Color(255,255,255));

		g.FillRectangle(&whiteBrush,0,0,width,height);

		Pen bluePen(Color(0,0,255));

		const int dx = 5;

		int count = width/dx;

		int x = 0, y = 0, h = 0;

		for (int i=0;i<count;i++)

		{

			h = ((double)rand()*height)/RAND_MAX;

			g.DrawRectangle(&bluePen,x,y,dx,h);

			x += dx;

		}

	}

	*/

private:

	CPen m_RectPen;

};

 

值得一提的是,Windows Vista操作系统增加了对Double buffered paint的内建支持,这里有一篇文章介绍如何在Win32程序中使用这些API:

Using Windows Vista Built-In Double Buffering

在WTL中使用Vista提供的这一功能非常容易,最新的WTL库中提供了CBufferedPaintImpl和CBufferedPaintWindowImpl两个类,这两个类的用法和前面提到的两个WTL自带的双缓冲类几乎一样。区别仅仅是所重载的DoPaint()函数的参数稍有不同。

对于CBufferedPaintImpl类,所需重载的DoPaint()函数的样子如下所示:

void DoPaint(CDCHandle dc, RECT& rect)

{

	CRect rc(rect);

	dc.FillSolidRect(&rc,WHITE_COLOR);

	HPEN hOldPen = dc.SelectPen(m_RectPen);

	const int width = 5;

	int x = 0;

	int count = rc.Width()/width;

	int height = 0;

	for (int i=0; i<count; i++)

	{

		height = (int)((double)rand()*rc.Height())/RAND_MAX;

		dc.Rectangle(x,rc.Height(),x+width,rc.Height()-height);

		x += width;

	}

	dc.SelectPen(hOldPen);

}

你可能感兴趣的:(buffer)