選択した画像をトリミングして保存させるには2カ月で160本作った還暦開発者が送る10のアプリ開発ノウハウ(9)(3/4 ページ)

» 2013年12月10日 18時00分 公開
[薬師寺国安,PROJECT KySS]

メイン画面のロジックコードを記述する(MainWindow.xaml.vb)

 次に、[ソリューション・エクスプローラー]内の「MainWindow.xaml」を展開して表示される、「MainWindow.xaml.vb」のコードを記述する。

 ここでは、コードが長くなるため今回のテーマと肝となる「画像の合成」「データの一覧表示」部分の解説にとどめている。名前空間の読み込み、メンバー変数の宣言も省略している。全てのコードを見る場合は、サンプルをダウンロードして「MainWindow.xaml.vb」ファイルを見ていただきたい。

ページがアクティブになったときの処理(OnNavigatedToメソッド処理)

  1. Protected Overrides Async Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
  2. Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
  3. Dim SubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists)
  4. myPictureFiles = Await SubFolder.GetFilesAsync
  5. If myPictureFiles.Count > 0 Then
  6. allDeleteButton.IsEnabled = True
  7. deleteButton.IsEnabled = True
  8. Else
  9. allDeleteButton.IsEnabled = False
  10. deleteButton.IsEnabled = False
  11. End If
  12. Await AddPhoto()
  13. MyBase.OnNavigatedTo(e)
  14. End Sub

 以降、上記コードの中身を詳細に見ていこう。

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

 次に、ピクチャライブラリにアクセスし、CreateFolderAsyncメソッドで「TrimingImage」というフォルダーを作成する。その際、CreationCollisionOption.OpenIfExistsを指定すると、同名フォルダーがあるときは、そのフォルダー名を返し、ないときは新規に作成する。

 CreationCollisionOption Enumerationの詳細については、下記のURLを参照してほしい。

 GetFilesAsyncメソッドで「TrimingImage」フォルダー内のファイルを取得し、メンバー変数「myPictureFiles」で参照しておく。

 Countプロパティで、そのフォルダー内のファイルの数を取得し、ファイルが存在する場合は、「削除」と「一括削除」ボタンの使用を可能にする。それ以外は使用を不可とする。

 切り出した画像が保存されている場合は、GridViewに画像の一覧を表示する、AddPhotoタスクを実行する。

ドラッグしたときの処理(ContentPanel_ManipulationDeltaメソッドの処理)

  1. Private Sub ContentPanel_ManipulationDelta(sender As Object, e As ManipulationDeltaRoutedEventArgs) 'Handles ContentPanel.ManipulationDelta
  2. 'エラー処理をしていないとトリミング時にエラーが発生する
  3. Try
  4. Rectangle1.Width = e.Cumulative.Translation.X
  5. Rectangle1.Height = e.Cumulative.Translation.Y
  6. Catch
  7. e.Handled = False
  8. Exit Sub
  9. End Try
  10. End Sub

 ここでは、「e.Cumulative.Translation.X」「e.Cumulative.Translation.Y」でx-y画面座標を取得し、RectangleのWidthとHeightに設定する。矩形で描かれたWidthとHeightの値を、RectangleのWidthとHeightの値に指定するということだ。

タッチを開始したときの処理(ContentPanel_ManipulationStartedメソッドの処理)

  1. Private Sub ContentPanel_ManipulationStarted(sender As Object, e As ManipulationStartedRoutedEventArgs)
  2. Rectangle1.Margin = New Thickness(e.Position.X, e.Position.Y, 0, 0)
  3. Rectangle1.Width = 0
  4. Rectangle1.Height = 0
  5. If flag = True Then
  6. Rectangle1.Visibility = Windows.UI.Xaml.Visibility.Collapsed
  7. Button1.IsEnabled = False
  8. Else
  9. Rectangle1.Visibility = Windows.UI.Xaml.Visibility.Visible
  10. Button1.IsEnabled = True
  11. End If
  12. End Sub

 RectangleのMarginプロパティに、タッチした位置に合わせてRectangleを移動した位置を指定する。Marginプロパティの書式は下記の通りだ。

FrameworkElement.Margin(left,,top, right, buttom)

 例えば、「Margin="10"」は全てのプロパティが10に設定される。またMargin=”10,20”はLeftとRightが10、TopとBottomが20に設定されたThicknessとして解釈される。

 Marginプロパティの値は「New Thickness(Left、Top、Right、Bottom)」と指定する。この場合はleftにe.Position.Xを、topにe.Position.Yの値を指定している。

 RectangleのWidthとHeightは「0」で初期化する。

 メンバー変数「flag」の値で条件分岐を行う。Trueであった場合、つまり一覧表示されている切り出された画像が画面上に表示されていた場合は、トリミングができないように、Rectangle1を非表示にし、「切り出す」ボタンの使用を不可とする。それ以外の場合は、トリミングを可能にし、「切り出す」ボタンの使用を可能にする。

矩形上でドラッグしたときの処理(Rectangle1_ManipulationDeltaメソッドの処理)

  1. Private Sub Rectangle1_ManipulationDelta(sender As Object, e As ManipulationDeltaRoutedEventArgs)
  2. Rectangle1.Margin = New Thickness(Rectangle1.Margin.Left + e.Delta.Translation.X, Rectangle1.Margin.Top + e.Delta.Translation.Y, 0, 0)
  3. e.Handled = True
  4. End Sub

 ここでは、矩形の位置をドラッグした移動量分だけ動かす。「e.Delta.Translation.X」「e.Delta.Translation.Y」でx-y画面座標の変化を取得している。「e.Handled=True」と指定して、Gridにイベントが伝わらないようにする。

「画像選択」ボタンがタップされたときに実行されるSelectImageタスク処理

  1. Private Async Function SelectImage() As Task
  2. Dim myFileOpenPicker As New FileOpenPicker
  3. myFileOpenPicker.ViewMode = PickerViewMode.Thumbnail
  4. myFileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary
  5. myFileOpenPicker.FileTypeFilter.Add(".png")
  6. myFileOpenPicker.FileTypeFilter.Add(".jpg")
  7. myFile = Await myFileOpenPicker.PickSingleFileAsync()
  8. If myFile Is Nothing = False Then
  9. flag = False
  10. FileName = myFile.Path
  11. myBmp.SetSource(Await myFile.OpenReadAsync)
  12. Image1.Source = myBmp
  13. If myBmp.PixelWidth <> 640 OrElse myBmp.PixelHeight <> 480 Then
  14. Dim myMessage As New MessageDialog("画像サイズは640×480限定です。切り出しはできません。")
  15. Await myMessage.ShowAsync
  16. Image1.Source = Nothing
  17. Button1.IsEnabled = False
  18. Else
  19. Button1.IsEnabled = False
  20.         End If
  21. End If
  22. End Function

 以降、上記コードの中身を詳細に見ていこう。

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

 次に、FileOpenPickerクラスの新しいインスタンスmyFileOpenPickerオブジェクトを作成する。FileOpenPickerクラスは、ユーザーが選択し、ファイルを開くことのできるUI要素を表すクラスだ。

 ファイルの表示モードを指定するViewModeプロパティにサムネイル表示を指定する。サムネイル表示の他にリスト(List)表示がある。ファイルを開く最初の場所を設定する、SuggestedStartLocationプロパティにピクチャライブラリを指定しておく。

 開くファイルタイプを指定するFileTypeFilter.Addで「.png」「.jpg」を指定しておく。PNGファイルを指定する場合は、「FileTyleFilter.Add(".png")」と指定する。"*.png"ではないので、注意してほしい。

 PickSingleFileAsynメソッドで、ユーザーが1つのファイルを選択できるようにファイルピッカーを表示し、変数「myFile」で参照する。変数「myFile」がファイルを参照している場合は、メンバー変数「flag」にFalseを指定し、トリミングを可能にしておく。選択された画像のファイルシステムパス名(myFile.Path)を、メンバー変数「FileName」に格納しておく。

 新しいBitmapImageクラスのインスタンスmyBmpオブジェクトに、SetSourceメソッドで「Await myFile.OpenReadAsync」と指定して、ファイルの内容を読み込むために、現在のファイルを、ランダムアクセスストリームで開く。

 Image1のSourceプロパティにmyBmpオブジェクトを指定する。これで、ファイルピッカーで指定したファイルが表示される。

 もし指定したファイルの画像サイズが640×480より大きかった場合は、メッセージを表示し、画像は表示せず、[切り取り]ボタンの使用も不可とする。

 また、画像を選択する際、選択をやめてキャンセルした場合も、[切り取り]ボタンの使用は不可としておく。

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

Smart & Social 鬯ッ�ッ�ス�ョ�ス�ス�ス�ォ�ス�ス�ス�ス�ス�ス�ス�ェ鬯ョ�ッ陋ケ�コ�ス�サ郢ァ謇假スス�ス�ス�ソ�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�コ鬯ョ�」陋ケ�ス�ス�ス�ス�オ鬮ォ�エ遶擾スオ�ス�コ�ス�キ�ス�ス�ス�ク�ス�ス�ス�キ�ス�ス�ス�ス�ス�ス�ス�ケ鬮ォ�エ髮懶ス」�ス�ス�ス�「�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ウ鬯ッ�ゥ陝キ�「�ス�ス�ス�「�ス�ス�ス�ス�ス�ス�ス�ァ�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ュ鬯ッ�ゥ陝キ�「�ス�ス�ス�「鬮ォ�エ髮懶ス」�ス�ス�ス�「�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ウ鬯ッ�ゥ陝キ�「�ス�ス�ス�「�ス�ス�ス�ス�ス�ス�ス�ァ�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ー

鬯ッ�ョ�ス�ォ�ス�ス�ス�エ鬮ッ譎「�ス�キ�ス�ス�ス�「�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ャ鬯ッ�ョ�ス�ォ�ス�ス�ス�エ鬯ッ�イ�ス�ス�ス�シ陞滂スイ�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�ス�・鬯ッ�ョ�ス�ォ�ス�ス�ス�エ鬮ッ譎「�ス�カ�ス�ス�ス�キ�ス�ス�ス�ス�ス�ス�ス�」�ス�ス�ス�ス�ス�ス�ス�ッ鬯ョ�」陷エ�ス�ス�ス�ス�ォ�ス�ス�ス�ス�ス�ス�ス�」

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。