演练:将动画添加到 MFC 项目

本演练介绍如何将基本动画对象添加到 Visual C++,Microsoft基础类库 (MFC) 项目。

本演练演示如何完成以下任务:

  • 创建 MFC 应用程序。

  • 添加菜单,然后添加命令以启动和停止动画。

  • 为启动和停止命令创建处理程序。

  • 向项目添加动画对象。

  • 将动画对象居中。

  • 验证结果。

注释

计算机可能会在以下说明中显示某些 Visual Studio 用户界面元素的不同名称或位置。 你拥有的 Visual Studio 版本以及所使用的设置决定了这些元素。 有关更多信息,请参阅 自定义 IDE

先决条件

若要完成本演练,必须具有 Visual Studio。

创建 MFC 应用程序

  1. 使用 MFC 应用程序向导 创建 MFC 应用程序。 请参阅 指南:使用新的 MFC Shell 控件,了解如何在您的 Visual Studio 版本中打开向导。

  2. “名称 ”框中,键入 MFCAnimationWalkthrough。 单击 “确定”

  3. “MFC 应用程序向导” 对话框中,验证 应用程序类型 是否为 多个文档项目样式Visual Studio,并且已选择 “文档/视图体系结构支持 ”选项。 单击“完成”。

添加菜单,然后添加命令以启动和停止动画

  1. “视图 ”菜单上,指向 “其他 Windows ”,然后单击“ 资源视图”。

  2. “资源视图”中,导航到 “菜单” 文件夹并打开它。 双击 IDR_MFCAnimationWalkthroughTYPE 资源将其打开以供修改。

  3. 在菜单栏的“ 键入此处” 框中,键入 A&nimation 以创建动画菜单。

  4. “动画”下,在“ 键入此处” 框中,键入 “开始”和“转发 ”以创建“开始转发”命令。

  5. “开始向前”下,在 “键入此处” 框中,键入 “开始”和“向后”。

  6. 在“ 开始向后”下,在 “键入此处” 框中,键入 S&top 以创建 Stop 命令。

  7. 保存 MFCAnimationWalkthrough.rc 并关闭它。

  8. 解决方案资源管理器中,双击MainFrm.cpp将其打开以供修改。 在 CMainFrame::OnCreate 方法中,找到具有多次调用的 lstBasicCommands.AddTail节。 就在该部分之后,添加以下代码。

    lstBasicCommands.AddTail(ID_ANIMATION_STARTFORWARD);
    lstBasicCommands.AddTail(ID_ANIMATION_STARTBACKWARD);
    lstBasicCommands.AddTail(ID_ANIMATION_STOP);
    
  9. 保存文件并将其关闭。

为启动和停止命令创建处理程序

  1. “项目 ”菜单上,单击“ 类向导”。

  2. MFC 类向导“类名称”下,选择 CMFCAnimationWalkthroughView

  3. 在“ 命令 ”选项卡上的 “对象 ID ”框中,选择 “ID_ANIMATION_STARTFORWARD”,然后在“ 消息 ”框中选择 “COMMAND”。 单击“ 添加处理程序”。

  4. 在“ 添加成员函数 ”对话框中,单击“ 确定”。

  5. “对象 ID ”框中,选择 ID_ANIMATION_STARTBACKWARD,然后在 “消息 ”框中,选择 “命令”。 单击“ 添加处理程序”。

  6. 在“ 添加成员函数 ”对话框中,单击“ 确定”。

  7. “对象 ID ”框中,选择 ID_ANIMATION_STOP,然后在 “消息 ”框中选择 “COMMAND”。 单击 “添加处理程序 ”,然后单击“ 确定”。

  8. 在“ 添加成员函数 ”对话框中,单击“ 确定”。

  9. MFC 类向导中,单击“ 确定”。

  10. 保存在编辑器中打开的MFCAnimationWalkthroughView.cpp,但不关闭它。

向项目添加动画对象

  1. 解决方案资源管理器中,双击 MFCAnimationWalkthroughView.h 将其打开以供修改。 在类的定义 CMFCAnimationWalkthroughView 之前,添加以下代码以创建自定义动画控制器,该控制器将处理与动画对象的计划冲突。

    class CCustomAnimationController : public CAnimationController
    {
    public:
        CCustomAnimationController()
        {
        }
    
        virtual BOOL OnHasPriorityTrim(CAnimationGroup* pGroupScheduled,
            CAnimationGroup* pGroupNew,
            UI_ANIMATION_PRIORITY_EFFECT priorityEffect)
        {
            return TRUE;
        }
    };
    
  2. CMFCAnimationWalkthroughView 类的末尾,添加以下代码。

    CCustomAnimationController m_animationController;
    CAnimationColor m_animationColor;
    CAnimationRect m_animationRect;
    
  3. DECLARE_MESSAGE_MAP() 行后,添加以下代码。

    void Animate(BOOL bDirection);
    
  4. 保存文件并将其关闭。

  5. 在 MFCAnimationWalkthroughView.cpp,在 #include 语句之后的文件顶部,但在任何类方法之前,添加以下代码。

    static int nAnimationGroup = 0;
    static int nInfoAreaHeight = 40;
    
  6. 在构造函数 CMFCAnimationWalkthroughView的末尾,添加以下代码。

    m_animationController.EnableAnimationTimerEventHandler();
    m_animationController.EnablePriorityComparisonHandler(UI_ANIMATION_PHT_TRIM);
    m_animationColor = RGB(255, 255, 255);
    m_animationRect = CRect(0, 0, 0, 0);
    m_animationColor.SetID(-1, nAnimationGroup);
    m_animationRect.SetID(-1, nAnimationGroup);
    m_animationController.AddAnimationObject(&m_animationColor);
    m_animationController.AddAnimationObject(&m_animationRect);
    
  7. 找到该方法 CAnimationWalthroughView::PreCreateWindow ,然后将其替换为以下代码。

    BOOL CMFCAnimationWalkthroughView::PreCreateWindow(CREATESTRUCT& cs)
    {
        // TODO: Modify the Window class or styles here by modifying
        //       the CREATESTRUCT cs
        m_animationController.SetRelatedWnd(this);
    
        return CView::PreCreateWindow(cs);
    }
    
  8. 找到该方法 CAnimationWalkthroughView::OnDraw ,然后将其替换为以下代码。

    void CMFCAnimationWalkthroughView::OnDraw(CDC* pDC)
    {
        CMFCAnimationWalkthroughDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        if (!pDoc)
            return;
    
        // TODO: add draw code for native data here
        CMemDC dcMem(*pDC, this);
        CDC& dc = dcMem.GetDC();
        CRect rect;
        GetClientRect(rect);
    
        dc.FillSolidRect(rect, GetSysColor(COLOR_WINDOW));
    
        CString strRGB;
        strRGB.Format(_T("Fill Color is: %d; %d; %d"),
            GetRValue(m_animationColor),
            GetGValue(m_animationColor),
            GetBValue(m_animationColor));
    
        dc.DrawText(strRGB, rect, DT_CENTER);
        rect.top += nInfoAreaHeight;
    
        CBrush br;
        br.CreateSolidBrush(m_animationColor);
        CBrush* pBrushOld = dc.SelectObject(&br);
    
        dc.Rectangle((CRect)m_animationRect);
    
        dc.SelectObject(pBrushOld);
    }
    
  9. 在文件末尾,添加以下代码。

    void CMFCAnimationWalkthroughView::Animate(BOOL bDirection)
    {
        static UI_ANIMATION_SECONDS duration = 3;
        static DOUBLE dblSpeed = 35.;
        static BYTE nStartColor = 50;
        static BYTE nEndColor = 255;
    
        BYTE nRedColorFinal = bDirection ? nStartColor : nEndColor;
        BYTE nGreenColorFinal = bDirection ? nStartColor : nEndColor;
        BYTE nBlueColorFinal = bDirection ? nStartColor : nEndColor;
    
        CLinearTransition* pRedTransition =
            new CLinearTransition(duration, (DOUBLE)nRedColorFinal);
    
        CSmoothStopTransition* pGreenTransition =
            new CSmoothStopTransition(duration, (DOUBLE)nGreenColorFinal);
    
        CLinearTransitionFromSpeed* pBlueTransition =
            new CLinearTransitionFromSpeed(dblSpeed, (DOUBLE)nBlueColorFinal);
    
        m_animationColor.AddTransition(pRedTransition,
            pGreenTransition,
            pBlueTransition);
    
        CRect rectClient;
        GetClientRect(rectClient);
    
        rectClient.top += nInfoAreaHeight;
    
        int nLeftFinal = bDirection ? rectClient.left : rectClient.CenterPoint().x;
        int nTopFinal = bDirection ? rectClient.top : rectClient.CenterPoint().y;
        int nRightFinal = bDirection ? rectClient.right : rectClient.CenterPoint().x;
        int nBottomFinal = bDirection ? rectClient.bottom : rectClient.CenterPoint().y;
    
        CLinearTransition* pLeftTransition =
            new CLinearTransition(duration, nLeftFinal);
    
        CLinearTransition* pTopTransition =
            new CLinearTransition(duration, nTopFinal);
    
        CLinearTransition* pRightTransition =
            new CLinearTransition(duration, nRightFinal);
    
        CLinearTransition* pBottomTransition =
            new CLinearTransition(duration, nBottomFinal);
    
        m_animationRect.AddTransition(pLeftTransition,
            pTopTransition,
            pRightTransition,
            pBottomTransition);
    
        CBaseKeyFrame* pKeyframeStart =
            CAnimationController::GetKeyframeStoryboardStart();
        CKeyFrame* pKeyFrameEnd =
            m_animationController.CreateKeyframe(nAnimationGroup,
                pBlueTransition);
    
        pLeftTransition->SetKeyframes(pKeyframeStart, pKeyFrameEnd);
        pTopTransition->SetKeyframes(pKeyframeStart, pKeyFrameEnd);
        pRightTransition->SetKeyframes(pKeyframeStart, pKeyFrameEnd);
        pBottomTransition->SetKeyframes(pKeyframeStart, pKeyFrameEnd);
    
        m_animationController.AnimateGroup(nAnimationGroup);
    }
    
  10. “项目 ”菜单上,单击“ 类向导”。

  11. MFC 类向导“类名称”下,选择 CMFCAnimationWalkthroughView

  12. 在“ 消息 ”选项卡上的“ 消息 ”框中,选择 WM_ERASEBKGND,单击“ 添加处理程序”,然后单击“ 确定”。

  13. 在MFCAnimationWalkthroughView.cpp中,将实现替换为 OnEraseBkgnd 以下代码,以在重绘动画对象时减少动画对象中的闪烁。

    BOOL CMFCAnimationWalkthroughView::OnEraseBkgnd(CDC* /*pDC*/)
    {
        return TRUE;
    }
    
  14. > 的实现替换为以下代码。

    void CMFCAnimationWalkthroughView::OnAnimationStartforward()
    {
        Animate(TRUE);
    }
    
    void CMFCAnimationWalkthroughView::OnAnimationStartbackward()
    {
        Animate(FALSE);
    }
    
    void CMFCAnimationWalkthroughView::OnAnimationStop()
    {
        IUIAnimationManager* pManager = m_animationController.GetUIAnimationManager();
        if (pManager != NULL)
        {
            pManager->AbandonAllStoryboards();
    
        }
    }
    
  15. 保存文件并将其关闭。

在窗口中居中显示动画对象

  1. 解决方案资源管理器中,双击 MFCAnimationWalkthroughView.h 将其打开以供修改。 在 CMFCAnimationWalkthroughView 类的末尾,在定义 m_animationRect之后添加以下代码。

    BOOL m_bCurrentDirection;
    
  2. 保存文件并将其关闭。

  3. “项目 ”菜单上,单击“ 类向导”。

  4. MFC 类向导“类名称”下,选择 CMFCAnimationWalkthroughView

  5. 在“ 消息 ”选项卡上的“ 消息 ”框中,选择 WM_SIZE,单击“ 添加处理程序”,然后单击“ 确定”。

  6. 在MFCAnimationWalkthroughView.cpp中,将代码 CMFCAnimationWalkthroughView::OnSize 替换为以下代码。

    void CMFCAnimationWalkthroughView::OnSize(UINT nType, int cx, int cy)
    {
        CView::OnSize(nType, cx, cy);
        CRect rect;
        GetClientRect(rect);
    
        rect.top += nInfoAreaHeight;
    
        CRect rectAnim = m_animationRect;
        m_animationRect = CRect(CPoint(rect.CenterPoint().x - rectAnim.Width() / 2,
        rect.CenterPoint().y - rectAnim.Height() / 2),
        rectAnim.Size());
    
        if (m_animationController.IsAnimationInProgress())
        {
            Animate(m_bCurrentDirection);
        }
    }
    
  7. 在构造函数 CMFCAnimationWalkthroughView的开头,添加以下代码。

    m_bCurrentDirection = TRUE;
    
  8. CMFCAnimationWalkthroughView::Animate 方法的开头,添加以下代码。

    m_bCurrentDirection = bDirection;
    
  9. 保存文件并将其关闭。

验证结果

  1. 生成并运行应用程序。 在 “动画 ”菜单上,单击“ 开始前进”。 应显示一个矩形,然后填充中心区域。 单击“ 向后开始”时,动画应反转,单击“ 停止”时,动画应停止。 随着动画的进行,矩形的填充颜色应发生变化,当前颜色应显示在动画窗口顶部。

另请参阅

演练