写真を切りぬいて新しい写真を撮影するサンプル

2012年6月15日(金)
PROJECT KySS

「Windows Phone 縦向きのページ」(DataIchiranPage.xaml)の作成

VS2010メニューの「プロジェクト(P)/新しい項目の追加(W)」と選択し、「Windows Phone 縦向きのページ」を選択します。「名前(N)」にはDataIchiranPage.xamlと入力します。

(※)コード解説については、「カメラに画像フレームを配置して撮影する」のDataIchiranPage.xaml
とDataIchiranPage.xaml.vbとほとんど同じ処理になりますので、DataIchiranPage.xaml.vbのコードだけリスト3に掲載します。解説については上記記事のDataIchiranPage.xaml.vbの解説を参照してください。

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

リスト3 (DataIchiranPage.xaml.vb)

Option Strict On
Imports System.Xml.Linq
Imports System.IO.IsolatedStorage
Imports System.IO
Imports System.Windows.Media.Imaging
Imports Microsoft.Phone

Public Class ImageInfo
  Property PictureName As ImageSource
  Property RecordDate As String
End Class

Partial Public Class DataIchiranPage
  Inherits PhoneApplicationPage
 
  Public Sub New()
    InitializeComponent()
  End Sub
 
  Dim doc As XElement

  
  Dim myMenuItem1 As New MenuItem
  Dim myMenuItem2 As New MenuItem
  
  Dim myIndex As Integer
  Dim myContextMenu As New ContextMenu
 
  Dim recordDate As String
  
  Dim imageName As String

ページがアクティブになった時に呼び出されるメソッド

  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    Dim filePath As String = Path.Combine("CameraInCamera", "ImageList.xml")
 
    If storage.FileExists(filePath) = False Then
      MessageBox.Show("表示できるデータはありません。")
      Exit Sub
    End If
    Dim myStream As IsolatedStorageFileStream = storage.OpenFile(filePath, FileMode.Open, FileAccess.Read)
    Using reader As StreamReader = New StreamReader(myStream)
      Dim readXmldoc As String = reader.ReadToEnd
      doc = XElement.Parse(readXmldoc)
      Dim myImageInfo As New List(Of ImageInfo)
 
      For Each result In From c In doc.Descendants("Picture") Select c
 
        Dim imageFilePath As String = Path.Combine("CameraInCamera", result.Element("PictureName").Value)
        Dim imageStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
        Using stream As IsolatedStorageFileStream = imageStorage.OpenFile(imageFilePath, FileMode.Open, FileAccess.Read)
          Dim imageSource As WriteableBitmap = PictureDecoder.DecodeJpeg(stream)
          With myImageInfo
           .Add(New ImageInfo With {.PictureName = imageSource, .RecordDate = result.Attribute("RecordDate").Value})
          End With
        End Using
      Next
      dataListBox.ItemsSource = myImageInfo
    End Using
    MyBase.OnNavigatedTo(e)
  End Sub

リストボックスから任意の画像が選択された時の処理

  Private Sub dataListBox_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles dataListBox.SelectionChanged
    Try
      myIndex = dataListBox.SelectedIndex
 
      recordDate = doc.Descendants("Picture")(myIndex).Attribute("RecordDate").Value
      imageName = doc.Descendants("Picture")(myIndex).Element("PictureName").Value
 
      Dim menuItemList As New List(Of MenuItem)
 
      myMenuItem1.Header = "データの削除"
      myMenuItem1.Foreground = New SolidColorBrush(Colors.Red)
      myMenuItem1.FontSize = 25
      myMenuItem1.FontWeight = FontWeights.Bold
 
      myMenuItem2.Header = "キャンセル"
      myMenuItem2.FontSize = 25
      myMenuItem2.FontWeight = FontWeights.Bold
 
      menuItemList.Add(myMenuItem1)
      menuItemList.Add(myMenuItem2)
 
      myContextMenu.ItemsSource = menuItemList
      myContextMenu.Opacity = 0.8
      myContextMenu.IsZoomEnabled = True
 
      ContextMenuService.SetContextMenu(dataListBox, myContextMenu)
      myContextMenu.UpdateLayout()
      myContextMenu.IsOpen = True
 
      RemoveHandler myMenuItem1.Click, AddressOf myMenuItem_Click
      AddHandler myMenuItem1.Click, AddressOf myMenuItem_Click
      AddHandler myMenuItem2.Click, AddressOf myMenuItem_Click
    Catch
      Exit Sub
    End Try
  End Sub

ContextMenuに表示されたメニューがタップされた時の処理

  Private Sub myMenuItem_Click(sender As Object, e As EventArgs)
    Try
      Dim selectHeader = DirectCast(sender, MenuItem).Header
 
      Select Case selectHeader.ToString
    
        Case "データの削除"
          Dim kakunin = MessageBox.Show("このデータを削除しますか?", "削除確認", MessageBoxButton.OKCancel)
 
          Select Case kakunin
            Case MessageBoxResult.OK
              DeleteData()
              Exit Select
            Case Else
              dataListBox.SelectedIndex = -1
              Exit Sub
            End Select
          Case "キャンセル"
            myContextMenu.IsOpen = False
            dataListBox.SelectedIndex = -1
            Exit Select
          Case Else
            dataListBox.SelectedIndex = -1
            Exit Select
      End Select
    Catch
      Exit Sub
    End Try
  End Sub

データを削除する処理

  Sub DeleteData()
    Dim delXml As XElement
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    Dim filePath As String = Path.Combine("CameraInCamera", "ImageList.xml")
    If storage.FileExists(filePath) = True Then
      Dim myStream As IsolatedStorageFileStream = storage.OpenFile(filePath, FileMode.Open, FileAccess.Read)
      Using reader As StreamReader = New StreamReader(myStream, System.Text.Encoding.UTF8)
        Dim readXmldoc As String = reader.ReadToEnd
        delXml = XElement.Parse(readXmldoc)
        myStream.Close()
      End Using
 
      Dim myRecordDate As String = delXml.Descendants("Picture")(myIndex).Attribute("RecordDate").Value
      
      Dim delImage As String = delXml.Descendants("Picture")(myIndex).Element("PictureName").Value
      Dim delJPGfile As String = Path.Combine("CameraInCamera", delImage)
      If delImage <> String.Empty Then
        storage.DeleteFile(delJPGfile)
        'NavigationService.RemoveBackEntry()
      End If
 
      Dim delElement = delXml.Descendants("Picture")(myIndex)
      delElement.Remove()
      Using stream As IsolatedStorageFileStream = New IsolatedStorageFileStream(filePath, FileMode.Create, FileAccess.Write, storage)
        delXml.Save(stream)
      End Using
      MessageBox.Show(myRecordDate & "のデータを削除しました。")
 
      Dim allDeleteQuery = From c In delXml.Descendants("Picture") Select c
 
      If allDeleteQuery.Count <= 0 Then
        storage.DeleteFile(filePath)
        storage.Dispose()
        NavigationService.Navigate(New Uri(String.Format("/MainPage.xaml?date={0}", DateTime.Now.ToShortDateString & DateTime.Now.ToLongTimeString), UriKind.Relative))
        Exit Sub
      End If
 
      storage.Dispose()
      NavigationService.Navigate(New Uri(String.Format("/DataIchiranPage.xaml?date={0}", DateTime.Now.ToShortDateString & DateTime.Now.ToLongTimeString), UriKind.Relative))
    Else
      storage.Dispose()
      Exit Sub
    End If
  End Sub

Backボタン(←)がタップされた時の処理

 Protected Overrides Sub OnBackKeyPress(e As System.ComponentModel.CancelEventArgs)
  dataListBox.SelectedIndex = -1
  Dim myStackCount = NavigationService.BackStack.Count
  For i As Integer = 0 To myStackCount - 2
  NavigationService.RemoveBackEntry()
  Next
  MyBase.OnBackKeyPress(e)
  End Sub
  End Class

今回のサンプルは以上で終了です。

【参照リンク】

PROJECT KySSでは現在、16個のWindows PhoneアプリをMarketplaceに公開しています。試用版もありますので、興味のある方はお試しください。
→参照:Windows Phone App Information(PROJECT KySS)

  • 写真を切りぬいて新しい写真を撮影するサンプル

四国の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メルマガ会員のサービス内容を見る

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