Aggiornare Gestione animazioni e disegnare fotogrammi

Ogni volta che un'applicazione pianifica uno storyboard, l'applicazione deve fornire l'ora corrente al gestore animazioni. L'ora corrente è necessaria anche quando si indirizza la gestione animazioni per aggiornarne lo stato e impostare tutte le variabili di animazione sui valori interpolati appropriati.

Panoramica

Esistono due configurazioni supportate dall'animazione di Windows: animazione guidata dall'applicazione e animazione basata su timer.

Per usare l'animazione guidata dall'applicazione nell'applicazione, è necessario aggiornare la gestione animazioni prima di disegnare ogni fotogramma e usare un meccanismo appropriato per disegnare fotogrammi con frequenza sufficiente per l'animazione. Un'applicazione che usa un'animazione guidata dall'applicazione può usare qualsiasi meccanismo per determinare l'ora corrente, ma l'oggetto timer animazione Di Windows restituisce un tempo preciso nelle unità accettate dalla gestione animazioni. Per evitare il disegno non necessario quando non vengono riprodotte animazioni, devi anche fornire un gestore eventi di gestione per iniziare a ridisegnare quando le animazioni sono pianificate e controllare dopo ogni fotogramma se è possibile sospendere il ridisegno. Per altre informazioni, vedere Animazione guidata dall'applicazione.

Nella configurazione guidata dall'applicazione un'applicazione può chiamare il metodo IUIAnimationManager::GetStatus per verificare che le animazioni siano attualmente pianificate e continuare a disegnare fotogrammi, se sono. Poiché il ridisegno si interrompe quando non sono pianificate animazioni, è necessario riavviarlo alla successiva pianificazione di un'animazione. Un'applicazione può registrare un gestore eventi di gestione per ricevere una notifica quando lo stato della gestione animazioni passa da inattività (nessuna animazione è attualmente pianificata) a quella occupata.

Per usare l'animazione basata su timer nell'applicazione, devi connettere la gestione animazioni a un timer di animazione e fornire un gestore eventi timer. Quando la gestione animazioni è connessa a un timer, il timer può indicare al gestore quando lo stato dell'animazione deve essere aggiornato man mano che avanza il tempo. L'applicazione deve disegnare un frame per ogni tick timer. La gestione animazioni può a sua volta indicare al timer quando sono in riproduzione animazioni, in modo che il timer possa chiudersi durante i periodi di inattività quando il ridisegno non è necessario. Per evitare il disegno non necessario quando non vengono riprodotte animazioni, è necessario configurare il timer per disabilitarsi automaticamente. Per altre informazioni, vedere Animazione basata su timer.

Codice di esempio

animazione Application-Driven

Il codice di esempio seguente è tratto da ManagerEventHandler.h dagli esempi di animazione di Windows Animazione basata su applicazione e layout griglia. Definisce il gestore eventi di gestione.

#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;
    }

    ...

};

Il codice di esempio seguente è tratto da MainWindow.cpp dall'animazione basata su applicazioni di esempio di Windows; vedere CMainWindow::InitializeAnimation. Questo esempio crea un'istanza del gestore eventi di gestione usando il metodo CreateInstance e lo passa al gestore animazioni usando il metodo 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();
}

Poiché il gestore eventi manager mantiene un riferimento all'oggetto finestra principale, il gestore eventi di gestione deve essere cancellato (passando NULL a SetManagerEventHandler) o la gestione animazioni deve essere completamente rilasciata prima che la finestra principale venga eliminata definitivamente.

Il codice di esempio seguente è tratto da MainWindow.cpp nell'esempio animazione basata su applicazioni di Windows; vedere il metodo CMainWindow::OnPaint. Chiama il metodo IUIAnimationManager::GetTime per recuperare l'ora nelle unità richieste dal metodo 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
        );

    ...

}

Il codice di esempio seguente è tratto da MainWindow.cpp dagli esempi di animazione windows Animazione guidata da applicazioni e layout griglia; vedere il metodo CMainWindow::OnPaint. Si presuppone che l'applicazione usi un'API grafica che si sincronizza automaticamente con la frequenza di aggiornamento del monitoraggio (ad esempio Direct2D con le impostazioni predefinite), nel qual caso una chiamata alla funzione InvalidateRect è sufficiente per garantire che il codice di disegno venga chiamato di nuovo quando è il momento di disegnare il frame successivo. Invece di chiamare InvalidateRect in modo incondizionato, è preferibile verificare se sono ancora presenti animazioni pianificate usando 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
                );
        }
    }
}

animazione Timer-Driven

Il codice di esempio seguente è tratto da TimerEventHandler.h dall'animazione timer di esempio di animazione di Windows. Il codice di esempio definisce il gestore eventi timer, che invalida l'area client della finestra per causare un aggiornamento dopo ogni aggiornamento dello stato dell'animazione.

#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;
    }

    ...

};

Il codice di esempio seguente è tratto da MainWindow.cpp dall'animazione timer di esempio di animazione di Windows; vedere CMainWindow::InitializeAnimation. Questo esempio crea un'istanza del gestore eventi timer usando il metodo CreateInstance e lo passa al timer usando il metodo IUIAnimationTimer::SetTimerEventHandler . Poiché il gestore eventi timer mantiene un riferimento all'oggetto finestra principale, il gestore eventi timer deve essere cancellato (passando NULL a SetTimerEventHandler) o il timer completamente rilasciato prima che la finestra principale venga eliminata definitivamente.

// Create and set the timer event handler

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

Il codice di esempio seguente è tratto da MainWindow.cpp nell'esempio Animazione timer di Windows; vedere il metodo CMainWindow::InitializeAnimation. Chiama il metodo QueryInterface nell'oggetto di gestione animazioni per ottenere un puntatore a IUIAnimationTimerUpdateHandler, quindi connette gli oggetti UIAnimationManager e UIAnimationTimer impostando il gestore animazioni come gestore di aggiornamento del timer usando il metodo IUIAnimationTimer::SetTimerUpdateHandler . Si noti che non è necessario cancellare esplicitamente questa connessione; la connessione viene cancellata in modo sicuro dopo che l'applicazione rilascia sia la gestione animazioni che il timer di animazione.

// 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

        ...

    }
}

Se UI_ANIMATION_IDLE_BEHAVIOR_DISABLE non viene usato, è necessario anche abilitare il timer per avviarlo.

Passaggio precedente

Prima di iniziare questo passaggio, è necessario aver completato questo passaggio: Creare variabili di animazione.

passaggio successivo

Al termine di questo passaggio, il passaggio successivo è: Leggere i valori delle variabili di animazione.

IUIAnimationManager::GetStatus

IUIAnimationManager::SetManagerEventHandler

IUIAnimationManager::Update

IUIAnimationTimer::GetTime

IUIAnimationTimer::SetTimerUpdateHandler

UIAnimationManager

UIAnimationTimer

Panoramica dell'animazione di Windows