カメラに配置した装飾アイテムを移動・変形させるサンプル

2012年6月18日(月)
PROJECT KySS

次に、MainPage.xamlを展開して表示されるMainPage.xaml.vbをダブルクリックして、リスト3のコードを記述します。

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

リスト3 (MainPage.xaml.vb)

Option Strict On
Imports System.Xml.Linq
Imports System.IO
Imports System.IO.IsolatedStorage

KanjiInfoクラス内にkanjiImage、reading、meaningというプロパティを定義しておきます。

Public Class KanjiInfo
  Property kanjiImage As String
  Property reading As String
  Property meaning As String
End Class
Partial Public Class MainPage
  Inherits PhoneApplicationPage
  
  ' コンストラクター
  Public Sub New()
    InitializeComponent()
  End Sub

新しいMenuItemクラスのインスタンス、myMenuItem1~myMenuItem7をメンバ変数として宣言します。MenuItemクラスは、ContextMenu 内に表示される個別の項目を表すクラスです。

  Dim myMenuItem1 As New MenuItem
  Dim myMenuItem2 As New MenuItem
  Dim myMenuItem3 As New MenuItem
  Dim myMenuItem4 As New MenuItem
  Dim myMenuItem5 As New MenuItem
  Dim myMenuItem6 As New MenuItem
  Dim myMenuItem7 As New MenuItem
 
  Dim kanjiIndex As Integer

ContextMenuクラスの新しいインスタンスmyContextMenuオブジェクトをメンバ変数として宣言します。ContextMenuコントロールは、コントロールのコンテキストに固有の機能を公開するポップアップメニューを表示するコントロールです。このコントロールは、Silverlight for Windows Phone Toolkit - Nov 2011.msiに含まれていますので、下記URLよりダウンロードしてインストールしてください。
→参照:Windows Phone Toolkit - Nov 2011 (7.1 SDK)(CodePlex)

  Dim myContextMenu As New ContextMenu
 
  Dim xmldoc As XElement
  Dim kanjiImageName As String
  Dim myReading As String
  Dim myMeaning As String

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

変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。分離ストレージ内にMultiTouchBehaviorというフォルダがない場合は、CreateDirectoryメソッドでMultiTouchBehaviorというフォルダを作成します。

XElement.LoadメソッドでXML文書ファイル(kanji.xml)を読み込みます。

KanjiInfoクラス型の新しいリストであるmyKanjiInfoオブジェクトを作成します。Descendantsメソッドで、子孫要素である全ての 要素のコレクションを選択し、各要素を、変数resultに格納しながら、以下の処理を繰り返します。

新しいKanjiInfoクラスのkanjiImageプロパティに、Imageフォルダを連結した要素の内容テキストを指定します。readingプロパティには要素の属性”reading”の値を指定します。meaningプロパティには要素の属性”meaning”の値を指定し、AddメソッドでmyKanjiInfoオブジェクトに追加していきます。

ListBoxのItemsSourceプロパティにmyKanjiInfoオブジェクトを指定します。これで、四文字熟語の画像一覧が表示されます。

  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    If storage.DirectoryExists("MultiTouchBehavior") = False Then
      storage.CreateDirectory("MultiTouchBehavior")
    End If
 
    xmldoc = XElement.Load("kanji.xml")
 
    Dim myKanjiInfo As New List(Of KanjiInfo)
    For Each result In From c In xmldoc.Descendants("name") Select c
      With myKanjiInfo
        .Add(New KanjiInfo With {.kanjiImage = "Image/" & result.Value, .reading = result.Attribute("reading").Value, .meaning = result.Attribute("meaning").Value})
      End With
    Next
    kanjiListBox.ItemsSource = myKanjiInfo
    MyBase.OnNavigatedTo(e)
  End Sub

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

メンバ変数kanjiImageNameにListBoxより選択された項目をKanjiInfoクラスにキャストし、そのkanjiImageプロパティの値を格納します。メンバ変数myReadingに、ListBoxより選択された項目をKanjiInfoクラスにキャストし、そのreadingプロパティの値を格納します。メンバ変数myMeaningに、ListBoxより選択された項目をKanjiInfoクラスにキャストし、そのmeaningプロパティの値を格納します。

MenuItem型の新しいリストであるmenuItemListオブジェクトを作成し、各プロパティの設定されたmyMenuItem1~myMenuItem7までのオブジェクトをAddメソッドで追加していきます。
myMenuItem2のHeaderにはmyReadingの値を指定します。
myMenuItem4のHeaderプロパティには新しいTextBlockを作成します。TextプロパティにmyMeaningの値を指定して文字の回り込みを可能にし、Widthに350、HeightにはAutoを意味するDouble.NaNを指定します。
ContextMenuのItemsSourceにmenuItemListオブジェクトを指定します。

変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。

分離ストレージ内のMultiTouchBehaviorフォルダ内にImageList.xmlファイルが存在していない場合は、「データ一覧」のMenuItemを使用不可とします。それ以外は使用可能にします。

ContextMenuService.SetContextMenu メソッドでListBoxオブジェクトにmyContextMenuオブジェクトの値を設定します。IsOpenメソッドでコンテキストメニューを開きます。

AddHandlerステートメントでmyMenuItem5~myMenuItem7のClickイベントにmyMenuItem_Clickのイベントハンドラを指定します。myMenuItem1~myMenuItem4までは、項目名とその内容ですので、イベントハンドラを指定する必要はありません。

  Private Sub kanjiListBox_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles kanjiListBox.SelectionChanged
    Try
      kanjiImageName = DirectCast(kanjiListBox.SelectedItem, KanjiInfo).kanjiImage
      myReading = DirectCast(kanjiListBox.SelectedItem, KanjiInfo).reading
      myMeaning = DirectCast(kanjiListBox.SelectedItem, KanjiInfo).meaning
      Dim menuItemList As New List(Of MenuItem)
 
      With myMenuItem1
        .Header = "読み"
        .FontSize = 25
        .FontWeight = FontWeights.Bold
        .Foreground = New SolidColorBrush(Colors.Red)
        .Background = New SolidColorBrush(Colors.LightGray)
      End With
 
      With myMenuItem2
        .Header = myReading
        .FontSize = 28
        .Foreground = New SolidColorBrush(Colors.Blue)
        .Background = New SolidColorBrush(Colors.LightGray)
      End With
 
      With myMenuItem3
        .Header = "意味"
        .FontSize = 25
        .FontWeight = FontWeights.Bold
        .Foreground = New SolidColorBrush(Colors.Red)
        .Background = New SolidColorBrush(Colors.LightGray)
      End With
 
      With myMenuItem4
        .Header = New TextBlock With {.Text = myMeaning, .TextWrapping = TextWrapping.Wrap, .Width = 350, .Height = Double.NaN}
        .FontSize = 21
        .Foreground = New SolidColorBrush(Colors.Blue)
        .Background = New SolidColorBrush(Colors.LightGray)
      End With
 
      With myMenuItem5
        .Header = "この文字を入れて写真を撮る"
        .FontSize = 22
        .FontWeight = FontWeights.Bold
      End With
 
      With myMenuItem6
        .Header = "データ一覧"
        .FontSize = 22
        .FontWeight = FontWeights.Bold
      End With
 
      With myMenuItem7
        .Header = "キャンセル"
        .FontSize = 22
        .FontWeight = FontWeights.Bold
      End With
 
      menuItemList.Add(myMenuItem1)
      menuItemList.Add(myMenuItem2)
      menuItemList.Add(myMenuItem3)
      menuItemList.Add(myMenuItem4)
      menuItemList.Add(myMenuItem5)
      menuItemList.Add(myMenuItem6)
      menuItemList.Add(myMenuItem7)
 
      myContextMenu.ItemsSource = menuItemList
    
      Dim isolate As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
      If isolate.FileExists(Path.Combine("MultiTouchBehavior", "ImageList.xml")) = False Then
        myMenuItem6.IsEnabled = False
      Else
        myMenuItem6.IsEnabled = True
      End If

 
      ContextMenuService.SetContextMenu(kanjiListBox, myContextMenu)
      myContextMenu.IsOpen = True
 
      AddHandler myMenuItem5.Click, AddressOf myMenuItem_Click
      AddHandler myMenuItem6.Click, AddressOf myMenuItem_Click
      AddHandler myMenuItem7.Click, AddressOf myMenuItem_Click
 
    Catch
      Exit Sub
    End Try
  End Sub

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

senderオブジェクトからMenuItemのHeaderプロパティの情報を取得して、変数selectHeaderに格納しておきます。selectHeaderの値で条件分岐を行います。

値が「この文字を入れて写真を撮る」の場合は、選択された四文字熟語のファイルを引数に、これから作成するCatchPhotoPage.xamlに遷移します。

「データ一覧」の場合は、これから作成するDataIchiranPage.xamlに遷移します。

 Private Sub myMenuItem_Click(sender As Object, e As EventArgs)

  Try

  Dim selectHeader = DirectCast(sender, MenuItem).Header

Select Case selectHeader.ToString
Case "この文字を入れて写真を撮る"
NavigationService.Navigate(New Uri(String.Format("/CatchPhotoPage.xaml?imagename={0}", kanjiImageName), UriKind.Relative))
Exit Select
Case "データ一覧"
NavigationService.Navigate(New Uri("/DataIchiranPage.xaml", UriKind.Relative))
Exit Select
Case "キャンセル"
myContextMenu.IsOpen = False
kanjiListBox.SelectedIndex = -1
Exit Select
Case Else
kanjiListBox.SelectedIndex = -1
Exit Select
End Select
Catch
Exit Sub
End Try
End Sub
End Class

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

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

CatchPhotoPage.xamlの編集とコントロールの追加

InkPresenterコントロールを配置し、その子要素となるようにRectangle(Rectangle1)とImage(backgroundImage)コントロールを配置します。書き出されるXAMLコードをリスト4のように編集します。

リスト4 編集されたXAMLコード(CatchPhotoPage.xaml)

(1)要素を配置しています。

(2)プロパティ要素内に要素を配置しx:NameにmyVideoBrushと指定しておきます。VideoBrushは、ビデオ コンテンツで領域を塗りつぶす要素です。
プロパティ要素内に、 要素を配置します。CompositeTransformクラスは、1つのオブジェクトに複数の異なる変換を適用する事ができるクラスです。CenterXとCenterYプロパティに0.5と指定します。回転を表すRotationには90を指定します。

(3)プロパティ要素内に、 要素を配置します。CenterXとCenterYプロパティに、0.5と指定します。回転を表すRotationには90を指定します。

(4) 要素のIconUriプロパティにIconsフォルダの画像を指定し、Clickイベントにイベントハンドラを指定します。

<phone:PhoneApplicationPage 
  x:Class="WP71_MultiTouchBehavior.CatchPhotoPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  FontFamily="{StaticResource PhoneFontFamilyNormal}"
  FontSize="{StaticResource PhoneFontSizeNormal}"
  Foreground="{StaticResource PhoneForegroundBrush}"
  SupportedOrientations="Portrait" Orientation="Portrait"
  mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480"
  shell:SystemTray.IsVisible="True">
 
  <!--LayoutRoot は、全てのページ コンテンツが配置されるルート グリッドです-->
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <!--ContentPanel - 追加コンテンツをここに入力します-->
    <Grid x:Name="ContentPanel" Grid.RowSpan="2">
 
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="442*" />
        <ColumnDefinition Width="14*" />
      </Grid.ColumnDefinitions>
      <InkPresenter x:Name="InkPresenter1" Height="480" Width="360" Margin="55,75,27,141"> ■(1)
        <Rectangle Height="357" HorizontalAlignment="Left"  Name="Rectangle1" VerticalAlignment="Top" Width="476" Canvas.Left="356" Canvas.Top="3">■(2)
          <Rectangle.Fill>
            <VideoBrush x:Name="myVideoBrush"/>
          </Rectangle.Fill>
          <Rectangle.RenderTransform>
            <CompositeTransform Rotation="90" CenterX="0.5" CenterY="0.5"/>
          </Rectangle.RenderTransform>
        </Rectangle>■(2)
 
        <Image  Height="360" Name="backgroundImage" Stretch="Fill" Width="480" Canvas.Left="359" Canvas.Top="1">■(3)
          <Image.RenderTransform>
            <CompositeTransform Rotation="90" CenterX="0.5" CenterY="0.5"/>
          </Image.RenderTransform>
        </Image>■(3)
      </InkPresenter>■(1)
    </Grid>
  </Grid>
  <!--ApplicationBar の使用法を示すサンプル コード-->
  <phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
      <shell:ApplicationBarIconButton IconUri="Icon/camera.png" Text="シャッター" Click="GoShutter"/>■(4)
      <shell:ApplicationBarIconButton IconUri="Icon/folder.png" Text="データ一覧" Click="GoIchiran"/>■(4)
      <shell:ApplicationBarIconButton IconUri="Icon/phrase.png" Text="四文字熟語選択" Click="KanjiImageSelect"/>■(4)
      <shell:ApplicationBarIconButton IconUri="Icon/clear.png" Text="熟語画像の削除" Click="GoDelete"/>■(4)
    </shell:ApplicationBar>
  </phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>

レイアウト図は図5のようになります。

 図5:各コントロールを配置した(クリックで拡大)
  • カメラに配置した装飾アイテムを移動・変形させるサンプル

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

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