泥庭

2013年5月11日

マルチタッチでお絵かき

Filed under: .NET, ストアアプリ, Windows8 — タグ: , , — yone64 @ 1:09 AM

前回の続き。Room metro #16のハンズオン2つ目です。

今回使うのは、PointerXXXXというイベント群です。これらのイベントに共通するイベント引数PointerRoutedEventArgsからは、PointerPointクラスが取得でき、タッチポイントに関するさまざまな情報が取得できます。このクラスから取得できるPointerIdを利用して、今発生しているイベントの入力ポインターを識別できます。

private void Canvas_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    var canvas = (Canvas)sender;
    var pointerPoint = e.GetCurrentPoint(canvas);

    // 入力ポイントを一意に識別するId
    uint pid = pointerPoint.PointerId;
}

PointerIdと描画中の線を紐づけておくことで、マルチタッチでお絵かきが可能になります。

[5/18追記]プロジェクトをGitHubにあげました。
https://github.com/yone64/RoomMetro16/tree/master/Pointer

XAML側

<Page
    x:Class="Pointer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Pointer"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Canvas Background="{StaticResource ApplicationPageBackgroundThemeBrush}" 
            PointerPressed="Canvas_PointerPressed" 
            PointerMoved="Canvas_PointerMoved" 
            PointerReleased="Canvas_PointerReleased"
            >
</Page>

コードビハインド側

/// <summary>
/// PointerIdと描画中の線を紐づけるDictionary
/// </summary>
private Dictionary<uint, Polyline> dic = new Dictionary<uint, Polyline>();

// Pointerが押されたときのイベント
private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    // PointerPointの取得
    var canvas = (Canvas)sender;
    var pointerPoint = e.GetCurrentPoint(canvas);
    
    // 赤色でPolylineを描画
    var line = new Polyline 
    {
        StrokeThickness = 3,
        Stroke = new SolidColorBrush(Colors.Red)
    };

    // Polylineに頂点を追加
    line.Points.Add(pointerPoint.Position);

    // PointerIdとPolylineを紐づけ
    dic[pointerPoint.PointerId] = line;

    // キャンバスに描画する線を追加
    canvas.Children.Add(line);

    // MoveイベントがCanvas上で発生するようにPointerをキャプチャ
    canvas.CapturePointer(e.Pointer);
}

// Pointerが動いた時のイベント
private void Canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    // PointerPointの取得
    var pointerPoint = e.GetCurrentPoint((UIElement)sender);
    var pid = pointerPoint.PointerId;

    // Moveイベントは押下中じゃなくても発生するので
    // 描画中かどうかの判断を行う。
    if (dic.ContainsKey(pid))
    {
        // 描画中のPolylineに頂点を追加する
        dic[pid].Points.Add(pointerPoint.Position);
    }
}

// Pointerが離された時のイベント
private void Canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    // PointerPointの取得
    var canvas = (Canvas)sender;
    var pointerPoint = e.GetCurrentPoint(canvas);

    // PointerIdとPolylineを紐づけを解除し、描画を終了。
    dic.Remove(pointerPoint.PointerId);

    // Pointerのキャプチャも終了する
    canvas.ReleasePointerCapture(e.Pointer);
}

実行結果

スクリーンショット (10)

補足

MSDNにある通り、PointerReleasedイベントの代わりにPointerCanceledやPointerCaptureLostイベントが発生することがあるので、きちんとそちらのイベントも対応する必要があります。

コメントする »

まだコメントはありません。

RSS feed for comments on this post. TrackBack URI

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

WordPress.com で無料サイトやブログを作成.

%d人のブロガーが「いいね」をつけました。