PCで撮影した写真を並べて最適な1枚を選べるプログラムをつくる

2013年9月12日(木)
薬師寺 国安

「Folder」アイコンがタップされた時の処理

PhotoAreaという名前のCanvasを非表示状態にします。Webカメラのデバイス名を表示している、camerComboBoxを非表示状態にします。
myFrameを表示状態にし、AppBar1を非表示状態にします。
NavigateメソッドでDataIchiranShowPageに遷移します。渡す値は無いのでNothingを指定しておきます。

  Private Sub ichiranButton_Click(sender As Object, e As RoutedEventArgs) Handles ichiranButton.Click
    PhotoArea.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

「kuniyasuのアプリ一覧」ボタンがクリックされた時の処理

私の作者名kuniyasuをクエリに指定して、Windows ストアに公開している私のアプリ一覧を表示します。
この画面から、もとの画面に戻るには、画面の左上隅にマウスカーソルを移動し、表示されるこのアプリの小さな画面をタップすると戻ることができます。

  Private Async Sub myApps_Click(sender As Object, e As RoutedEventArgs) Handles myApps.Click
    Dim myAppsUri = New Uri("ms-windows-store:Search?query=kuniyasu")
    Await Windows.System.Launcher.LaunchUriAsync(myAppsUri)
  End Sub
End Class

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

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

リスト4 (DataIchiranShowPage.xaml.vb)

Imports Windows.Storage
Imports Windows.UI.Popups
Imports Windows.UI
Public NotInheritable Class DataIchiranShowPage
  Inherits Page

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

ピクチャライブラリのPhotoAlbumフォルダ内の画像を一覧で表示する、DataShowプロシージャを実行します。

  Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    DataShow()
  End Sub

ピクチャライブラリのPhotoAlbumフォルダ内の画像を一覧で表示する処理

GridView内をクリアします。ピクチャライブラリのPhotoAlbumサブフォルダにアクセスします。
GetFilesAsyncメソッドで、ファイルを取得してコレクション変数myPictureFilesに格納します。Countプロパティでファイルの個数を取得し、ファイルが無い場合は、メッセージを表示して、処理を抜けます。
コレクション変数myPictureFiles内のファイルを変数myFileに格納しながら、以下の処理を繰り返します。
新しいBitmapImageのインスタンスbmpオブジェクトを作成します。SetSourceメソッドに、
Await myFile.OpenReadAsync
と指定し、OpenReadAsyncメソッドで、ランダムアクセスストリームを開き、BitmapSourceのソースイメージに設定します。
新しいImageのインスタンスmyImageオブジェクトを作成します。Widthに512、Heightに384、Sourceプロパティにbmpオブジェクトを指定します。
StackPanelの新しいインスタンスmyStackPanelオブジェクトを作成します。Marginに5を指定して余白を設けます。
新しいTextBlockのインスタンスtitleTextBlockオブジェクトを作成します。Widthに512、文字の回り込みを可とします。Textプロパティに、Path.GetFileNameWithoutExtensionメソッドで、パスと拡張子を除いたファイル名を指定します。文字サイズは26、文字色はGoldとします。
新しいButtonのインスタンスdelButtonを作成します。Contentプロパティに「削除」、Tagプロパティにメンバ変数noの値を文字列にキャストして指定します。どの「削除」ボタンがクリックされたかの判定に使用します。
myStackPanelオブジェクトに、myImage、titleTextBlock、delButtonオブジェクトを追加し、これをGridViewに追加します。画像の下にファイル名、その下に「削除」ボタンの付いた画像の一覧が表示されます。
AddHandlerステートメントで、delButtonがクリックされた時のイベントハンドラを追加します。イベントハンドラ内では以下の処理を行います。
Buttonの情報を保持しているdelSenderオブジェクトをDirectCastでButtonにキャストし、そのTagプロパティの値を取得し、数値に変換して変数delIndexに格納しておきます。
コレクションメンバ変数である、myPictureFiles内のdelIndexに該当する画像ファイルを、DeleteAsyncメソッドで削除します。「削除しました。」のメッセージを表示し、画面を再描画するために、DataShowプロシージャを実行します。
変数noの値を1ずつ加算します。
非同期処理で行われるためメソッドの先頭にAsyncを追加します。

  Private Async Sub DataShow()
    GridView1.Items.Clear()
    Dim no As Integer = 0
    Dim pictureFolder As StorageFolder = KnownFolders.PicturesLibrary
    Dim pictureSubFolder As StorageFolder = Await pictureFolder.CreateFolderAsync("PhotoAlbum", CreationCollisionOption.OpenIfExists)
    Dim myPictureFiles As IReadOnlyList(Of IStorageFile) = Await pictureSubFolder.GetFilesAsync()
    If myPictureFiles.Count = 0 Then
      Dim message As New MessageDialog("画像データがありません。戻ってください。")
      Await message.ShowAsync
      Exit Sub
    End If
    For Each myFile As IStorageFile In myPictureFiles
      Dim bmp As New BitmapImage
      bmp.SetSource(Await myFile.OpenReadAsync)
      Dim myImage As New Image
      myImage.Width = 512
      myImage.Height = 384
      myImage.Source = bmp
 
      Dim myStackPanel As New StackPanel
      myStackPanel.Margin = New Thickness(5)
 
      Dim titleTextBlock As New TextBlock
      With titleTextBlock
        .Width = 512
        .TextWrapping = TextWrapping.Wrap
        .Text = Path.GetFileNameWithoutExtension(myFile.Path)
        .FontSize = 26
        .Foreground = New SolidColorBrush(Colors.Gold)
      End With
      Dim delButton As New Button
      With delButton
        .Content = "削除"
        .Tag = no.ToString
      End With
 
      myStackPanel.Children.Add(myImage)
      myStackPanel.Children.Add(titleTextBlock)
      myStackPanel.Children.Add(delButton)
      GridView1.Items.Add(myStackPanel)
 
      AddHandler delButton.Click, Async Sub(delSender As Object, delArgs As RoutedEventArgs)
                                Dim delIndex = CInt(DirectCast(delSender, Button).Tag)
                                Await myPictureFiles(delIndex).DeleteAsync
                                Dim message As New MessageDialog("削除しました。")
                                Await message.ShowAsync
                                DataShow()
                              End Sub
      no += 1
    Next
  End Sub
End Class

アイコンの作成

詳細については、「自分の現在位置を取得して表示するサンプルプログラム」の記事を参照してください。

今回はここまでです。ありがとうございました。

  • 撮影した写真から最適な1枚を選ぶサンプルプログラム

薬師寺国安事務所

薬師寺国安事務所代表。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メルマガ会員のサービス内容を見る

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