【番外編】スライドショーアプリ開発に挑戦!!:ココが変わったWindows Embedded CE 6.0 R3(5)(1/2 ページ)
今回も前回に引き続き、連載「ココが変わったWindows Embedded CE 6.0 R3」の【番外編】として、ディジ インターナショナルの評価ボード「ConnectCore Wi-i.MX51」を使用し、このボード上で動作するアプリケーション開発の流れを紹介する。
前回「【番外編】評価ボードを使ってCE 6.0 R3を体験しよう」では、ディジ インターナショナルの評価ボード「ConnectCore Wi-i.MX51」を利用し、Windows Embedded CE 6.0 R3(以下、CE 6.0 R3)が起動するまでの流れを解説しました。
今回は、番外編の続きということで、連載第2回「Silverlight for Windows Embeddedの実装方法」で解説した「Silverlight for Windows Embedded」の機能を利用したアプリケーションを開発し、ConnectCore Wi-i.MX51上で実行してみたいと思います。
単に連載第2回で紹介したアプリケーションをそのまま利用しても面白みがないため、今回は簡単なデジタルフォトフレームをイメージした以下のようなアプリケーションを作成します。
- 画像ファイルをスライドショー再生する
- SDメモリに保存されている画像ファイルを順番に再生する
- アニメーション効果を利用し、画像を順番に表示する
はじめに、完成したアプリケーションの動作を示します(動画1)。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
本稿では、連載第2回で紹介していない内容を中心に解説していきますので、連載第2回の内容と併せてご覧ください。大まかな作業の流れは、以下のとおりです。
- Expression Blend2でXAMLファイル作成
- OSワークスペースにSilverlight for Windows Embeddedを追加
- Visual Studio 2005でWCEアプリケーションを作成
- OSランタイムへのリソースの追加
- ターゲットOS環境で実行
Expression Blend2を利用した作業/XAMLファイルの作成
コントロールの配置
「Expression Blend2(以下、Blend2)」を利用し、XAMLファイルを作成します。まずは、「Silverlight 2アプリケーション」の「新しいプロジェクト」を作成します。プロジェクトの名前は任意で構いません(画像1)。
ConnectCore Wi-i.MX51用のBSPのデフォルトの解像度に合わせ、ベースウィンドウとなる「UserControl」のレイアウトプロパティのWidthを「800」に、Heightを「480」にします(画像2)。
背景の色を好きな色に変更します。ここでは黒色に設定しました(任意の画像ファイルを張り付けてもよいでしょう)。
スライドショーで画像ファイルを表示する領域(「Image」コントロール)を追加します。ツールボックスから「アセットライブラリ」を選択します。「すべてを表示」チェックボックスにチェックを入れ、コントロール一覧からImageを選択します。Imageコントロールのプロパティの名前を「Image1」とし、Widthを「400」、Heightを「300」に設定します(画像3)。そして、共通プロパティのSourceを「windows\default.png」とし、Imageコントロールを中央に配置します。
もう1つImageコントロールを追加します。このImageコントロールは、スライドショーのアニメーションで“次の画像を表示する領域”として使います。プロパティの名前を「Image2」とし、Width/Heightおよび配置位置を先ほどのImage1と同じ設定にします。共通プロパティのSourceも同様に「windows\default.png」を設定します。
最後にImage1を選択し、右クリックメニューから[順序]―[最前面に移動]を選択します。これでコントロールの配置は完了です。
ストーリーボードの設定
続いて、スライドショーのアニメーションを定義します。ストーリーボードを新規追加します。名前はデフォルトの「Storyboard1」で構いません。
今回作成するアプリケーションのアニメーションのイメージは以下のとおりです。
まず、Image1に現在表示している画像ファイルを表示します。このとき、Image2には何も表示しません。そして、Image1が縮小&移動しながら消えていき、次の画像を表示するImage2が背後から徐々に表示されます。
それでは、Blend2の「オブジェクトとタイムライン」ビュー上で、アニメーションを定義していきます。
前述のとおり、Image2には次の画像を表示しますので、アニメーション開始から1秒間は非表示にしておきます。タイムラインの0秒の位置でImage2を選択し、Opacity(不透過率)を「0%」に、Visibilityを「Collapsed」に設定します。
次に、タイムラインの0.5秒の位置までスライドし、Image1を選択します。Image1の「プロパティ」タブを選択し、「変換」の「平行移動」タブを選択し、Xを「−300」に設定します。同じく「変換」の「拡大縮小」タブを選択し、Xを「0」に、Yを「0.75」にします。
さらに、タイムラインの1秒の位置までスライドし、Image1を選択します。「変換」の「平行移動」タブを選択し、Xを「0」に設定します。同じく「変換」の「拡大縮小」タブを選択し、Xを「−0.5」に、Yを「0.5」に設定します。Opacityは「0%」に設定します。そして、Image2を選択します。「変換」の「拡大縮小」タブを選択し、Xを「−0.5」に、Yを「0.5」に、Visibilityを「Visible」に設定します。
ここまでの作業で、現在表示している画像(Image1)が縮小&移動しながら消えていく流れを定義できました。
次に、タイムラインの1.5秒の位置までスライドし、Image2を選択します。「変換」の「平行移動」タブを選択し、Xを「300」に設定します。同じく「変換」の「拡大縮小」タブを選択し、Xを「0」に、Yを「0.75」に設定します。Opacityは「100%」に設定してください。
続いて、タイムラインの2秒の位置までスライドし、Image2を選択します。「変換」の「平行移動」タブを選択し、Xを「0」に設定します。同じく「変換」の「拡大縮小」タブを選択し、Xを「1」に、Yを「1」に設定します。Opacityは「100%」に設定してください。
以上で、次の画像を表示するImage2が背後から徐々に表示されるアニメーションを定義できました。ここまでの作業が完了したら、メニューの[ファイル]―[すべてを保存]を選択し、保存します。ちなみに、ここで紹介した平行移動や拡大縮小のほかにも、回転などいろいろな効果を追加できますので、ご自身でいろいろとアレンジしても面白いと思います。
Visual Studio 2005を利用した作業
サブプロジェクトの作成
今度は、アプリケーションの内部ロジックを実装します。
今回のアプリケーションでは、タイマを利用し、定期的にSDメモリ内の画像ファイルを順番に読み込み、XAMLファイル内に追加したImage1およびImage2コントロールに画像を描画し、先ほど定義したストーリーボードを再生します。
ここでは、前回作成したプロジェクトを利用します。作成方法は連載第2回の「3. Visual Studio 2005でWCEアプリケーションを作成」を参照してください。なお、サブプロジェクト名は「SlideShow」とします。「自動生成されたサブプロジェクトファイル」では、「シンプルなWindows Embedded CEアプリケーション」を選択します。
以下のサンプルコード1を「SlideShow.cpp」ファイルに実装します(なお、実装のポイントについては以降で解説します)。
#include "stdafx.h" #include "pwinuser.h" #include "xamlruntime.h" #include "xrdelegate.h" #include "xrptr.h" #define NUM_TIMER_ID 1 IXRVisualHostPtr g_vhost; IXRImagePtr g_btnImage1; IXRImagePtr g_btnImage2; IXRStoryboardPtr g_pStoryboard1; TCHAR g_szCurrentFileName[MAX_PATH]; UINT g_nTimer; BOOL GetNextFileName(TCHAR* pszCurrentFileName, TCHAR *pszNextFileName) { HANDLE hFind; WIN32_FIND_DATA FindFileData; TCHAR szSearch[MAX_PATH]; ZeroMemory( &FindFileData, sizeof( FindFileData ) ); ZeroMemory( szSearch, MAX_PATH*sizeof(TCHAR) ); _tcscpy(szSearch, TEXT("\\SDMemory\\*.png")); hFind = FindFirstFile( szSearch, &FindFileData ); if ( hFind == INVALID_HANDLE_VALUE ) { return false; } _tcscpy(pszNextFileName, FindFileData.cFileName); do { if(0 == _tcscmp(FindFileData.cFileName, pszCurrentFileName)) { if(FindNextFile( hFind, &FindFileData)) { _tcscpy(pszNextFileName, FindFileData.cFileName); } break; } } while( FindNextFile( hFind, &FindFileData) ); FindClose( hFind ); return TRUE; } BOOL CALLBACK HostHookProc(VOID* pv, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* pRetVal) { ULONG ulStyle; switch(msg) { case WM_CREATE: ulStyle = ::GetWindowLong(hwnd, GWL_STYLE); ulStyle = ulStyle & ~ulStyle; ::SetWindowLong(hwnd, GWL_STYLE, ulStyle); g_nTimer = ::SetTimer(hwnd, NUM_TIMER_ID, 6000, NULL); case WM_TIMER: if (wParam == NUM_TIMER_ID) { HRESULT result; IXRBitmapImagePtr pBitmapImage1; IXRBitmapImagePtr pBitmapImage2; TCHAR szNextFileName[MAX_PATH]; TCHAR szNextFilePath[MAX_PATH]; ZeroMemory( szNextFileName, MAX_PATH*sizeof(TCHAR) ); ZeroMemory( szNextFilePath, MAX_PATH*sizeof(TCHAR) ); GetNextFileName(g_szCurrentFileName, szNextFileName); _tcscpy(szNextFilePath, TEXT("\\SDMemory\\")); _tcscat(szNextFilePath, szNextFileName); _tcscpy(g_szCurrentFileName, szNextFileName); if(FAILED(result=g_btnImage1->GetSource(&pBitmapImage1))) { return S_OK; } if(FAILED(result=g_btnImage2->GetSource(&pBitmapImage2))) { return S_OK; } BSTR bstrImageName; pBitmapImage2->GetUriSource(&bstrImageName); if(FAILED(result=pBitmapImage1->SetUriSource(bstrImageName))) { return S_OK; } if(FAILED(result=pBitmapImage2->SetUriSource(szNextFilePath))) { return S_OK; } g_pStoryboard1->Begin(); } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HRESULT retcode; IXRApplicationPtr app; ZeroMemory(g_szCurrentFileName, sizeof(g_szCurrentFileName)); if(!XamlRuntimeInitialize()) return -1; if(FAILED(retcode=GetXRApplicationInstance(&app))) return -1; if(FAILED(retcode=app->AddResourceModule(hInstance))) return -1; XRWindowCreateParams wp; ZeroMemory(&wp, sizeof(XRWindowCreateParams)); wp.Style = WS_OVERLAPPED; wp.pTitle = TEXT("SlideShow"); wp.Left = 0; wp.pHookProc = HostHookProc; XRXamlSource xamlsrc; xamlsrc.SetFile(TEXT("\\Windows\\Page.xaml")); if(FAILED(retcode=app->CreateHostFromXaml(&xamlsrc, &wp, &g_vhost))) { return -1; } IXRFrameworkElementPtr root; if(FAILED(retcode=g_vhost->GetRootElement(&root))) { return -1; } if(FAILED(retcode=root->FindName(TEXT("Image1"), &g_btnImage1))) { return -1; } if(FAILED(retcode=root->FindName(TEXT("Image2"), &g_btnImage2))) { return -1; } if(FAILED(retcode=root->FindName(TEXT("Storyboard1"), &g_pStoryboard1))) { return -1; } UINT exitcode; if(FAILED(retcode=g_vhost->StartDialog(&exitcode))) { return -1; } XamlRuntimeUninitialize(); return 0; }
サンプルコード1 |
Copyright © ITmedia, Inc. All Rights Reserved.