お気に入りの写真に登場する、仲良しクラウディアちゃん
Saveアイコンがタップされた時の処理
変数claudiaWidthに、クラウディアの幅にX軸の拡大縮小の値myTrans.ScaleXを乗算して指定します。
変数claudiaHeightに、クラウディアの高さにY軸の拡大縮小の値myTrans.ScaleYを乗算して指定します。
ピクチャライブラリにアクセスします。
CreateFolderAsyncメソッドで、ピクチャライブラリ内にClaudiaData2というサブフォルダを作成します。CreationCollisionOption.OpenIfExistsを指定すると、既に同名フォルダが存在する場合はフォルダ名を返し、ない場合は新規に作成します。
Visual Basic の埋め込み式を用いて、ルート要素
属性”Width”にclaudiaWidth変数の値を指定します。
属性”Height”にclaudiaHeightの値を指定します。
属性”Top”にはmyTrans.TranslateY.ToStringの値を、属性”Left”にはmyTrans.TranslateX.ToStringの値を指定します。
属性”Wav”にはメンバ変数SoundFileの値を指定します。
次に
To属性には167、Left属性には303と指定しています。
埋め込み式の構文であるを用いています。
これは ASP.NET で使用される構文と同じです。作成したXML文書を変数saveXmlに格納します。
XElemet.Parseメソッドで、作成したXMLを文字列として読み込みます。読み込んだ結果XMLを変数resultに格納しておきます。
CreateFileAsyncメソッドで、ピクチャライブラリのClaudiaData2サブフォルダ内に現在の年月日時分秒.xmlというファイルを作成します。
CreationCollisionOption.ReplaceExistingと指定し、既に同名のファイルがある場合は上書きします。
OpenAsyncメソッドで、作成した現在の年月日時分秒.xmlを「読み取り/書き込み」モードで開き、入出力データへの、ランダムアクセスをサポートするIRandomAccessStreamインターフェース型のmyStreamで参照します。
データを出力ストリームに書き込む、新しいDataWriterのインスタンスをmyStreamで初期化し、writerオブジェクトを作成します。
出力ストリームのUnicode文字エンコードを設定する、UnicodeEncodingプロパティにUtf8を指定します。
Writeメソッドで出力ストリームにresult変数の値を書き込みます。
StoreAsyncメソッドでバッキングストアにバッファーのデータをコミットします。Canvas内をクリアします。
文字列型の新しいリストであるmyFileListオブジェクトを作成します。
GetFilesAsyncメソッドでClaudiaData2フォルダ内のファイルを取得し、コレクション変数myImageFileに格納します。
myImageFileに格納されたファイルの個数が0より大きい場合は以下の処理を行います。
コレクション変数myImageFile内を変数fileResultで反復処理しながら、fileResult.Pathで取得した絶対パス付きファイル名から、パスと拡張子を除いたファイル名を取得し、再度”.xml”という拡張子を追加して、そのファイル名をmyFileListオブジェクトに追加します。
fileListBoxのItemsSourceプロパティにmyFileListオブジェクトを指定します。これで、リストボックスにClaudiaData2内のXMLファイルが一覧表示されます。
言葉の表示されているリストボックスの使用を不可とし、Saveアイコンの使用を不可とします。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します
Private Async Sub saveButton_Click(sender As Object, e As RoutedEventArgs) Handles saveButton.Click Dim claudiaWidth = CInt(myClaudiaImage.Width * myTrans.ScaleX) Dim claudiaHeight = CInt(myClaudiaImage.Height * myTrans.ScaleY) Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim SubFolder = Await myFolder.CreateFolderAsync("ClaudiaData2", CreationCollisionOption.OpenIfExists) Dim saveXml As XElement = <Claudia><Info><Image Width=<%= claudiaWidth %> Height=<%= claudiaHeight %> Top=<%= myTrans.TranslateY.ToString %> Left=<%= myTrans.TranslateX.ToString %> Wav=<%= SoundFile %>><%= claudiaImageFileName %></Image><PersonalImage Width=<%= 640 %> Height=<%= 480 %> Top=<%= 167 %> Left=<%= 303 %>><%= myFileName %></PersonalImage></Info></Claudia> Dim saveXmldoc As XElement = XElement.Parse(saveXml.ToString) Dim result As String = saveXmldoc.ToString Dim myXmlFile As StorageFile = Await SubFolder.CreateFileAsync(DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".xml", CreationCollisionOption.ReplaceExisting) Using myStream As IRandomAccessStream = Await myXmlFile.OpenAsync(FileAccessMode.ReadWrite) Dim writer As DataWriter = New DataWriter(myStream) writer.UnicodeEncoding = UnicodeEncoding.Utf8 writer.WriteString(result) Await writer.StoreAsync End Using Canvas1.Children.Clear() Dim myFileList As New List(Of String) Dim myImageFile = Await SubFolder.GetFilesAsync If myImageFile.Count > 0 Then For Each fileResult As StorageFile In myImageFile myFileList.Add(Path.GetFileNameWithoutExtension(fileResult.Path) & ".xml") Next Else fileListBox.Items.Clear() End If fileListBox.ItemsSource = myFileList soundListBox.IsEnabled = False saveButton.IsEnabled = False End Sub
戻る(←)アイコンがタップされた時の処理
Frameを非表示にし、ピクチャライブラリのClaudiaData2フォルダ内にファイルが存在した場合は、リストボックスにファイルの一覧を表示し、クラウディアの画像と、音声用のファイルを表示する処理である、DataShowプロシージャを実行します。
Private Sub backButton_Click(sender As Object, e As RoutedEventArgs) Handles backButton.Click myFrame.Visibility = Windows.UI.Xaml.Visibility.Collapsed DataShow() End Sub
ファイルの一覧から任意のファイルが選択された時の処理
Frameを表示状態にし、fileListBoxから選択されたファイル名を変数mySelectedFileに格納します。
この変数を引数にDataShowPageに遷移します。
Private Sub fileListBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles fileListBox.SelectionChanged If fileListBox.SelectedIndex >= 0 Then myFrame.Visibility = Windows.UI.Xaml.Visibility.Visible mySelectedFile = fileListBox.SelectedItem.ToString myFrame.Navigate(GetType(DataShowPage), mySelectedFile) Else Exit Sub End If End Sub End Class
次に、ソリューションエクスプローラー内のDataShowPage.xamlを展開して表示される、DataShowPage.xaml.vbをダブルクリックしてリスト5のコードを記述します。
ロジックコードを記述する
リスト5 (DataShowPage.xaml.vb)
Option Strict On
ファイルやフォルダおよびアプリケーションの設定を管理するクラスの含まれる、Windows.Storage名前空間をインポートします。
Imports Windows.Storage
シーケンシャルアクセスストリームおよびランダムアクセスストリームに対する読み込みと書き込みのサポートを提供するクラスの含まれる、Windows.Storage.Streams名前空間をインポートします。
Imports Windows.Storage.Streams
コンテキストメニューおよびメッセージダイアログのサポートを提供するクラスの含まれる、Windows.UI.Popups名前空間をインポートします。
Imports Windows.UI.Popups
メンバ変数mySelectedFileを宣言しておきます。
Dim mySelectedFile As String
ページがアクティブになった時の処理
音声を再生するPlayボタンの使用を可能にします。
MainPage.xamlから渡された値はe.Parameterで受け取れます。これはObject型であるためDirectCastで文字列にキャストして、メンバ変数mySelectedFileに格納します。XMLファイルが格納されています。
ピクチャライブラリにアクセスします。
CreateFolderAsyncメソッドでピクチャライブラリ内にClaudiaData2というサブフォルダを作成します。
CreationCollisionOption.OpenIfExistsと指定すると、同名フォルダがある場合は、そのフォルダ名を返し、ない場合は新規に作成します。
GetFileAsyncメソッドで、指定されたファイルの名前を使用して、現在のフォルダから1つのファイルを取得します。
取得したファイルを変数myFileで参照します。
OpenFileAsyncメソッドでmyFileを「読み込み専用」モードで開き、myStream変数で参照します。
myStreamと文字のエンコード(UTF-8)で初期化された、新しいStreamReaderクラスのインスタンスreaderオブジェクトを作成します。
ReadToEndメソッドでファイルの最後まで読み取り変数resultに格納しておきます。
XElement.Parseメソッドで変数resultの値を文字列として読み込みます。
変数myPersonalImageに
変数myClaudiaImageには
あと、クラウディアのWidth、Heigt、Top、Left属性の値を取得して各変数に格納しておきます。
音声ファイルであるWav属性の値も取得して変数c_Wavに格納しておきます。
同様にClaudiaのフォルダから取得した画像のWidth、Height、Top、Left属性の値も取得して、各変数に格納しておきます。
選択されたXMLファイルは1個で、各要素も属性も1個しか存在しないため、Firstメソッドで、シーケンスの最初の属性を取得しています。
CreateFolderAsyncメソッドでピクチャライブラリ内にClaudiaというサブフォルダを作成します。
CreationCollisionOption.OpenIfExistsと指定すると、同名フォルダがある場合はそのフォルダ名を返し、ない場合は新規に作成します。
GetFileAsyncメソッドで、指定されたファイルの名前を使用して、現在のフォルダから1つのファイルを取得します。
BitmapImageクラスの新しいインスタンスmyBmpを作成します。
SetSourceメソッドにAwait peronalImageFile.OpenReadAsyncと指定して、ファイルの内容を読むために、現在のファイルのランダムアクセスストリームを開き、BitmapSourceのソースイメージに設定します。
新しいImageのインスタンスpersonalImgを作成します。
Widthにp_Width変数の値を、Heightにp_Heightの値を指定します。
SourceプロパティにはmyBmpオブジェクトを指定します。
Marginプロパティには、p_Leftとp_Topの値を指定します。減算している数値は位置合わせの数値です。
ShowAreaという名前のCanvasにperonalImgオブジェクトを追加します。Claudiaフォルダから読み込んだ画像が表示されます。
新しいImageクラスのインスタンスclaudiaImgオブジェクトを作成します。
Widthプロパティにc_Width変数の値を、Heightプロパティにc_Height変数の値を、Marginプロパティにはc_Leftとc_Top変数の値を指定します。
Sourceプロパティには、Imagesフォルダ内の、変数myClaudiaImageが格納しているファイル名を指定します。
MediaElementのSourceプロパティにはWAVフォルダ内で変数c_Wavに格納されている音声ファイルを指定します。
ShowAreaというCanvasにclaudiaImgを追加します。これで、先に追加しておいたClaudiaフォルダの画像の上にクラウディアのイメージが重なって表示されます。
土台となる画像をClaudiaフォルダから読み込まなかった場合は例外が発生します。その際にはErrorShowプロシージャを実行します。
非同期処理で行われるためメソッドの先頭にAsyncを追加します。
Protected Overrides Async Sub OnNavigatedTo(e As Navigation.NavigationEventArgs) Try delTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed playButton.IsEnabled = True mySelectedFile = DirectCast(e.Parameter, String) Dim result As String Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myStorageFolder.CreateFolderAsync("ClaudiaData2", CreationCollisionOption.OpenIfExists) Dim myFile = Await mySubFolder.GetFileAsync(mySelectedFile) Using myStream As IRandomAccessStream = Await myFile.OpenAsync(FileAccessMode.Read) Using reader As StreamReader = New StreamReader(myStream.AsStream, System.Text.Encoding.UTF8) result = reader.ReadToEnd End Using End Using Dim doc As XElement = XElement.Parse(result) Dim myPeronalImage = doc.Descendants("PersonalImage").Value Dim myClaudiaImage = doc.Descendants("Image").Value Dim c_Width = doc.Descendants("Image").Attributes("Width").First Dim c_Height = doc.Descendants("Image").Attributes("Height").First Dim c_Top = doc.Descendants("Image").Attributes("Top").First Dim c_Left = doc.Descendants("Image").Attributes("Left").First Dim c_Wav = doc.Descendants("Image").Attributes("Wav").First.Value Dim p_Width = doc.Descendants("PersonalImage").Attributes("Width").First Dim p_Height = doc.Descendants("PersonalImage").Attributes("Height").First Dim p_Top = doc.Descendants("PersonalImage").Attributes("Top").First Dim p_Left = doc.Descendants("PersonalImage").Attributes("Left").First Dim personalSubFolder As StorageFolder = Await myStorageFolder.CreateFolderAsync("Claudia", CreationCollisionOption.OpenIfExists) Dim peronalImageFile = Await personalSubFolder.GetFileAsync(myPeronalImage) Dim myBmp As New BitmapImage myBmp.SetSource(Await peronalImageFile.OpenReadAsync) Dim personalImg As New Image With personalImg .Width = CDbl(p_Width) .Height = CDbl(p_Height) .Source = myBmp .Margin = New Thickness(CDbl(p_Left) - 300, CDbl(p_Top) - 170, 0, 0) End With ShowArea.Children.Add(personalImg) Dim claudiaImg As New Image With claudiaImg .Width = CDbl(c_Width) .Height = CDbl(c_Height) .Margin = New Thickness(CDbl(c_Left), CDbl(c_Top), 0, 0) .Source = New BitmapImage(New Uri("ms-appx:///Images/" & myClaudiaImage)) End With MediaElement1.Source = New Uri("ms-appx:///WAV/" & c_Wav) ShowArea.Children.Add(claudiaImg) Catch ErrorShow() End Try End Sub
例外が発生した場合の処理
警告メッセージを発生して、処理を抜けます。
非同期処理で行われるためメソッドの先頭にAsyncを追加します。
Private Async Sub ErrorShow() Dim myMessage As New MessageDialog("ピクチャフォルダ内のClaudiaサブフォルダ内の画像ではありません。Deleteアイコンでこのファイルを削除してください。") Await myMessage.ShowAsync Exit Sub End Sub
Playアイコンがタップされた時の処理
音声を再生します。
Private Sub playButton_Click(sender As Object, e As RoutedEventArgs) Handles playButton.Click MediaElement1.Play() End Sub
Deleteアイコンがタップされた時の処理
ピクチャライブラリのClaudiaData2サブフォルダにアクセスします。
メンバ変数mySelectedFileに格納されているXMLファイルを、GetFileAsyncメソッドで取得し、変数myFileで参照します。
DeleteAsyncで取得したファイルを削除します。
ShowAreaという名前のCanvasをクリアします。
「削除しました!」を表示するために、delTextBlockを表示状態にします。
Playアイコンの使用を不可にします。またDeleteアイコンの使用も不可とします。
Private Async Sub delButton_Click(sender As Object, e As RoutedEventArgs) Handles delButton.Click Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myStorageFolder.CreateFolderAsync("ClaudiaData2", CreationCollisionOption.OpenIfExists) Dim myFile = Await mySubFolder.GetFileAsync(mySelectedFile) Await myFile.DeleteAsync() ShowArea.Children.Clear() delTextBlock.Visibility = Windows.UI.Xaml.Visibility.Visible playButton.IsEnabled = False delButton.IsEnabled = False End Sub End Class
今回はここまでです。ありがとうございました。
筆者からのお知らせ
筆者はWindowsストアでアプリを公開しています。チャームの検索からWindowsストアを選択して、検索欄に、kuniyasuまたはYakushijiKuniyasuと入力すると、公開されているアプリの一覧が表示されます。上記はどちらも私のアカウントですので、興味のある方は是非ダウンロードして使ってみてください。
クラウディアが写真に登場してセリフを喋るプログラム
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- お花とクラウディアさんを合成して表示するプログラムを作る
- デスクトップのクラウディアさんが声で励ましてくれるプログラムを作る
- PCで撮影した写真を並べて最適な1枚を選べるプログラムをつくる
- 撮影した写真の管理ができるマイフォトアプリを作る
- Webカメラで撮影した写真をセピア調に演出するアプリを作る
- 場所と写真を記録するプログラムを作って思い出のシーンを保存しよう
- 画像のドラッグ、移動、回転、拡大縮小を行う+1つのサンプル
- CountDownControlを使ってカウントダウン後にカメラのシャッターを切る
- 写真と現在位置を入れた画像日記アプリを作る
- メッセージボックスの処理を分岐させる+2つのサンプル