ImageコントロールをButtonコントロールに変換する
ImageコントロールをButtonコントロールに変換する
まずカメラの画像の表示されているImage1を選択し、マウスの右クリックで表示されるメニューから、「コントロールの作成」を選択します(図4)。
| 図4:Image1を選択し、マウスの右クリックで表示されるメニューから「コントロールの作成」を選択(クリックで拡大) |
「コントロールの作成」画面が表示されます。「コントロールの種類」からButtonを選択し、「定義先」の「アプリケーション」にチェックを付け[OK]ボタンをクリックします(図5)。「名前(キー)」はデフォルトのままにしておきます。
| 図5:「コントロールの種類」にButtonを選択し、「定義先」の「アプリケーション」をチェックする(クリックで拡大) |
中央にButtonと表示されたカメラの画像が表示されます。Buttonの文字を選択し、[Delete]キーで削除します。アートボードの上部に表示されている[Button]タブをクリックします。コントロールを配置した画面が表示されます。カメラの画像を選択して、プロパティを見ると「種類」がButtonになっています。「名前」にcameraButtonと指定します(図6)。
| 図6:ImageがButtonに変換されている。Buttonの名前にcameraButtonと指定する(クリックで拡大) |
同様にImage2のフロッピーの画像もButtonに変換します。Buttonの名前はsaveButtonとします。
Expression Blendを終了してVS2010に戻ります。
ImageからButtonに変換した箇所がリスト2のように書き出されています。
リスト2 ImageからButtonに変換されたXAMLコード(MainPage.xamlの一部)
(1)cameraButtonとsaveButtonにStyle属性が持たされ、ButtonStyle1とButtonStyle2を参照しています。ButtonStyle1とButtonStyle2はApp.xaml内で定義されています。saveButtonは最初の状態では、使用不可とするため、IsEnabledのチェックを外しておきます。写真が撮影された時点でsaveButton(フロッピーのアイコン)の使用を可能とします。
(2)ichiranButton(データ一覧)も最初の状態では使用不可としておきます。
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Image Height="356" HorizontalAlignment="Left" Margin="40,71,0,0" x:Name="Image" Stretch="Fill" VerticalAlignment="Top" Width="398" />
<TextBox Height="91" HorizontalAlignment="Left" Margin="-6,485,0,0" x:Name="commentTextBox" VerticalAlignment="Top" Width="456" TextWrapping="Wrap" AcceptsReturn="True" />
<Button Content="データ一覧" Height="72" HorizontalAlignment="Left" Margin="6,624,0,0" Name="ichiranButton" VerticalAlignment="Top" Width="444" IsEnabled="False" /> ■(2)
<TextBlock Height="31" HorizontalAlignment="Left" Margin="12,463,0,0" Name="TextBlock1" Text="コメント" VerticalAlignment="Top" Width="131" />
<TextBlock Height="33" HorizontalAlignment="Left" Margin="140,18,0,0" Name="TextBlock2" Text="カメラは縦向きのみの対応です" VerticalAlignment="Top" Width="298" FontWeight="Bold" Foreground="Crimson" />
<Button x:Name="cameraButton" Content="Button" HorizontalAlignment="Left" Height="45" Margin="40,6,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="61"/> ■(1)
<Button x:Name="saveButton" Content="Button" HorizontalAlignment="Left" Height="46" Margin="190,572,0,0" Style="{StaticResource ButtonStyle2}" VerticalAlignment="Top" Width="50" IsEnabled="False" /> ■(1)
</Grid>
次に、MainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックしてリスト3のコードを記述します。
ロジックコードを記述する
リスト3 (MainPage.xaml.vb)
Option Strict On
ランチャーやチューザーに関するクラスの含まれる、Microsoft.Phone.Tasks名前空間をインポートします。
Imports Microsoft.Phone.Tasks
Imports System.Windows.Media.Imaging
Imports Microsoft.Phone
仮想ファイルシステムを作成および使用するための型が含まれている、System.IO.IsolatedStorage名前空間をインポートします。分離ストレージによって、安全なクライアント側のストレージが提供されます。
Imports System.IO.IsolatedStorage
Imports System.IO
Imports System.Xml.Linq
Partial Public Class MainPage
Inherits PhoneApplicationPage
' コンストラクター
Public Sub New()
InitializeComponent()
End Sub
カメラアプリケーションを起動するCameraCaptureTaskクラス用メンバ変数、myCameraTaskを宣言します。
Dim myCameraTask As CameraCaptureTask
バイト型の配列、imageByteをメンバ変数として宣言します。
Dim imageByte As Byte()
ページがアクティブになった時呼び出されるメソッド
新しいCameraCaptureTaskクラスのインスタンス、myCameraTaskオブジェクトを生成します。
AddHandlerステートメントで、チューザータスクが完了した時に発生するCompletedイベントに、イベントハンドラを追加します。イベントハンドラ内では以下の処理が実行されます。
カメラアプリケーションが起動して、写真がきちんと撮れた場合は、CompositeTransformクラスの新しいインスタンスmyCompositeを生成します。CompositeTransformクラスは、1 つのオブジェクトに複数の異なる変換を適用することができるクラスです。CenterXとCenterYプロパティに、撮った画像が表示されるImageコントロールのWidthとHeightの約半分のサイズを指定します。CenterXプロパティでは、CompositeTransform で指定された、全ての変換の中心点の x 座標を設定します。CenterYプロパティでは、CompositeTransform で指定された、全ての変換の中心点の y 座標を設定します。回転を表すRotationに90を指定します。カメラを縦向きで撮った画像もデフォルトでは横向きに表示されるため、90度回転して縦向きに表示されるようにしています。
写真のデータを含む、ストリームのバイトの長さを取得し、バイト配列を作成します。Readメソッドで、現在のストリームからバイトシーケンスを読み取り、読み取ったバイト数でストリーム内の位置を進めます。
ChosenPhoto.Readの書式は以下の通りです。
ChosenPhoto.Read(バイト配列,0ベースのバイトオフセット(現在のストリームから読み取ったデータの格納を開始します),現在のストリームから読み取るバイトの最大数)
Seekメソッドで、現在のストリーム内の位置を設定します。書式は以下の通りです。
ChosePhoto.Seek(基点のパラメーターのバイト オフセット, 参照ポイントを示すSeekOrigin型の値)
SeekOriginにはBeginを指定し、ストリームの先頭を指定しています。
WriteableBitmap型の変数imageSourceを宣言し、PictureDecoder.DecodeJpeg(resultArgs.ChosenPhoto)で、撮った写真をJPEGファイルとしてWriteableBitmapオブジェクトにデコードします。PictureDecoder.DecodeJpegメソッドはMicrosof.Phone名前空間に属しています。WriteableBitmapクラスは書き込み更新することのできるBitmapSourceを提供するクラスです。
ImageのRenderTransformプロパティにmyCompsiteオブジェクトを指定して、Image領域を90度回転し、Sourceプロパティに、デコードされたJPEGファイルを格納しているimageSourceオブジェクトを指定します。これでImage内に撮った写真が表示されます。
カメラを起動している状態で撮影を中止した場合は、saveButton(フロッピーのアイコン)は使用不可のままで処理を抜けます。
変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。Path.Combineメソッドで、2つの文字列を1つのパスに結合します。ここでは、myPicturesフォルダとimageFileList.xmlを結合しています。myPictures\imageFileList.xmlとなります。この値をfilePath変数に格納します。FileExistsメソッドでfilePathに格納したファイルが存在する場合は、ichiranButton(データ一覧)の使用を可能にします。そうでない場合は、不可のままです。
Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
myCameraTask = New CameraCaptureTask
AddHandler myCameraTask.Completed, Sub(resultSender As Object, resultArgs As PhotoResult)
If resultArgs.TaskResult = TaskResult.OK Then
Dim myComposite As New CompositeTransform
myComposite.CenterX = 189
myComposite.CenterY = 173
myComposite.Rotation = 90
imageByte = New Byte(CInt(resultArgs.ChosenPhoto.Length)) {}
resultArgs.ChosenPhoto.Read(imageByte, 0, imageByte.Length)
resultArgs.ChosenPhoto.Seek(0, IO.SeekOrigin.Begin)
Dim imageSource As WriteableBitmap = PictureDecoder.DecodeJpeg(resultArgs.ChosenPhoto)
Image.RenderTransform = myComposite
Image.Source = imageSource
Else
saveButton.IsEnabled = False
Exit Sub
End If
End Sub
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
Dim xmlFilePath As String = Path.Combine("myPictures", "imageFileList.xml")
If storage.FileExists(xmlFilePath) = True Then
ichiranButton.IsEnabled = True
Else
ichiranButton.IsEnabled = False
End If
MyBase.OnNavigatedTo(e)
End Sub
カメラアイコンがタップされた時の処理
Showメソッドでカメラアプリケーションを起動します。saveButton(フロッピーのアイコン)の使用を可能にします。
Private Sub cameraButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles cameraButton.Click
myCameraTask.Show()
saveButton.IsEnabled = True
End Sub
フロッピーのアイコン(保存)がタップされた時の処理
保存する画像のファイル名を作成します。現在の「年月日時間分秒.jpg」のファイル名とし、imageFileNameに格納しておきます。
変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。DirectryExistsメソッドでmyPicturesというフォルダが存在しているかどうかをチェックし、存在していない場合は、CreateDirectoryメソッドでmyPicturesというフォルダを作成します。
Path.CombineでmyPicturesというフォルダとimageFileNameに格納されている画像名とを連結します。
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数myStream変数を用意し、IsolatedStorageFile.CreateFileメソッドで、分離ストレージ内にfilePath変数の持っているフォルダ名付き画像ファイル名を作成します。次に、IsolatedStorageFileStream.Writeメソッドで、バイト配列から読み取ったデータを使用して、IsolatedStorageFileStreamオブジェクトにバイトのブロックを書き込みます。
IsolatedStorageFileStream.Writeメソッドの書式は下記の通りです。
IsolatedStorageFileStream.Write(書き込むバッファ, 開始位置を示すバッファ内のバイト オフセット,書き込む最大バイト数)
変数xmlStorageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。Path.Combineで、myPicturesというフォルダ名と、imageFileList.xmlという画像ファイル名を記録したXMLファイルを連結し、xmlFilePath変数に格納しておきます。
myPicturesというフォルダ内にimageFileList.xmlが存在していない場合は、Visual Basic の埋め込み式を用いて、XML宣言とルート要素image、その子要素としてfileName、属性にimageFileNameを指定し、埋め込み式の構文である <%= expression %>を用いてimageFileName変数の値を指定します。また、fileNameの内容テキストには、commentTextBox.Textの値を指定します。これは ASP.NET で使用される構文と同じです。 分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数xmlStreamを用意し、IsolatedStorageFile.CreateFileメソッドで、分離ストレージ内にxmlFilePath変数の持っているフォルダ名付きXMLファイルを作成します。
imageFileList.xmlファイルが存在する場合は、新しいStreamWriter 生成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードでファイルを開き、初期化します。Writeメソッドで埋め込み式のXMLをストリームに書き込みます。保存した旨のメッセージを表示します。
次は、既にmyPicturesフォルダ内にimageFileList.xmlが存在する場合の処理です。
IsolatedStorageFileクラスのOpenFileメソッドでmyPicturesフォルダ内のimageFileList.xmlファイルを、指定したファイルアクセスを使用して指定したモードでファイルを開きます。開いたファイルをStreamReaderで読み込みます。ReadToEndメソッドでファイルの最後まで読み取り変数readXmldoc変数に格納しておきます。読み込んだXMLテキストをParseメソッドでXElementとして読み込みます。
追加するfileName要素を、埋め込み式を用いて生成し、imageFileName属性の値や、fileNameの内容テキストを指定します。新しく生成したXML要素を、読み込んだXMLにAddメソッドで追加します。IsolatedStorageFileStreamを閉じます。
imageFileList.xmlファイルが存在する場合は、新しいStreamWriter 生成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードでファイルを開き、初期化します。Writeメソッドで新しいXML要素が追加されたXMLを、ストリームに書き込みます。保存した旨のメッセージを表示します。
「データ一覧」ボタンの使用を可能にし、コメント欄と画像の表示されていた領域をクリアします。フロッピーアイコンの保存ボタンの使用を不可とします。
Private Sub saveButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles saveButton.Click
'画像の保存
Dim imageFileName As String=DateTime.Now.ToString("yyyyMMddHHmmss") & ".jpg"
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
If storage.DirectoryExists("myPictures") = False Then
storage.CreateDirectory("myPictures")
End If
Dim filePath As String = Path.Combine("myPictures", imageFileName)
Using myStream As IsolatedStorageFileStream = storage.CreateFile(filePath)
myStream.Write(imageByte, 0, imageByte.Length)
End Using
'XMLファイルの保存
Dim xmlStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
Dim xmlFilePath As String = Path.Combine("myPictures", "imageFileList.xml")
If xmlStorage.FileExists(xmlFilePath) = False Then
Dim xmldoc As XDocument = <?xml version="1.0" encoding="utf-8"?>
<image>
<fileName imageFileName=<%= imageFileName %>><%= commentTextBox.Text %></fileName>
</image>
Using xmlStream As IsolatedStorageFileStream = xmlStorage.CreateFile(xmlFilePath)
End Using
If xmlStorage.FileExists(xmlFilePath) = True Then
Using xmlwriter As StreamWriter = New StreamWriter(xmlStorage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Write))
xmlwriter.Flush()
xmlwriter.Write(xmldoc.ToString)
End Using
MessageBox.Show("画像とXMLファイルを保存しました。")
End If
Else
Dim xmlStream As IsolatedStorageFileStream = xmlStorage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Read)
Using xmlreader As StreamReader = New StreamReader(xmlStream)
Dim readXmldoc As String = xmlreader.ReadToEnd
Dim doc As XElement = XElement.Parse(readXmldoc)
Dim addXml As XElement = <fileName imageFileName=<%= imageFileName %>><%= commentTextBox.Text %></fileName>
doc.Add(addXml)
xmlStream.Close()
If xmlStorage.FileExists(xmlFilePath) = True Then
Using xmlwriter As StreamWriter = New StreamWriter(storage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Write))
xmlwriter.Flush()
xmlwriter.Write(doc.ToString)
MessageBox.Show("画像とXMLファイルを保存しました。")
End Using
End If
End Using
End If
ichiranButton.IsEnabled = True
commentTextBox.Text = String.Empty
Image.Source = Nothing
saveButton.IsEnabled = False End Sub
[データ一覧]ボタンがクリックされた時の処理
これから作成する、DataShowPage.xamlに遷移します。
Private Sub ichiranButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles ichiranButton.Click
NavigationService.Navigate(New Uri("/DataShowPage.xaml", UriKind.Relative))
End Sub
End Class
- この記事のキーワード

