PR

好きな写真を指で選んで順番に拡大表示するLeap Motionプログラムを作る

2013年12月6日(金)
薬師寺 国安

Updateメソッドの処理(ホバー処理)

手前側が「ホバー状態(hovering)」、奥側が「タッチ状態(touching)」を表します。空間の範囲は前後「1」〜「-1」となっています。

図20:Leap Motionのタッチ検出イメージ(Leap Motion SDKのAPIドキュメントから引用)(クリックで拡大)

まずホバーの場合は、タッチした座標値をメンバー変数「x」と「y」に格納しておきます。画面に表示されている指の数をleap.Frame.Fingers.Countプロパティで取得して、メンバー変数「FingersCount」に格納しておきます。マウスの左ボタンのクリックをやめた時のWin32 APIを実行します(リスト6参照)。

リスト6 ホバー時の処理(MainWindow.xaml.vb)

For Each Pointable As Pointable In leap.Frame.Pointables
  ……コード略(前述)……
  If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then
        touchIndicator.Color = Colors.Blue

' タッチ・ポイントの値をメンバー変数に格納
        x = touchPoint.X
        y = touchPoint.Y
 
        FingersCount = leap.Frame.Fingers.Count' 指の本数を取得
        apimouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) ' Win32 APIの実行
……コード略(続きは後述)……
  End If
Next

次にタッチした処理になります。タッチした場合は、表示されている円が赤に変わります。

Updateメソッドの処理(タッチ処理)

指が1本認識されている場合は、SetCursorPos(x,y)と指定して、タッチ・ポイントとカーソルの位置を同じ位置に表示します。

apimouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)

と指定して、マウスの左ボタンを押した処理を行います。タッチ以外の処理ではタッチ・ポイントの色がGoldになり、何も発生しません。具体的にはリスト7のコードになります。

リスト7 タッチとタッチ以外の処理(MainWindow.xaml.vb)

If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then
  ……コード略(前述)……
  ElseIf Pointable.TouchDistance <= 0 Then
   touchIndicator.Color = Colors.Red
  If FingersCount = 1 Then
                  SetCursorPos(x,y)
                  apimouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) ' タッチした場合の処理
              End If
              ' タッチ対象外
            Else
              touchIndicator.Color = Colors.Gold
            End If
      Next
  End Sub

プログラム・コード(TransitionEffectListBox.xaml.vb)

では、次にプログラム・コード(TransitionEffectListBox.xaml.vbファイル)を見ていきましょう。

名前空間の読み込み

名前空間の読み込みはありません。

クラスの定義(ImageInfo)

ImageInfoクラス内に、「画像名」と「タイトル」のプロパティを定義しておきます。

Public Class ImageInfo
  Public Property 画像名 As String
  Public Property タイトル As String
End Class

メンバー変数の宣言

XML要素を表すXElementクラスのメンバー変数「Private xmldoc As XElement」を宣言します。

TransitionEffectListBoxが読み込まれた時の処理

XElement.LoadメソッドでPhoto.xmlを読み込みます。読み込んだXMLから要素を選択するクエリーを定義します。

ImageInfoクラス型の新しいリストであるmyImageListオブジェクトを作成します。

Descendantsメソッドで子孫要素の内容を、繰り返し変数resultに格納しながら、以下の処理を繰り返します。

タイトル名を取得して変数myTitleに格納します。新しいImageInfoクラスの、「画像名」プロパティに文字列「Images/」と要素の内容を連結して指定し、「タイトル」プロパティに変数myTitleの値を指定して、AddメソッドでmyImageInfoオブジェクトに追加していきます。

ListBox1のItemsSourceプロパティにmyImageInfoオブジェクトを指定します。これで、ListBox1に画像の一覧が表示されます。

コードはリスト8のようになります。

リスト8 TransitionEffectListBox_Loadedメソッドの処理(TransitionEffectListBox.xaml.vb)

・・・コード略・・・
' ImageInfoクラスの定義
Public Class ImageInfo
  Public Property 画像名 As String
  Public Property タイトル As String
End Class

Public Class TransitionEffectListBox
  Private xmldoc As XElement
  
  Private Sub TransitionEffectListBox_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    xmldoc = XElement.Load("Photo.xml")
    Dim query = From c In xmldoc.Descendants("画像名") Select c
    Dim myImageInfo As New List(Of ImageInfo)

'「画像名」と「タイトル」の値を取得してImageInfoクラスのプロパティに指定する
    For Each result In query
      Dim titleLen As Integer = Len(result.Value) - 4
      Dim myTitle = Microsoft.VisualBasic.Left(result.Value, titleLen)
      With myImageInfo
        .Add(New ImageInfo With {.画像名 = "Images/" & result.Value, .タイトル = myTitle})
      End With
    Next
    ListBox1.ItemsSource = myImageInfo
  End Sub

ListBoxコントロールから画像が選択された時の処理

ImageShowAreaに適用されているVisualState(特定の状態でのコントロールの外観を表すクラス)が存在し、かつ、VisualStateの名前がSlideIn2である場合は、VisualStateManager.GotoStateメソッドでSlideInの VisualStateを実行します。それ以外の場合は、SlideIn2を実行します。VisualStateManager.GotoStateメソッドの書式は下記の通りです。

VisualStateManager.GotoState(状態を遷移させるコントロール,状態名,VisualTransitionを使うかどうかのBoolean値(使用する場合はTrue、それ以外はFalse)

ListBoxのインデックスに該当する要素の内容を取得し、変数selectImageに格納します。

ImageShowAreaのImage1コントロールのSourceプロパティに、画像を格納している「Image/フォルダ」を連結したselectImage変数を指定します。相対Uriで指定します。これで、ListBoxから選択された画像が、左から右に向かってスライドしながら表示されます。

コードはリスト9のようになります。

リスト9  ListBox1_SelectionChangedメソッドの処理(TransitionEffectListBox.xaml.vb)

  Private Sub ListBox1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ListBox1.SelectionChanged

' 条件分岐によるSlideInとSlideIn2の実行
    If ImageShowArea.VisualStateGroup.CurrentState Is Nothing = False AndAlso ImageShowArea.VisualStateGroup.CurrentState.Name.ToString = "SlideIn2" Then
      VisualStateManager.GoToState(ImageShowArea, "SlideIn", True)
    Else
      VisualStateManager.GoToState(ImageShowArea, "SlideIn2", True)
    End If
    Dim selectImage = xmldoc.Descendants("画像名")(ListBox1.SelectedIndex).Value

' ImageShowAreaのImage1コントロールに選択した画像を表示する
    ImageShowArea.Image1.Source = New BitmapImage(New Uri("Images/" & selectImage, UriKind.Relative))
  End Sub

※注意
今回紹介しているコードは、「LeapCSharp.NET4.0.dll」や「LeapCSharp.dll」、「Leap.dll」を読者自身のフォルダ内にあるDLLファイルに指定し直さなければ動かない可能性があるので、動かない場合は再指定してください。

10回に亘って紹介しましたLeap Motionのサンプル解説は今回で終わりです。長い間お付き合いありがとうございました。

Leap Motionを使うと、皆さんのアイデア次第で、想像もしなかったようなアプリが作成できる可能性を持っています。今回の連載が、皆さんにLeap Motionに対する興味を湧き立たせる一助となれば、筆者として大変に嬉しいです。

では、またいつかお会いしましょう。

薬師寺国安

Think IT会員限定特典
  • 好きな写真を指で選んで順番に拡大表示するLeap Motionプログラム

    『新世代モーションコントローラー Leap Motion -Visual Basicによる実践プログラミング-』 第10回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。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のWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

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

好きな写真を指で選んで順番に拡大表示するLeap Motionプログラムを作る | Think IT(シンクイット)

Think IT(シンクイット)

サイトに予期せぬエラーが起こりました。しばらくたってから再度お試しください。