ホワイトボードアプリケーション
前回に引き続きLive Framework SDKの.NET Kitを使用した開発です。今回は、

本連載ではVisual Studio 2008と言語にVB.
WPFアプリケーションの作成
最初にホワイトボードアプリケーションの基本的な部分を作成します。Visual Studioを使用して、

プロジェクトの作成後、
InkCanvas
手書きを実現するためInkCanvasというコントロールを使用します。InkCanvasはTablet PC等でスタイラスによる入力を行い、
まずは、

この時点で実行するとウィンドウに手書き入力することができます。実際に実行して確認してみましょう。入力により画面上に追加される線は、
コードを記述しない状態で手書き入力が可能になり便利なコントロールですが、
追加する内容は
- 消しゴムの選択
- ホワイトボードのクリア
および消しゴム選択から手書き入力に戻るための
- ペンの選択
とします。ここでは、
XAMLファイルを以下のように編集します。InkCanvasだけでなくボタンを追加し、
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ホワイトボード" Height="300" Width="300">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="ペン" Click="PenButton_Click" Width="80" Margin="2" />
<Button Content="消しゴム" Click="EraserButton_Click" Width="80" Margin="2" />
<Button Content="クリア" Click="ClearButton_Click" Width="80" Margin="2" />
</StackPanel>
<InkCanvas Name="MyInkCanvas" />
</DockPanel>
</Window>
続いてボタンのClickイベント処理を記述します。ソリューションエクスプローラからWindow1.
ペンと消しゴムの選択はInkCanvasのEditingModeプロパティを使用し、
Private Sub PenButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
MyInkCanvas.EditingMode = InkCanvasEditingMode.Ink
End Sub
Private Sub EraserButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
MyInkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke
End Sub
このEditingModeで指定できる動作には、
ホワイトボードのクリアは、
Private Sub ClearButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
MyInkCanvas.Strokes.Clear()
End Sub
以上でホワイトボードとしての処理部分は完了です。実際に実行して各ボタンが機能するか確認してみましょう。
ユーザー定義のデータ
さて、
Mesh上へファイルを追加する方法は、
アプリケーションでバイナリデータを扱う場合はファイル追加のときと同様に処理すればよいですが、
SetUserDataとGetUserDataメソッドは、
コード例を以下に示します。単純にString型の値をMesh Objectに設定および取得するには次のようになります。
' Imports Microsoft.LiveFX.Client
' Imports System.Net
Dim loe = New LiveOperatingEnvironment
loe.Connect(New NetworkCredential("userid", "password"), New LiveItemAccessOptions(True))
' Mesh Object に文字列データの設定
Dim meshObject = New MeshObject("Sample")
meshObject.Resource.SetUserData(Of String)("文字列データ")
loe.Mesh.MeshObjects.Add(meshObject) ' Mesh へ追加
' Mesh Object から文字列データの取得
Dim str = meshObject.Resource.GetUserData(Of String)()
MessageBox.Show(str)
続いて独自のクラスを設定する場合です。クラスオブジェクトの場合は、
Public Class UserDataClass
' メンバ1
Public Foo As String
' メンバ2
Private _bar As Integer
Public Property Bar() As Integer
Get
Return _bar
End Get
Set(ByVal value As Integer)
_bar = value
End Set
End Property
End Class
先ほどと同じようにこのクラスオブジェクトをMesh Objectのデータとして設定・
' Mesh Object に文字列データの設定
Dim meshObject = New MeshObject("UserDataClass")
Dim userData1 = New UserDataClass With {.Foo = "hoge", .Bar = 123}
meshObject.Resource.SetUserData(Of UserDataClass)(userData)
' Mesh Object から文字列データの取得
Dim userData2 = meshObject.Resource.GetUserData(Of UserDataClass)()
MessageBox.Show(userData2.Foo & userData2.Bar.ToString)
シリアライズ可能なものに限られますが、
Live Frameworkの利用
それでは、
LOEへ接続とMesh Objectの作成
最初にLive Operating Environment
Private Const WhiteboardResourceType As String = "GihyoJp.SampleApplication.Whiteboard"
Private LOE As New LiveOperatingEnvironment ' LOE
Private WithEvents WhiteboardObject As MeshObject ' Mesh Object
Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
' LOEへ接続
LOE.Connect(New NetworkCredential("userid", "password"), New LiveItemAccessOptions(True))
' Mesh Objectの取得
Dim whiteboards = From mo In LOE.Mesh.MeshObjects.Entries _
Where mo.Resource.Type = WhiteboardResourceType
If whiteboards.Count > 0 Then
' Mesh 内に既にホワイトボードアプリケーション用の Mesh Object がある場合
WhiteboardObject = whiteboards.First
Else
' Mesh 内にホワイトボードアプリケーション用の Mesh Object がない場合、作成
WhiteboardObject = New MeshObject
WhiteboardObject.Resource.Type = WhiteboardResourceType
WhiteboardObject.Resource.Title = "whiteboard app"
LOE.Mesh.MeshObjects.Add(WhiteboardObject)
End If
End Sub
実用的なアプリケーションにするためには、
上記コードでは、
Stroke情報の保存
InkCanvas.
Using fs = New System.IO.FileStream("strokes", IO.FileMode.Create, IO.FileAccess.Write)
MyInkCanvas.Strokes.Save(fs)
End Using
ただ、
Using ms = New System.IO.MemoryStream
XamlWriter.Save(MyInkCanvas.Strokes, ms)
Dim strokes = System.Text.Encoding.UTF8.GetString(ms.ToArray)
End Using
入力されたStroke情報をMeshへ追加・
XML形式にする部分をメソッド化しMesh Objectの更新処理を追加したコードを以下に示します。
Private Sub SetStrokes()
Using ms = New System.IO.MemoryStream
XamlWriter.Save(MyInkCanvas.Strokes, ms)
Dim strokes = System.Text.Encoding.UTF8.GetString(ms.ToArray)
WhiteboardObject.Resource.SetUserData(Of String)(strokes)
End Using
WhiteboardObject.Update()
End Sub
Private Sub MyInkCanvas_StrokeErased(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyInkCanvas.StrokeErased
SetStrokes()
End Sub
Private Sub MyInkCanvas_StrokeCollected(ByVal sender As Object, ByVal e As System.Windows.Controls.InkCanvasStrokeCollectedEventArgs) Handles MyInkCanvas.StrokeCollected
SetStrokes()
End Sub
クリアボタンをクリックしたときには上記のイベントは発生しないため、
以上で、
Stroke情報の復元
Mesh ObjectにはXML形式の文字列としてStroke情報を保存していたので、
Private Sub GetStrokes()
WhiteboardObject.Load()
Dim xml = WhiteboardObject.Resource.GetUserData(Of String)()
If xml IsNot Nothing Then
Dim strokes = TryCast(XamlReader.Parse(xml), StrokeCollection)
If strokes IsNot Nothing Then
MyInkCanvas.Strokes.Clear()
MyInkCanvas.Strokes.Add(strokes)
End If
End If
End Sub
明示的にMesh ObjectのLoadメソッドを呼び、
Stroke情報を復元するタイミングはアプリケーションの起動時とMesh Objectがほかのデバイスからなど外部要因で更新された場合です。起動時に処理するにはウィンドウのLoadイベントの最後にGetStrokesメソッドの呼び出しを追加ます。Mesh Objectの更新通知を受信するには、
Private Sub WhiteboardObject_ChangeNotificationReceived(ByVal sender As Object, ByVal e As System.EventArgs) Handles WhiteboardObject.ChangeNotificationReceived
GetStrokes()
End Sub
更新通知の受信については前回に紹介していますので、
以上で今回作成するアプリケーションは完成です。実行してみて動作を確認してみてください。アプリケーションを終了し、
おわりに
最後に作成したアプリケーションの動作について改良点などを補足しておきます。
実際にアプリケーションを実行してみて気づいたかもしれませんが、
WhiteboardObject.UpdateAsync("state") ' 非同期呼び出し
非同期呼び出しをした場合Object型の引数を指定できます。アプリケーションで何らかの状態を管理する必要がある場合に利用します。非同期処理が完了を知るにはイベントを使用します。
Private Sub WhiteboardObject_UpdateCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) Handles WhiteboardObject.UpdateCompleted
Console.WriteLine(e.UserState)
End Sub
非同期処理が完了するまで次の非同期処理のメソッドを呼ぶことはできません。そのため、
また、