MFC Support for Windows Animation

Let’s say we have to make a slide show presentation using Cross Fade effect. If the target system is Windows 10, that’s quite easy because Direct2D offers built-in Cross Fade effect.

Cross Fade effect example

void CAnimationWnd::Draw(CRenderTarget* pRenderTarget)
{
    // get ID2D1DeviceContext interface; note: must include 
    CComQIPtr<ID2D1DeviceContext> spDeviceContext = pRenderTarget->GetRenderTarget();

    // create cross-fade effect; note include  and link to dxguid.lib
    CComPtr<ID2D1Effect> spCrossFadeEffect;
    spDeviceContext->CreateEffect(CLSID_D2D1CrossFade, &spCrossFadeEffect);
    // ...
    // set source and destination bitmaps
    spCrossFadeEffect->SetInput(0, m_pBitmapSrc->Get());
    spCrossFadeEffect->SetInput(1, m_pBitmapDest->Get());

    // get "animated" value (uncomment the line below if use Windows Animation)
    // m_spAnimCrossFadeWeightValue->GetValue(m_dWeight);

    // set cross-fade effect weight
    // for a value of 0.0f the destination image is exclusively used
    // for a value of 1.0f the source image is exclusively used
    spCrossFadeEffect->SetValue(D2D1_CROSSFADE_PROP_WEIGHT, static_cast<FLOAT>(m_dWeight));

    // perform drawing
    spDeviceContext->DrawImage(spCrossFadeEffect);
}

Further we can set a timer to periodically change m_dWeight value from 0.0f to 1.0f. So far, so good but a better solution is to use Windows Animation interfaces that allow to implement animations that are smooth, natural, and interactive. Moreover, MFC offers wrapper classes that can make programmer’s life much more easier than in case of direct using COM interfaces.

Using MFC support for animation

To use MFC support for animation do the following:

  1. first of all we need an object of type CAnimationController which is the key class that manages animations;
  2. call CAnimationController::SetRelatedWnd in order to establish a window that will receive WM_PAINT message when animation manager status has changed or animation timer has been updated;
  3. call CAnimationController::EnableAnimationTimerEventHandler;
  4. add an animation object, in our case of type CAnimationValue as long as we only need an “animated” FLOAT to set cross-fade weight property; here is a list of MFC animation object classes defined in afxanimationcontroller.h
    • CAnimationValue
    • CAnimationPoint
    • CAnimationSize
    • CAnimationColor
    • CAnimationRect
  5. add transition(s) to animation object; here is a list of transition MFC classes:
    • CAccelerateDecelerateTransition
    • CConstantTransition
    • CCubicTransition
    • CDiscreteTransition
    • CInstantaneousTransition
    • CLinearTransition
    • CLinearTransitionFromSpeed
    • CSmoothStopTransition
    • CParabolicTransitionFromAcceleration
    • CReversalTransition
    • CSinusoidalTransitionFromRange
    • CSinusoidalTransitionFromVelocity
    • CSinusoidalTransitionFromVelocity
  6. uncomment the line containing m_spAnimCrossFadeWeightValue->GetValue(m_dWeight) in the previous example;
  7. finally, call CAnimationController::AnimateGroup.

Here is some sample code:

void CAnimationWnd::PreSubclassWindow()
{
    // ...

    // this window receive WM_PAINT when animation manager state has changed 
    // or timer post update event has occurred
    m_animController.SetRelatedWnd(this);
    // set a handler for timing events and handler for timing updates
    m_animController.EnableAnimationTimerEventHandler();

    m_spAnimCrossFadeWeightValue = std::make_unique<CAnimationValue>(DEMO_DEFAULT_CROSSFADE_WEIGHT_VALUE, DEMO_GROUP_ID);
    m_animController.AddAnimationObject(m_spAnimCrossFadeWeightValue.get());

    // ...
}
void CAnimationWnd::Animate()
{
    // ...

    // clear existing transitions
    m_spAnimCrossFadeWeightValue->ClearTransitions(TRUE);

    // set initial animation value (here is 1.0f)
    *m_spAnimCrossFadeWeightValue = DEMO_MAX_CROSSFADE_WEIGHT_VALUE;
    // add linear transition to minimum value (0.0f in our case)
    m_spAnimCrossFadeWeightValue->AddTransition(new CLinearTransition(DEMO_TRANSITION_DURATION,
        DEMO_MIN_CROSSFADE_WEIGHT_VALUE));

    // add constant transition; the value remains constant during given duration
    m_spAnimCrossFadeWeightValue->AddTransition(new CConstantTransition(DEMO_TRANSITION_DURATION));

    // add linear transition to maximum value (1.0f)
    m_spAnimCrossFadeWeightValue->AddTransition(new CLinearTransition(DEMO_TRANSITION_DURATION,
        DEMO_MAX_CROSSFADE_WEIGHT_VALUE));

    // run animation
    m_animController.AnimateGroup(DEMO_GROUP_ID);
}

More details can be found in the attached demo project.

Demo project

Download: MFC Support for Animation Demo.zip (1270 downloads)

Cross Fade Effect with Animation 1
Cross Fade Effect with Animation 1
Cross Fade Effect with Animation 2
Cross Fade Effect with Animation 2
Cross Fade Effect with Animation 3
Cross Fade Effect with Animation 3

Resources and related articles

Leave a Comment