パノラマページを作成する(後編)

2011年7月22日(金)
PROJECT KySS

ソリューションエクスプローラー内のseiSong.xamlを展開し、表示されるseiSong.xaml.vbをダブルクリックしてリスト2のロジックコードを記述します。

リスト2 曲を再生する処理 (seiSong.xaml.vb)

Option Strict On
Imports System.Xml.Linq

タイマーの機能を提供するクラスの含まれる、System.Windows.Threading名前空間をインポートしておきます。
Imports System.Windows.Threading

画像を表示するのに必要な機能の含まれる、System.Windows.Media.Imaging名前空間をインポートしておきます。
Imports System.Windows.Media.Imaging
Partial Public Class seiSong
  Inherits PhoneApplicationPage

~コード略~

タイマーを表すDispatcherTimerクラスのインスタンスdtオブジェクトを、メンバ変数として宣言します。
  Dim dt As New DispatcherTimer
  Dim no As Boolean = False

ReadXmldocクラスのインスタンスmyReadXmldocオブジェクトをメンバ変数として宣言します。
  Dim myReadXmldoc As New ReadXmldoc

■画面の遷移で移動した時に最初に呼ばれるイベント
ここで、MainPage.xamlから渡された文字データを受け取ります。文字データはNavigationContextのQueryStringにDictionary として提供されます。送信時のキーワード(この場合Index)を基に渡された文字列情報を、myParam(“Index”)として取得します。
myParam(“Index”)の値を数値に変換して、変数Indexに格納します。
ReadXmldocクラスのインスタンスmyReadXmldocでseiSong関数を呼び出します。Descendantsメソッドで、変数Indexに該当する<Music>要素の値を取得し、変数myTitleに格納します。
同じく、変数Indexに該当する<Music>要素の属性”Uri”の値を取得し、変数mySongに格納します。
x:NameがPageTitleというTextBlockにmyTitleの値を表示します。曲名が表示されます。
MediaElementのSourceプロパティに絶対URIとして、変数mySongの値を指定します。前編のリスト1の、SeiMusic.xmlの”Uri”属性に記述されたアドレスにアクセスします。
Volumeプロパティの値に1を指定します。Volumeプロパティには0~1の値を指定できます。規定値は0.5です。
変数Indexに該当する<Music>要素の属性”Image”値を取得し、変数imageNameに格納します。
ImageのSourceプロパティに、画像を置いてあるImageフォルダーを連結したimageNameの値を相対URIで指定します。
  Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
    Dim myParam As IDictionary(Of String, String) = NavigationContext.QueryString
    Dim Index As Integer = Integer.Parse(myParam("Index"))
    Dim myTitle As String = myReadXmldoc.seiSong.Descendants("Music")(Index).Value
    Dim mySong As String = myReadXmldoc.seiSong.Descendants("Music")(Index).Attribute("Uri").Value
    PageTitle.Text = myTitle
    MediaElement1.Source = New Uri(mySong, UriKind.Absolute)
    MediaElement1.Volume = 1
    Dim imageName As String = myReadXmldoc.seiSong.Descendants("Music")(Index).Attribute("Image").Value
    Image1.Source = New BitmapImage(New Uri("Image/" & imageName, UriKind.Relative))
    MyBase.OnNavigatedTo(e)
  End Sub

■メディアストリームが検証されて開かれ、ファイル ヘッダーが読み取られると発生する処理
AddHandlerメソッドで、タイマー間隔が経過すると発生するTickイベントに、イベントハンドラを追加します。イベントハンドラ内では下記の処理を行います。
タイマーの経過に伴い、ProgressBar を進行させます。経過時間を示す MediaElement.Position.TotalSecondsを、MediaElement.NaturalDuration.TimeSpan.TotalSeconds で取得したメディア・ファイルの継続時間で除算することにより、メディア・ファイルに対する再生時間の比率を求め、ProgressBarのデフォルトのMaximumである100を乗算して、ProgressBar の値に設定します。これで、曲の再生と同期してプログレスバーが進行します。
Startメソッドでタイマーを開始します。
  Private Sub MediaElement1_MediaOpened(sender As Object, e As System.Windows.RoutedEventArgs) Handles MediaElement1.MediaOpened
    AddHandler dt.Tick, Sub()
                             ProgressBar1.Value = MediaElement1.Position.TotalSeconds / MediaElement1.NaturalDuration.TimeSpan.TotalSeconds * 100
                        End Sub
      dt.Start()
  End Sub

■曲の再生が完了した時の処理
[Pause]ボタンを使用不可とし、[Play]ボタンを使用可能にします。ブール型変数noにTrueを指定します。タイマーを中止します。
  Private Sub MediaElement1_MediaEnded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles MediaElement1.MediaEnded
    PauseButton.IsEnabled = False
    PlayButton.IsEnabled = True
    no = True
    dt.Stop()
  End Sub

■[Pause]ボタンがクリックされた時の処理
曲の再生を休止し、[Play]ボタンを使用可能、[Pause]ボタンを使用不可とします。
  Private Sub PauseButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles PauseButton.Click
    MediaElement1.Pause()
    PlayButton.IsEnabled = True
    PauseButton.IsEnabled = False
  End Sub

■[Playボタンがクリックされた時の処理
ブール型変数noの値で条件分岐を行います。noの値がTrueの時、つまり、曲が最後まで再生し切った場合は、PositionプロパティにTimeSpan.Zeroと指定し、再生開始位置を0秒時点に戻します。ProgressBarの値を0で初期化し、タイマーを開始します。no変数にFalseを指定します。
曲を再生し、[Play]ボタンを使用不可、[Pause]ボタンを使用可とします。
  Private Sub PlayButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles PlayButton.Click
    If no = True Then
      MediaElement1.Position = TimeSpan.Zero
      ProgressBar1.Value = 0
      dt.Start()
      no = False
    End If
    MediaElement1.Play()
    PlayButton.IsEnabled = False
    PauseButton.IsEnabled = True
  End Sub

■[Topに戻る]ボタンがクリックされた時の処理
タイマーを中止し、MainPage.xamlに遷移します。
  Private Sub TopButton_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles TopButton.Click
    dt.Stop()
    Me.NavigationService.Navigate(New Uri("/MainPage.xaml", UriKind.Relative))
  End Sub

■プログレスバーの上でマウスの左ボタンが押下された時の処理
GetPosition メソッドで座標を取得し、ProgressBar の幅に対する比率を求め、メディアの継続時間に乗算して、クリックした位置に相当するメディアの秒数を計算します。TimeSpan.FromSeconds を用いて、これを再生開始位置として指定します。
  Private Sub ProgressBar1_MouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles ProgressBar1.MouseLeftButtonDown
    Dim myPoint As New Point
    myPoint = e.GetPosition(ProgressBar1)
    Dim mySecond As Double = myPoint.X / ProgressBar1.ActualWidth * MediaElement1.NaturalDuration.TimeSpan.TotalSeconds
    MediaElement1.Position = TimeSpan.FromSeconds(mySecond)
  End Sub

■エミュレーターのBack(←)ボタンのイベントを上書きする処理
エミュレーターの持っている本来のBack処理を、e.Cancel=Trueで無効とします。
NavigationService.NavigateメソッドでMainPage.xamlに遷移します。その際panoramaIndexというキーワードに1の値を渡しています。パノラマページのインデックスは0から開始するため、1を渡すと、2ページ目の曲名の一覧が表示されたページに戻ります。
このBackボタンのイベントを上書きする処理を記述していないと、エミュレーターのBack(←)をクリックした際エラーが発生しますので、注意してください。
Protected Overrides Subと入力すると、インテリセンス機能が働き、イベントの一覧が表示されますので、その中から選択してください。
  Protected Overrides Sub OnBackKeyPress(ByVal e As System.ComponentModel.CancelEventArgs)
    e.Cancel = True
    dt.Stop()
    NavigationService.Navigate(New Uri("/MainPage.xaml?panoramaIndex=1", UriKind.Relative))
    MyBase.OnBackKeyPress(e)
  End Sub
End Class

去る2011年7月16日に「日本経済新聞 電子版」にて、Windows Phone 7搭載の機種が、8月末にもKDDI(au)から発売されるという報道がされました。Windows Phone Mangoを採用した端末としては世界最初の発売となるようです(詳細についてはKDDIの正式発表を待つのが賢明でしょう)。

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています