Partager via


Mettre à jour le gestionnaire d’animations et les images de dessin

Chaque fois qu’une application planifie un storyboard, l’application doit fournir l’heure actuelle au gestionnaire d’animations. L’heure actuelle est également requise lorsque le gestionnaire d’animations doit mettre à jour son état et définir toutes les variables d’animation sur les valeurs interpolées appropriées.

Vue d’ensemble

Il existe deux configurations prises en charge par l’animation Windows : l’animation pilotée par l’application et l’animation pilotée par le minuteur.

Pour utiliser l’animation pilotée par l’application dans votre application, vous devez mettre à jour le gestionnaire d’animations avant de dessiner chaque image et utiliser un mécanisme approprié pour dessiner des images suffisamment fréquemment pour l’animation. Une application utilisant une animation pilotée par l’application peut utiliser n’importe quel mécanisme pour déterminer l’heure actuelle, mais l’objet du minuteur d’animation Windows retourne une heure précise dans les unités acceptées par le gestionnaire d’animations. Pour éviter le dessin inutile quand aucune animation n’est en cours de lecture, vous devez également fournir un gestionnaire d’événements pour commencer à redessiner lorsque les animations sont planifiées et case activée après chaque image si le redécoupage peut être suspendu. Pour plus d’informations, consultez Animation pilotée par les applications.

Dans la configuration pilotée par l’application, une application peut appeler la méthode IUIAnimationManager::GetStatus pour vérifier que les animations sont actuellement planifiées et continuent à dessiner des images si elles le sont. Étant donné que le redécoupage s’arrête lorsqu’aucune animation n’est planifiée, il est nécessaire de le redémarrer la prochaine fois qu’une animation est planifiée. Une application peut inscrire un gestionnaire d’événements pour être averti lorsque le status du gestionnaire d’animations passe d’inactif (aucune animation n’est actuellement planifiée) à occupé.

Pour utiliser l’animation pilotée par le minuteur dans votre application, vous devez connecter le gestionnaire d’animations à un minuteur d’animation et fournir un gestionnaire d’événements du minuteur. Lorsque le gestionnaire d’animations est connecté à un minuteur, le minuteur peut indiquer au gestionnaire quand l’état de l’animation doit être mis à jour au fur et à mesure que le temps avance. L’application doit dessiner une trame pour chaque coche du minuteur. Le gestionnaire d’animations peut à son tour indiquer au minuteur quand des animations sont en cours de lecture, de sorte que le minuteur peut s’arrêter pendant les périodes d’inactivité lorsque le redessinage n’est pas nécessaire. Pour éviter un dessin inutile quand aucune animation n’est en cours de lecture, vous devez configurer le minuteur pour qu’il se désactive automatiquement. Pour plus d’informations, consultez Animation pilotée par le minuteur.

Exemple de code

animation Application-Driven

L’exemple de code suivant est extrait de ManagerEventHandler.h à partir des exemples d’animation Windows pilotée par l’application et de disposition de grille. Il définit le gestionnaire d’événements.

#include "UIAnimationHelper.h"

// Event handler object for manager status changes

class CManagerEventHandler :
    public CUIAnimationManagerEventHandlerBase<CManagerEventHandler>
{
public:

    static HRESULT
    CreateInstance
    (
        CMainWindow *pMainWindow,
        IUIAnimationManagerEventHandler **ppManagerEventHandler
    ) throw()
    {
        CManagerEventHandler *pManagerEventHandler;
        HRESULT hr = CUIAnimationCallbackBase::CreateInstance(
            ppManagerEventHandler,
            &pManagerEventHandler
            );
        if (SUCCEEDED(hr))
        {
            pManagerEventHandler->m_pMainWindow = pMainWindow;
        }
        
        return hr;
    }

    // IUIAnimationManagerEventHandler

    IFACEMETHODIMP
    OnManagerStatusChanged
    (
        UI_ANIMATION_MANAGER_STATUS newStatus,
        UI_ANIMATION_MANAGER_STATUS previousStatus
    )
    {
        HRESULT hr = S_OK;

        if (newStatus == UI_ANIMATION_MANAGER_BUSY)
        {
            hr = m_pMainWindow->Invalidate();
        }

        return hr;
    }

    ...

};

L’exemple de code suivant est extrait de MainWindow.cpp à partir de l’exemple d’animation pilotée par l’application d’animation Windows ; consultez CMainWindow::InitializeAnimation. Cet exemple crée une instance du gestionnaire d’événements à l’aide de la méthode CreateInstance et la transmet au gestionnaire d’animations à l’aide de la méthode IUIAnimationManager::SetManagerEventHandler.

// Create and set the ManagerEventHandler to start updating when animations are scheduled

IUIAnimationManagerEventHandler *pManagerEventHandler;
HRESULT hr = CManagerEventHandler::CreateInstance(
    this,
    &pManagerEventHandler
    );
if (SUCCEEDED(hr))
{
    hr = m_pAnimationManager->SetManagerEventHandler(
        pManagerEventHandler
        );
    pManagerEventHandler->Release();
}

Étant donné que le gestionnaire d’événements conserve une référence à l’objet window main, le gestionnaire d’événements du gestionnaire doit être effacé (en passant la valeur NULL à SetManagerEventHandler) ou le gestionnaire d’animation doit être complètement libéré avant la destruction de la fenêtre main.

L’exemple de code suivant est tiré de MainWindow.cpp dans l’exemple d’animation windows pilotée par les applications ; consultez la méthode CMainWindow::OnPaint. Il appelle la méthode IUIAnimationManager::GetTime pour récupérer le temps dans les unités requises par la méthode IUIAnimationManager::Update .

// Update the animation manager with the current time

UI_ANIMATION_SECONDS secondsNow;
HRESULT hr = m_pAnimationTimer->GetTime(
    &secondsNow
    );

if (SUCCEEDED(hr))
{
    hr = m_pAnimationManager->Update(
        secondsNow
        );

    ...

}

L’exemple de code suivant est extrait de MainWindow.cpp à partir des exemples d’animation Windows pilotée par l’application et de disposition de grille ; consultez la méthode CMainWindow::OnPaint. Il suppose que l’application utilise une API graphique qui se synchronise automatiquement avec le taux d’actualisation du moniteur (par exemple Direct2D avec ses paramètres par défaut), auquel cas un appel à la fonction InvalidateRect suffit pour garantir que le code de peinture sera appelé à nouveau au moment de dessiner l’image suivante. Plutôt que d’appeler InvalidateRect de manière inconditionnelle, il est préférable de case activée s’il existe encore des animations planifiées à l’aide de GetStatus.

// Read the values of the animation variables and draw the client area

hr = DrawClientArea();
if (SUCCEEDED(hr))
{          
    // Continue redrawing the client area as long as there are animations scheduled
    UI_ANIMATION_MANAGER_STATUS status;
    hr = m_pAnimationManager->GetStatus(
        &status
        );
    if (SUCCEEDED(hr))
    {
        if (status == UI_ANIMATION_MANAGER_BUSY)
        {
            InvalidateRect(
                m_hwnd,
                NULL,
                FALSE
                );
        }
    }
}

animation Timer-Driven

L’exemple de code suivant est extrait de TimerEventHandler.h de l’exemple d’animation windows pilotée par le minuteur. L’exemple de code définit le gestionnaire d’événements du minuteur, qui invalide la zone cliente de la fenêtre pour provoquer un repeint après chaque mise à jour de l’état de l’animation.

#include "UIAnimationHelper.h"

// Event handler object for timer events

class CTimerEventHandler :
    public CUIAnimationTimerEventHandlerBase<CTimerEventHandler>
{
public:

    static HRESULT
    CreateInstance
    (
        CMainWindow *pMainWindow,
        IUIAnimationTimerEventHandler **ppTimerEventHandler
    ) throw()
    {
        CTimerEventHandler *pTimerEventHandler;
        HRESULT hr = CUIAnimationCallbackBase::CreateInstance(
            ppTimerEventHandler,
            &pTimerEventHandler
            );

        if (SUCCEEDED(hr))
        {
            pTimerEventHandler->m_pMainWindow = pMainWindow;
        }
        
        return hr;
    }

    // IUIAnimationTimerEventHandler

    IFACEMETHODIMP
    OnPreUpdate()
    {
        return S_OK;
    }

    IFACEMETHODIMP
    OnPostUpdate()
    {
        HRESULT hr = m_pMainWindow->Invalidate();

        return hr;
    }

    IFACEMETHODIMP
    OnRenderingTooSlow
    (
        UINT32 /* fps */
    )
    {
        return S_OK;
    }

    ...

};

L’exemple de code suivant est tiré de MainWindow.cpp à partir de l’exemple d’animation windows pilotée par le minuteur ; consultez CMainWindow::InitializeAnimation. Cet exemple crée une instance du gestionnaire d’événements du minuteur à l’aide de la méthode CreateInstance et la transmet au minuteur à l’aide de la méthode IUIAnimationTimer::SetTimerEventHandler. Étant donné que le gestionnaire d’événements du minuteur conserve une référence à l’objet window main, le gestionnaire d’événements du minuteur doit être effacé (en transmettant NULL à SetTimerEventHandler) ou le minuteur complètement libéré avant la destruction de la fenêtre main.

// Create and set the timer event handler

IUIAnimationTimerEventHandler *pTimerEventHandler;
hr = CTimerEventHandler::CreateInstance(
    this,
    &pTimerEventHandler
    );
if (SUCCEEDED(hr))
{
    hr = m_pAnimationTimer->SetTimerEventHandler(
        pTimerEventHandler
        );
    pTimerEventHandler->Release();
}

L’exemple de code suivant est tiré de MainWindow.cpp dans l’exemple d’animation Windows pilotée par le minuteur ; consultez la méthode CMainWindow::InitializeAnimation. Il appelle la méthode QueryInterface sur l’objet du gestionnaire d’animation pour obtenir un pointeur vers IUIAnimationTimerUpdateHandler, puis connecte les objets UIAnimationManager et UIAnimationTimer en définissant le gestionnaire d’animation comme gestionnaire de mises à jour du minuteur à l’aide de la méthode IUIAnimationTimer::SetTimerUpdateHandler . Notez qu’il n’est pas nécessaire d’effacer explicitement cette connexion ; la connexion est effacée en toute sécurité une fois que l’application a libéré à la fois le gestionnaire d’animation et le minuteur d’animation.

// Connect the animation manager to the timer

IUIAnimationTimerUpdateHandler *pTimerUpdateHandler;
hr = m_pAnimationManager->QueryInterface(
    IID_PPV_ARGS(&pTimerUpdateHandler)
    );

if (SUCCEEDED(hr))
{
    hr = m_pAnimationTimer->SetTimerUpdateHandler(
        pTimerUpdateHandler
        UI_ANIMATION_IDLE_BEHAVIOR_DISABLE  // timer will shut itself off when there are no animations playing
        );
    pTimerUpdateHandler->Release();
    if (SUCCEEDED(hr))
    {
        // Create and set the timer event handler

        ...

    }
}

Si UI_ANIMATION_IDLE_BEHAVIOR_DISABLE n’est pas utilisé, il est également nécessaire d’activer le minuteur pour qu’il commence à cocher.

Étape précédente

Avant de commencer cette étape, vous devez avoir terminé cette étape : Créer des variables d’animation.

étape suivante

Une fois cette étape terminée, l’étape suivante est : Lire les valeurs des variables d’animation.

IUIAnimationManager::GetStatus

IUIAnimationManager::SetManagerEventHandler

IUIAnimationManager::Update

IUIAnimationTimer::GetTime

IUIAnimationTimer::SetTimerUpdateHandler

UIAnimationManager

UIAnimationTimer

Vue d’ensemble de l’animation Windows