写真と現在位置を入れた画像日記アプリを作る
Webカメラのデバイスの種類が選択された時の処理
メンバ変数cameraNoにcameraComboBoxより選択されたインデックス番号を格納しておきます。
AppBar1を表示状態にします。
MediaCaptureの新しいインスタンスmyMediaCaptureオブジェクトを作成します。
InitializeAsyncメソッドで、以下の内容でMediaCaptureオブジェクトを初期化します。
新しいMediaCaptureInitializationSettingsクラスのインスタンスを作成します。MediaCaptureInitializationSettingsクラスは、MediaCaptureオブジェクトの初期化設定をするクラスです。VideoDevideIdプロパティにcameraComboBoxより選択されたインデックスに対応する、コレクション変数myCameraのデバイスIDを指定します。
CaptureElement1のSourceプロパティにデバイスIDで初期化されたmyMediaCaptureを指定します。StartPreviewAsyncメソッドでプレビューを開始します。これで、Webカメラの画像が表示されます。
マウスの右クリックで表示されるshutterButton(Attach Cameraアイコン)の使用を可能にします。非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Sub cameraComboBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles cameraComboBox.SelectionChanged Try cameraNo = cameraComboBox.SelectedIndex AppBar1.Visibility = Xaml.Visibility.Visible myMediaCapture = New MediaCapture Await myMediaCapture.InitializeAsync(New MediaCaptureInitializationSettings With {.VideoDeviceId = myCamera(cameraComboBox.SelectedIndex).Id}) CaptureElement1.Source = myMediaCapture Await myMediaCapture.StartPreviewAsync shutterButton.IsEnabled = True Catch Exit Sub End Try End Sub
「Attach Camera」アイコンがタップされた時の処理
MediaElement1を再生します。つまりシャッター音が鳴ります。
ピクチャライブラリにアクセスし、CreateFolderAsyncメソッドで、ピクチャフォルダ内にImageDiaryというサブフォルダを作成します。その際、CreationCollisionOption.OpenIfExistsと指定しておくと、同名フォルダやファイルがある場合は、そのフォルダやファイル名を返し、ない場合は新規に作成してくれます。
CreateFileAsyncメソッドで現在の年月日時間分秒.jpgファイルを作成します。メンバ変数saveImageFileNameに、このjpgファイル名を格納しておきます。
イメージストリームの書式を表す新しい、ImageEncodingPropertiesクラスのインスタンス、myImageEncodingPropertyオブジェクトを作成します。書式のサブタイプを表すSubtypeプロパティにjpegを指定し、Widthに640、Heightに480と指定します。
CapturePhotoToStorageFileAsyncメソッドで、ストレージファイルにフォトをキャプチャします。書式は以下の通りです。
CapturePhotoToStorageFileAsync(ImageEncodingProperties,IStorageFile)
コレクション変数myPictureFilesにGetFilesAsyncメソッドで、ImageDiaryフォルダ内の画像ファイルを取得して格納します。
コレクション変数myPictureFilesが格納しているファイルの個数を、Countプロパティで取得して、メンバ変数Indexに格納します。
新しいBitmapImageクラスのインスタンスsaveBmpを作成します。SetSourceメソッドに
Await myPictureFiles(Index - 1).OpenReadAsync
と指定して、コレクション変数内のIndexに対応するファイルをOpenReadAsyncメソッドで開き、ソースイメージに指定します。Indexを-1しているのはコレクション変数myPictureFilesが格納しているファイルのインデックスが0から始まるためです。「Save」アイコンの使用を可能にします。
非同期処理で行われるためメソッドの先頭にAsyncを追加します。
Private Async Sub shutterButton_Click(sender As Object, e As RoutedEventArgs) Handles shutterButton.Click MediaElement1.Play() Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myFolder.CreateFolderAsync("ImageDiary", CreationCollisionOption.OpenIfExists) Dim myFile As StorageFile = Await mySubFolder.CreateFileAsync(DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".jpg") saveImageFileName = DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".jpg" Dim myImageEncodingProperty As New ImageEncodingProperties myImageEncodingProperty.Subtype = "jpeg" myImageEncodingProperty.Width = 640 myImageEncodingProperty.Height = 480 AwaitmyMediaCapture.CapturePhotoToStorageFileAsync(myImageEncodingProperty, myFile) myPictureFiles = Await mySubFolder.GetFilesAsync() Index = myPictureFiles.Count saveBmp = New BitmapImage saveBmp.SetSource(Await myPictureFiles(Index - 1).OpenReadAsync) Image1.Source = saveBmp saveButton.IsEnabled = True End Sub
「Save」アイコンがタップされた時の処理
コメント欄が未入力の場合は、警告メッセージを発して処理を抜けます。
それ以外の場合は、ピクチャライブラリのImageDiaryXMLサブフォルダにアクセスします。
XMLを作成して変数saveXmlに格納します。作成するXMLは、ルート要素が
各要素の内容は、Visual Basicの埋め込み式を用いています。埋め込み式の構文はで、ASP.NET で使用される構文と同じです。
XElement.Parseメソッドで、作成したXMLを文字列として読み込みます。読み込んだXMLを変数resultXmlに格納します。
ImageDiaryXMLフォルダに、CreateFileAsyncメソッドで、saveImageFileName変数が格納している画像ファイル名から、20文字分取りだして、文字列「.xml」と連結したXMLファイルを作成し、変数myXmlFileで参照しておきます。
OpenAsyncメソッドで、読み込みと書きこみモードでmyXmlFileが参照しているファイルを開き、myStreamで参照します。
データをストリームに書きこむ、myStreamで初期化された新しいインスタンス、writerを作成します。
エンコードにUTF-8を指定し、WriteStringメソッドで、出力ストリームにresultXmlの内容を書きこみます。
StoreAsyncメソッドで、ストアにバッファのデータをコミットします。
文字列型の新しいリストである、xmlFileListオブジェクトを作成します。ImageDiaryXml内のファイルを、GetFilesAsyncで取得して、コレクション変数myXmlFileNameに格納します。
XMLファイルが存在する場合は、コレクション変数myXmlFileName内を、変数resultで反復しながら、以下の処理を繰り返します。
Addメソッドで、取得したファイル名から、パスと拡張子を除いたファイル名を取り出し、それに、文字列「.xml」を連結して、xmlFileListオブジェクトに追加していきます。
fileListBoxのItemsSourceプロパティにxmlFileListオブジェクトを指定します。ListBoxに保存したXMLファイルが追加されます。
Folderアイコンの使用を可能にし、Saveアイコンの使用を不可とします。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Sub saveButton_Click(sender As Object, e As RoutedEventArgs) Handles saveButton.Click If commentTextBox.Text = String.Empty Then Dim message As New MessageDialog("何かコメントを入力してください。") Await message.ShowAsync Exit Sub Else Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myFolder.CreateFolderAsync("ImageDiaryXML", CreationCollisionOption.OpenIfExists) Dim saveXml As XElement = <ImageDiary><Info><ImageName><%= saveImageFileName %></ImageName><Comment><%= commentTextBox.Text %></Comment><Latitude><%= myLatitude %></Latitude><Longitude><%= myLongitude %></Longitude></Info></ImageDiary> Dim saveXmlDoc As XElement = XElement.Parse(saveXml.ToString) Dim resultXml As String = saveXmlDoc.ToString Dim myXmlFile As StorageFile = Await mySubFolder.CreateFileAsync(saveImageFileName.Substring(0, 20) & ".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(resultXml) Await writer.StoreAsync End Using Dim xmlFileList As New List(Of String) Dim myXmlFileName = Await mySubFolder.GetFilesAsync If myXmlFileName.Count > 0 Then For Each result In myXmlFileName xmlFileList.Add(Path.GetFileNameWithoutExtension(result.Path) & ".xml") Next Else fileListBox.Items.Clear() End If fileListBox.ItemsSource = xmlFileList ichiranButton.IsEnabled = True saveButton.IsEnabled = False End If End Sub
ListBoxからXMLファイルが選択された時の処理
AppBarを非表示にし、ブール型メンバ変数をTrueで初期化します。この値を元に戻る(←)アイコンがタップされた時、どこに戻るかを決定します。
Frameを表示状態にし、ListBoxから選択されたXMLファイル名を変数mySelectedFileに格納します。
Image1を非表示にします。
FrameのNavigateメソッドで、mySelectedFileを引数にDataShowPageに遷移します。
エラーが発生した場合は、Frameを非表示にし、AppBarとImageを表示状態にします。
Private Sub fileListBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles fileListBox.SelectionChanged AppBar1.Visibility = Xaml.Visibility.Collapsed Try flag = True myFrame.Visibility = Xaml.Visibility.Visible Dim mySelectedFile As String = fileListBox.SelectedItem.ToString Image1.Visibility = Xaml.Visibility.Collapsed myFrame.Navigate(GetType(DataShowPage), mySelectedFile) Catch myFrame.Visibility = Xaml.Visibility.Collapsed AppBar1.Visibility = Xaml.Visibility.Visible Image1.Visibility = Xaml.Visibility.Visible Exit Sub End Try End Sub
戻る(←)アイコンがタップされた時の処理
各表示を以下の状態にします。
- CaptureElementを表示状態にします。
- cameraComboBoxを表示状態にします。
- AppBarを表示状態にします。
- myFrameを非表示にします。
- Image1を表示状態にします。
- CommentTextBox内を空にします。
ブール型メンバ変数がTrueの場合は、DataShowプロシージャを実行して、flagをFalseで初期化します。それ以外は、flagをFalseで初期化し、処理を抜けます。
Private Sub backButton_Click(sender As Object, e As RoutedEventArgs) Handles backButton.Click CaptureElement1.Visibility = Xaml.Visibility.Visible cameraComboBox.Visibility = Xaml.Visibility.Visible AppBar1.Visibility = Xaml.Visibility.Visible AppBar1.IsEnabled = True myFrame.Visibility = Xaml.Visibility.Collapsed Image1.Visibility = Xaml.Visibility.Visible Image1.Source = Nothing commentTextBox.Text = String.Empty If flag = True Then DataShow() flag = False Else flag = False Exit Sub End If End Sub
「Folder」アイコンがタップされた時の処理
CaptureElementを非表示に、cameraComboBoxを非表示に、myFrameを表示状態に、AppBarを非表示とします。
myFrameのNavigateメソッドでDataIchiranShowPageに遷移します。何も値は渡さないのでNothingを指定しておきます。
Private Sub ichiranButton_Click(sender As Object, e As RoutedEventArgs) Handles ichiranButton.Click CaptureElement1.Visibility = Xaml.Visibility.Collapsed cameraComboBox.Visibility = Xaml.Visibility.Collapsed myFrame.Visibility = Xaml.Visibility.Visible AppBar1.Visibility = Xaml.Visibility.Collapsed myFrame.Navigate(GetType(DataIchiranShowPage), Nothing) End Sub
Geolocatorの機能が変更された時に発生する処理
Geolocatorオブジェクトの更新後の状態を、変数positionStatusで参照します。
Select Case文で条件分岐を行います。場所データを提供するGeolocatorオブジェクトがDisabledであった場合、つまり、場所プロバイダーが無効であった場合は、RunAsyncメソッドでディスパッチされたイベントの結果を非同期に返します。ディスパッチャの優先順位は標準のNormalを指定しています。
この場合は、「位置情報を取得できません。GPSおよび位置情報取得可能なPCでお試しください。」というメッセージボックスを表示させ、「Attach Camera」アイコンの使用を不可として、処理を抜けます。それ以外の場合は、「Attch Camera」アイコンの使用を可能にします。
非同期で行われるためメソッドの先頭にAsyncを追加します。
Private Async Sub myGeolocator_StatusChanged(sender As Geolocator, args As StatusChangedEventArgs) Dim positionStatus = args.Status Select Case positionStatus Case Windows.Devices.Geolocation.PositionStatus.Disabled Await myCoreDispacher.RunAsync(CoreDispatcherPriority.Normal, Async Sub() Dim message As New MessageDialog("位置情報を取得できません。GPSおよび位置情報取得可能なPCでお試しください。") Await message.ShowAsync shutterButton.IsEnabled = False Exit Sub End Sub) Case Else Await myCoreDispacher.RunAsync(CoreDispatcherPriority.Normal, Sub() shutterButton.IsEnabled = True End Sub) End Select End Sub End Class
次に、ソリューションエクスプローラー内のDataShowPage.xamlを展開して表示される、DataShowPage.xaml.vbをダブルクリックしてリスト5のコードを記述します。
ロジックコードを記述する
リスト5 (DataShowPage.xaml.vb)
ファイル、フォルダおよびアプリケーションの設定を管理するクラスの含まれる、Windows.Storage名前空間をインポートします。
Imports Windows.Storage
Bing Mapsに関するクラスの含まれるBing.Maps名前空間をインポートします。
Imports Bing.Maps
図形を定義するクラスの含まれる、Windows.UI.Xaml.Shapes名前空間をインポートします。
Imports Windows.UI.Xaml.Shapes
オブジェクトのUIをサポートする機能の含まれる、Windows.UI名前空間をインポートします。
Imports Windows.UI
最新のHTTPアプリケーション用のプログラミング インターフェイスを提供するクラスの含まれる、System.Net.Http名前空間をインポートします。
Imports System.Net.Http Imports Windows.UI.Popups Imports System.IO
シーケンシャルアクセスストリームおよびランダムアクセスストリームに対する読み取りと書きこみのサポートを提供するクラスの含まれる、Windows.Storage.Streams名前空間をインポートします。
Imports Windows.Storage.Streams Public NotInheritable Class DataShowPage Inherits Page
文字列型の定数メンバ変数を宣言し、YahooのアプリケーションIDで初期化します。
Const AppID As String = "YahooのアプリケーションID" Dim myLatitude As String Dim myLongitude As String Dim myImageFile As String Dim myComment As String Dim delXmlFile As String
画像日記を作るプログラム
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Bing Maps上に地震の震源地を表示するプログラムを作る
- 場所と写真を記録するプログラムを作って思い出のシーンを保存しよう
- PCで撮影した写真を並べて最適な1枚を選べるプログラムをつくる
- 現在位置近くの病院を素早く検索するサンプルプログラム
- 自分の現在位置を取得して表示するサンプルプログラム
- Webカメラで撮影した写真をセピア調に演出するアプリを作る
- 近くにある病院の場所をキャラクターが音声で教えてくれるアプリを作る
- フリーハンドで書いた住所を認識してBing Map上に表示する
- 現在位置の近くにある宿を検索するサンプルプログラム
- Bing Maps上の好きな場所をマークして情報を表示するプログラムを作る