四文字熟語の意味をキャラクターが声で教えてくれるアプリを作る

2014年3月27日(木)
薬師寺 国安

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

ロジックコードを記述する

リスト3 (MainWindow.xaml.vb)

Imports Windows.UI.Popups

‘ HeadItemクラス内に「頭」という文字列型のプロパティを定義します。
Public Class HeadItem
  Public Property 頭 As String
End Class

‘ YonmpjiContentクラス内に文字列型の「四文字熟語」、「読み」、「意味」を定義します。
Public Class YonmojiContent
  Public Property 四文字熟語 As String
  Public Property 読み As String
  Public Property 意味 As String
End Class

Public NotInheritable Class MainPage
  Inherits Page

‘ キャラクタが読み上げる内容を格納するメンバー変数readingTextを宣言します。
  Private readingText As String

‘ XML要素を表すXElementクラス型のメンバー変数xmldocを宣言します。
  Private xmldoc As XElement
 
  Private myCount As Integer = 0
  Private TotalCount As Integer = 0

‘ 音声で読み上げさせるためのMediaElementクラス型のメンバー変数myMediaを宣言します。
  Private myMedia As MediaElement

ページがアクティブになった時の処理

XElement.LoadメソッドでXML文書(yonmojijyukugo.xml)を読み込みます。

HeadItemクラス型の新しいリストである、myHeadItemオブジェクトを作成します。

DescenDantsメソッドで全ての子孫要素で、要素の要素から先頭の1文字分を抜き出して、重複しないの内容を変数resultに格納しながら、以下の処理を繰り返します。

メンバー変数myCountを1ずつ増加します。HeadItemクラスの「頭」プロパティに、要素から取り出した先頭の、重複しない1文字を指定して、AddメソッドでmyHeadItemオブジェクトに追加します。

headGridViewのItemsSourceプロパティにmyHeadItemオブジェクトを追加します。これで、要素の重複しない先頭の1文字が表示されます。

YonmojiContentクラスの新しいリストであるmyYonmojiContentオブジェクトを作成します。

Descendantsメソッドで全ての子孫要素の内容を、変数resultに格納しながら、以下の処理を繰り返します。

メンバー変数TotalCountを1ずつ増加します。

YonmojiContentクラスの、「四文字熟語」プロパティに要素の内容を、「読み」プロパティに要素の内容を、「意味」プロパティに要素の内容を指定して、AddメソッドでmyYomnojiContentオブジェクトに追加します。

GridView1のItemsSourceにmyYonmojiContentオブジェクトを追加します。

  Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    xmldoc = XElement.Load("yonmojijyukugo.xml")
    Dim myHeadItem As New List(Of HeadItem)
 
    For Each result In From c In xmldoc.Descendants("熟語") Select c.Element("読み").Value.Substring(0, 1) Distinct
      myCount += 1
      myHeadItem.Add(New HeadItem With {.頭 = result})
    Next
    headGridView.ItemsSource = myHeadItem
 
    Dim myYonmojiContent As New List(Of YonmojiContent)
    For Each result In From c In xmldoc.Descendants("熟語") Select c
      TotalCount += 1
      myYonmojiContent.Add(New YonmojiContent With {.四文字熟語 = result.Element("四文字熟語").Value, .読み = result.Element("読み").Value, .意味 = result.Element("意味").Value})
    Next
    GridView1.ItemsSource = myYonmojiContent

  End Sub

50音が選択された時の処理

メンバー変数myCountを0で初期化します。

変数headMojiにheadGridViewから選択された項目を、HeadItemクラスにキャストして、その「頭」プロパティを取得します。

YomnojiContentの新しいリストであるmyYonmojiContentオブジェクトを作成します。

Descendantsメソッドで全ての子孫要素の子要素の値が、変数headMojiで始まっている(StartsWith)要素の内容を、変数resultに格納しながら以下の処理を繰り返します。

メンバー変数myCountを1ずつ増加します。YonmojiContentクラスの、「四文字熟語」プロパティに要素の内容を、「読み」プロパティに要素の内容を、「意味」プロパティに要素の内容を指定して、AddメソッドでmyYomnojiContentオブジェクトに追加します。

mainGridViewのItemsSourceプロパティにmyYonmojiContentオブジェクトを追加します。これで、50音から選択した文字で始まる四文字熟語が全て表示されます。その四文字熟語は何個あるかを、countTextBlockにmyCountメンバー変数の格納している値と、文字列「登録数」とを連結して表示します。

  Private Sub headGridView_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles headGridView.SelectionChanged
    Try
      myCount = 0
      Dim headMoji = DirectCast(headGridView.SelectedItem, HeadItem).頭
      Dim myYonmojiContent As New List(Of YonmojiContent)
      For Each result In From c In xmldoc.Descendants("熟語") Where c.Element("読み").Value.StartsWith(headMoji) Select c
        myCount += 1
        myYonmojiContent.Add(New YonmojiContent With {.四文字熟語 = result.Element("四文字熟語").Value, .読み = result.Element("読み").Value, .意味 = result.Element("意味").Value})
      Next
      mainGridView.ItemsSource = myYonmojiContent
      countTextBlock.Text = "【登録数】=" & myCount.ToString
    Catch
      Exit Sub
    End Try
  End Sub

検索の際に[実行]アイコンがタップされた時の処理

変数noを0で初期化します。

検索対象文字が未入力の場合は、警告メッセージを出して処理を抜けます。それ以外の場合は以下の処理を行います。

Descendantsメソッドで全ての子孫要素を選択したクエリを定義します。

そのクエリ内の要素の値を変数resultに格納しながら、以下の処理を行います。

もし、要素の値が、yomiWatermarkTextBlockに入力された値と同じであれば、GridViewの選択されたインデックスに1ずつ増加する変数noの値を指定し、ScrollIntoViewメソッドで、その位置までスクロールします。指定した四文字熟語が見つかれば、その位置までスクロールして選択状態にしてくれるということです。

もし、1ずつ増加する変数noの値が要素の個数と同じか、それより大きかった場合は、「該当する熟語がありません。」とメッセージを出して処理を抜けます。

  Private Async Sub okButton_Click(sender As Object, e As RoutedEventArgs) Handles okButton.Click
    Dim no As Integer = 0
    If yomiWatermarkTextBox.Text = String.Empty Then
      Dim message As New MessageDialog("読みを入力してください。")
      Await message.ShowAsync
      yomiWatermarkTextBox.Focus(Windows.UI.Xaml.FocusState.Pointer)
      Exit Sub
    Else
      Dim query = From c In xmldoc.Descendants("熟語") Select c '.Element("読み").Value.Equals(yomiWatermarkTextBox.Text) Select c
      For Each result In query
        If result.Element("読み").Value.Equals(yomiWatermarkTextBox.Text) Then
          GridView1.SelectedIndex = no
          GridView1.ScrollIntoView(GridView1.SelectedItem)
          Exit For
        End If
        If no >= query.Count - 1 Then
          Dim message As New MessageDialog("該当する熟語がありません。")
          Await message.ShowAsync
          no = 0
        End If
        no += 1
      Next
    End If
  End Sub

画面上でマウスの右をタップした時の処理

画面上に表示させていた、四文字熟語の個数を消去します。

  Private Sub MainPage_RightTapped(sender As Object, e As RightTappedRoutedEventArgs) Handles Me.RightTapped
    countTextBlock.Text = String.Empty
  End Sub

50音から選択された四文字熟語を選択した際の処理

mainGridViewを引数にYomiAndMeanメソッドを実行します。

  Private Sub mainGridView_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles mainGridView.SelectionChanged
    YomiAndMean(mainGridView)
  End Sub

「読み」と「意味」をキャラクタが音声で喋る処理

メンバー変数myMediaをMediaElement1で初期化しておきます。

音声機能へのアクセスを提供する、新しいSpeechSynthesizerのインスタンス、synthオブジェクトを作成します。

SynthesizeTextToStreamAsyncメソッドで、指定した文字列から、音声出力を非同期に生成します。

SetSourceメソッドで、指定されたストリームおよびMIME型を使用してSourceプロパティを設定します。Playメソッドで音声を再生します。

音声にどんな言語で、どのような声で喋らすかは、SpeechSynthesizerのVoiceプロパティで参照できます。下記のURLを参照してください。
> SpeechSynthesizer.Voice | voice property
上記URLを見るとJapanese JA は性別が「Female」で、名前は「Haruka」という女性が読み上げるようです。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。

  Private Async Function syokoVoice() As Task
    myMedia = Me.MediaElement1
    Dim synth = New Windows.Media.SpeechSynthesis.SpeechSynthesizer
    Dim stream = Await synth.SynthesizeTextToStreamAsync(readingText)
    myMedia.SetSource(stream, stream.ContentType)
    myMedia.Play()
  End Function

検索結果から表示された四文字熟語が選択された時の処理

GridView1を引数にYomiAndMeanメソッドを実行します。

  Private Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged
    YomiAndMean(GridView1)
  End Sub

各GridViewの四文字熟語が選択された時に実行される処理

変数yomiにmyGridViewから選択された項目を、YonmojiContentクラスにキャストして、その「読み」プロパティの値を取得します。変数meanにmyGridViewから選択された項目を、YonmojiContentクラスにキャストして、その「意味」プロパティの値を取得します。

メンバー変数readingTextに変数yomiとmeanを指定して、「読み」と「意味」を読み上げるsykoVoiceタスクを実行します。

ProgressRing1を稼働させます。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。

  Private Async Sub YomiAndMean(myGridView As GridView)
      Try
          Dim yomi = DirectCast(myGridView.SelectedItem, YonmojiContent).読み
          Dim mean = DirectCast(myGridView.SelectedItem, YonmojiContent).意味
          readingText = yomi & "。意味は、" & mean & "です。"
          ProgressRing1.IsEnabled = True
          ProgressRing1.IsActive = True
          Await syokoVoice()
      Catch
          Exit Sub
      End Try
  End Sub

AppBar1が閉じられた時の処理

検索結果で選択されていたGridView1の選択を解除します。

  Private Sub AppBar1_Closed(sender As Object, e As Object) Handles AppBar1.Closed
    GridView1.SelectedIndex = -1
  End Sub

キャラクタが「読み」と「意味」を読み終えた時の処理

ProgressRing1を非稼働状態にします。

  Private Sub MediaElement1_MediaEnded(sender As Object, e As RoutedEventArgs) Handles MediaElement1.MediaEnded
    ProgressRing1.IsEnabled = False
    ProgressRing1.IsActive = False
  End Sub
End Class

今回で10回続いた連載も最終回です。お付き合いのほどありがとうございました。いかがだったでしょうか。皆様のWindows ストア・アプリ作成のアイデアのヒントにでもなれば、筆者としては嬉しい限りです。

では、またお会いする日まで…。

薬師寺国安

  • 四文字熟語の意味をキャラクターが声で教えてくれるアプリ

    『Windows 8.1+Visual Studio 2013によるWindows ストア・アプリ開発実例集』 第11回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

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

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

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

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