アニメーション マネージャと描画フレームを更新する
アプリケーションがストーリーボードをスケジュールするたびに、アプリケーションはアニメーション マネージャーに現在の時刻を指定する必要があります。 アニメーション マネージャーが状態を更新し、すべてのアニメーション変数を適切な補間値に設定するように指示する場合も、現在の時刻が必要です。
概要
Windows アニメーションでサポートされる構成には、アプリケーション駆動型アニメーションとタイマー駆動型アニメーションの 2 つがあります。
アプリケーション駆動型アニメーションをアプリケーションで使用するには、各フレームを描画する前にアニメーション マネージャーを更新し、適切なメカニズムを使用してアニメーションに十分な頻度でフレームを描画する必要があります。 アプリケーション駆動型アニメーションを使用するアプリケーションでは、任意のメカニズムを使用して現在の時刻を判断できますが、Windows アニメーション タイマー オブジェクトは、アニメーション マネージャーが受け入れる単位で正確な時刻を返します。 アニメーションが再生されていないときに不要な描画を回避するには、アニメーションがスケジュールされたときに再描画を開始し、再描画を中断できるかどうかを各フレームの後にチェックするマネージャー イベント ハンドラーも用意する必要があります。 詳細については、「 アプリケーション駆動型アニメーション」を参照してください。
アプリケーション駆動型構成では、アプリケーションは IUIAnimationManager::GetStatus メソッドを呼び出して、アニメーションが現在スケジュールされていることを確認し、フレームがスケジュールされている場合は引き続きフレームを描画することを確認できます。 アニメーションがスケジュールされていない場合は再描画が停止するため、次回アニメーションがスケジュールされたときに再起動する必要があります。 アプリケーションは、アニメーション マネージャーの状態がアイドル状態 (現在スケジュールされていないアニメーション) からビジー状態に変わるときに通知を受け取るマネージャー イベント ハンドラーを登録できます。
アプリケーションでタイマー駆動型アニメーションを使用するには、アニメーション マネージャーをアニメーション タイマーに接続し、タイマー イベント ハンドラーを提供する必要があります。 アニメーション マネージャーがタイマーに接続されている場合、タイマーは、時間の経過に応じてアニメーションの状態を更新するタイミングをマネージャーに通知できます。 アプリケーションでは、タイマー ティックごとにフレームを描画する必要があります。 アニメーション マネージャーは、再生中のアニメーションがある場合にタイマーを通知できるため、再描画が不要なアイドル期間中にタイマーがオフになる可能性があります。 アニメーションが再生されていないときに不要な描画を回避するには、自動的に無効にするようにタイマーを構成する必要があります。 詳細については、「 タイマー駆動型アニメーション」を参照してください。
コード例
アニメーションのApplication-Driven
次のコード例は、Windows アニメーションサンプル アプリケーション駆動型アニメーション と グリッド レイアウトから ManagerEventHandler.h から取得されています。 マネージャー イベント ハンドラーを定義します。
#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;
}
...
};
次のコード例は、Windows アニメーション サンプル アプリケーション駆動型アニメーションから MainWindow.cpp から取得されています。CMainWindow::InitializeAnimation を参照してください。 この例では、 CreateInstance メソッドを使用してマネージャー イベント ハンドラーのインスタンスを作成し、 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();
}
マネージャー イベント ハンドラーはメイン ウィンドウ オブジェクトへの参照を保持するため、マネージャー イベント ハンドラーをクリアするか (SetManagerEventHandler に NULL を渡すことによって)、メイン ウィンドウが破棄される前にアニメーション マネージャーを完全に解放する必要があります。
次のコード例は、Windows アニメーション のサンプル アプリケーション駆動型アニメーションの MainWindow.cpp から取得したものです。CMainWindow::OnPaint メソッドを参照してください。 IUIAnimationManager::GetTime メソッドを呼び出して、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
);
...
}
次のコード例は、Windows アニメーション のサンプル アプリケーション 駆動型アニメーション と グリッド レイアウトから MainWindow.cpp から取得されています。CMainWindow::OnPaint メソッドを参照してください。 アプリケーションは、モニターの更新レート (Direct2D とその既定の設定など) に自動的に同期するグラフィックス API を使用していることを前提としています。この場合、 InvalidateRect 関数の呼び出しは、次のフレームを描画するときに描画コードが再度呼び出されるようにするのに十分です。 InvalidateRect を無条件に呼び出すのではなく、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
);
}
}
}
アニメーションのTimer-Driven
次のコード例は、Windows アニメーション のサンプル タイマー 駆動型アニメーションの TimerEventHandler.h から取得したものです。 このコード例では、タイマー イベント ハンドラーを定義します。これにより、ウィンドウのクライアント領域が無効になり、アニメーション状態が更新されるたびに再描画が行われます。
#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;
}
...
};
次のコード例は、Windows アニメーションサンプル のタイマー駆動型アニメーションから MainWindow.cpp から取得されています。CMainWindow::InitializeAnimation を参照してください。 この例では、 CreateInstance メソッドを使用してタイマー イベント ハンドラーのインスタンスを作成し、 IUIAnimationTimer::SetTimerEventHandler メソッドを使用してタイマーに渡します。 タイマー イベント ハンドラーはメイン ウィンドウ オブジェクトへの参照を保持するため、タイマー イベント ハンドラーをクリアするか (SetTimerEventHandler に NULL を渡すことによって)、またはメイン ウィンドウが破棄される前に完全に解放されるタイマーをクリアする必要があります。
// Create and set the timer event handler
IUIAnimationTimerEventHandler *pTimerEventHandler;
hr = CTimerEventHandler::CreateInstance(
this,
&pTimerEventHandler
);
if (SUCCEEDED(hr))
{
hr = m_pAnimationTimer->SetTimerEventHandler(
pTimerEventHandler
);
pTimerEventHandler->Release();
}
次のコード例は、Windows アニメーション のサンプル タイマー駆動型アニメーションの MainWindow.cpp から取得されています。CMainWindow::InitializeAnimation メソッドを参照してください。 アニメーション マネージャー オブジェクトの QueryInterface メソッドを呼び出して IUIAnimationTimerUpdateHandler へのポインターを取得し、IUIAnimationTimer::SetTimerUpdateHandler メソッドを使用してタイマーの更新ハンドラーとしてアニメーション マネージャーを設定することで、UIAnimationManager オブジェクトと UIAnimationTimer オブジェクトを接続します。 この接続を明示的にクリアする必要はありません。アプリケーションがアニメーション マネージャーとアニメーション タイマーの両方を解放した後、接続は安全にクリアされます。
// 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
...
}
}
UI_ANIMATION_IDLE_BEHAVIOR_DISABLEが使用されていない場合は、タイマーを有効にしてティックを開始する必要もあります。
前の手順
この手順を開始する前に、 アニメーション変数の作成に関する手順を完了しておく必要があります。
次の手順
この手順を完了した後の次の手順は、 アニメーション変数の値の読み取りです。
関連トピック