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:
- first of all we need an object of type CAnimationController which is the key class that manages animations;
- 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;
- call CAnimationController::EnableAnimationTimerEventHandler;
- 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
- 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
- uncomment the line containing m_spAnimCrossFadeWeightValue->GetValue(m_dWeight) in the previous example;
- 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 (42)
Resources and related articles
- MSDN: CAnimationController Class
- MSDN: CAnimationValue Class
- MSDN: CLinearTransition Class
- MSDN: Cross Fade effect
- Marc Gregoire’s Blog: The New MFC Animation API
- Codexpert blog: MFC Support for Direct2D – Part 6: Composite Effects