【番外編】スライドショーアプリ開発に挑戦!!ココが変わったWindows Embedded CE 6.0 R3(5)(1/2 ページ)

今回も前回に引き続き、連載「ココが変わったWindows Embedded CE 6.0 R3」の【番外編】として、ディジ インターナショナルの評価ボード「ConnectCore Wi-i.MX51」を使用し、このボード上で動作するアプリケーション開発の流れを紹介する。

» 2010年11月19日 00時00分 公開
[松井俊訓/監修:杉本拓也(富士通ソフトウェアテクノロジーズ),@IT MONOist]

 前回「【番外編】評価ボードを使って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)。

動画1 今回作成するサンプルアプリケーション

 本稿では、連載第2回で紹介していない内容を中心に解説していきますので、連載第2回の内容と併せてご覧ください。大まかな作業の流れは、以下のとおりです。

  1. Expression Blend2でXAMLファイル作成
  2. OSワークスペースにSilverlight for Windows Embeddedを追加
  3. Visual Studio 2005でWCEアプリケーションを作成
  4. OSランタイムへのリソースの追加
  5. ターゲットOS環境で実行

Expression Blend2を利用した作業/XAMLファイルの作成

コントロールの配置

 「Expression Blend2(以下、Blend2)」を利用し、XAMLファイルを作成します。まずは、「Silverlight 2アプリケーション」の「新しいプロジェクト」を作成します。プロジェクトの名前は任意で構いません(画像1)。

「新しいプロジェクト」の作成 画像1 「新しいプロジェクト」の作成

 ConnectCore Wi-i.MX51用のBSPのデフォルトの解像度に合わせ、ベースウィンドウとなる「UserControl」のレイアウトプロパティのWidthを「800」に、Heightを「480」にします(画像2)。

「UserControl」のレイアウト 画像2 「UserControl」のレイアウト

 背景の色を好きな色に変更します。ここでは黒色に設定しました(任意の画像ファイルを張り付けてもよいでしょう)。

 スライドショーで画像ファイルを表示する領域(「Image」コントロール)を追加します。ツールボックスから「アセットライブラリ」を選択します。「すべてを表示」チェックボックスにチェックを入れ、コントロール一覧からImageを選択します。Imageコントロールのプロパティの名前を「Image1」とし、Widthを「400」、Heightを「300」に設定します(画像3)。そして、共通プロパティのSourceを「windows\default.png」とし、Imageコントロールを中央に配置します。

「Image」コントロールのレイアウト 画像3 「Image」コントロールのレイアウト

 もう1つImageコントロールを追加します。このImageコントロールは、スライドショーのアニメーションで“次の画像を表示する領域”として使います。プロパティの名前を「Image2」とし、Width/Heightおよび配置位置を先ほどのImage1と同じ設定にします。共通プロパティのSourceも同様に「windows\default.png」を設定します。

 最後にImage1を選択し、右クリックメニューから[順序]―[最前面に移動]を選択します。これでコントロールの配置は完了です。

ストーリーボードの設定

 続いて、スライドショーのアニメーションを定義します。ストーリーボードを新規追加します。名前はデフォルトの「Storyboard1」で構いません。

「Storyboard リソースの作成」 画像4 「Storyboard リソースの作成」

 今回作成するアプリケーションのアニメーションのイメージは以下のとおりです。

まず、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%」に設定してください。

Storyboardの設定 画像5 Storyboardの設定

 以上で、次の画像を表示する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

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.