代码改变世界

WTL学习笔记(5)双缓冲技术和动画(BufferedPaint)

2011-08-10 20:37  Clingingboy  阅读(1745)  评论(0编辑  收藏  举报

 

Vista+添加了相关函数对GDI双缓冲进行了支持,下面是wtl进行的封装

1.CBufferedPaint

对相关的BufferedPaint函数进行封装

class CBufferedPaint
{
public:
    HPAINTBUFFER m_hPaintBuffer;

    CBufferedPaint() : m_hPaintBuffer(NULL)
    { }

    ~CBufferedPaint()
    {
        ATLVERIFY(SUCCEEDED(End()));
    }

    bool IsNull() const
    {
        return (m_hPaintBuffer == NULL);
    }

    HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint)
    {
        ATLASSERT(m_hPaintBuffer == NULL);
        m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint);
        return m_hPaintBuffer;
    }

    HRESULT End(BOOL bUpdate = TRUE)
    {
        HRESULT hRet = S_FALSE;
        if(m_hPaintBuffer != NULL)
        {
            hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate);
            m_hPaintBuffer = NULL;
        }
        return hRet;
    }
…
   };

好像构造函数和析构函数中没有添加BufferedPaintInit和BufferedPaintUnInit函数,使用相关函数必须先调用BufferedPaintInit,结束时调用BufferedPaintUnInit

2.CBufferedPaintBase

CBufferedPaintBase封装了BufferedPaintInit和BufferedPaintUnInit函数,IsBufferedPaintSupported判断必须是vista+

class CBufferedPaintBase
{
public:
    static int m_nIsBufferedPaintSupported;

    CBufferedPaintBase()
    {
        if(IsBufferedPaintSupported())
            ATLVERIFY(SUCCEEDED(::BufferedPaintInit()));
    }

    ~CBufferedPaintBase()
    {
        if(IsBufferedPaintSupported())
            ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit()));
    }

    static bool IsBufferedPaintSupported()
    {
        if(m_nIsBufferedPaintSupported == -1)
        {
            CStaticDataInitCriticalSectionLock lock;
            if(FAILED(lock.Lock()))
            {
                ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n"));
                ATLASSERT(FALSE);
                return false;
            }

            if(m_nIsBufferedPaintSupported == -1)
                m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0;

            lock.Unlock();
        }

        ATLASSERT(m_nIsBufferedPaintSupported != -1);
        return (m_nIsBufferedPaintSupported == 1);
    }
};

3.CBufferedPaintImpl

CBufferedPaintImpl继承了CBufferedPaintBase,并在内部调用了CBufferedPaint的相关方法

4.CBufferedPaintWindowImpl

继承自CBufferedPaintImpl,默认实现BufferedPaint功能

参考:

http://www.cnblogs.com/dflying/archive/2007/03/21/681921.html

http://www.codeguru.com/cpp/w-p/vista/print.php/c15709/(源码示例参考)

动画支持

5.CBufferedAnimation

BeginBufferedAnimation,EndBufferedAnimation,BufferedPaintRenderAnimation是新增了三个函数,可以在画图时提供动画支持.

CBufferedAnimation封装了这3个函数

6.CBufferedAnimationImpl

除了了解上面三个函数之外,动画肯定需要提供默认的动画效果,BP_ANIMATIONPARAMS用来设置动画效果和动画间隔时间

// BP_ANIMATIONSTYLE
typedef enum _BP_ANIMATIONSTYLE
{
    BPAS_NONE,                // No animation
    BPAS_LINEAR,              // Linear fade animation
    BPAS_CUBIC,               // Cubic fade animation
    BPAS_SINE                 // Sinusoid fade animation
} BP_ANIMATIONSTYLE;


// BP_ANIMATIONPARAMS
typedef struct _BP_ANIMATIONPARAMS
{
    DWORD               cbSize;
    DWORD               dwFlags; // BPAF_ flags
    BP_ANIMATIONSTYLE   style;
    DWORD               dwDuration;
} BP_ANIMATIONPARAMS, *PBP_ANIMATIONPARAMS;

CBufferedAnimationImpl继承自CBufferedPaintBase,并在内部设置了默认的动画效果,同时添加了DoPaint方法,供子类重写

7.CBufferedAnimationWindowImpl

继承自CBufferedAnimationImpl,重写DoPaint方法,默认支持GDI动画程序效果

参考:http://www.codeguru.com/cpp/w-p/vista/print.php/c15841/

感谢这位作者提供的2个通俗易懂的例子