今回も前回に引き続き、連載「ココが変わった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回で紹介したアプリケーションをそのまま利用しても面白みがないため、今回は簡単なデジタルフォトフレームをイメージした以下のようなアプリケーションを作成します。
はじめに、完成したアプリケーションの動作を示します(動画1)。
| 動画1 今回作成するサンプルアプリケーション |
本稿では、連載第2回で紹介していない内容を中心に解説していきますので、連載第2回の内容と併せてご覧ください。大まかな作業の流れは、以下のとおりです。
「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が背後から徐々に表示されるアニメーションを定義できました。ここまでの作業が完了したら、メニューの[ファイル]―[すべてを保存]を選択し、保存します。ちなみに、ここで紹介した平行移動や拡大縮小のほかにも、回転などいろいろな効果を追加できますので、ご自身でいろいろとアレンジしても面白いと思います。
今度は、アプリケーションの内部ロジックを実装します。
今回のアプリケーションでは、タイマを利用し、定期的に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.
よく読まれている編集記者コラム