酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windows PhoneでInkPresenterコントロールを使って絵を描く

InkPresenterコントロールを使って、簡単にお絵かきアプリケーションを作成することができます。

InkPresenterコントロールを使う

既定の状態ではVisual Studioのツールボックスには、InkPresenterコントロールが表示されていません。ツールボックスに表示されていないので、手作業でInkPresenterコントロールをXAMLに追加する必要があります。

<!--ContentPanel - 追加コンテンツをここに入力します-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <InkPresenter  Name="inkPresenter" Background="White" />
</Grid>

上記のXAMLを実行してみました。しかし、InkPresenterコントロールを配置するだけでは線を引くことするできません。

f:id:ch3cooh393:20150730222752p:plain

ストロークを追加する

絵を描くというよりもマウスイベントの発生地点から発生地点まで直線を引くのを繰り返すイメージになります。

ここでいう直線はStrokeオブジェクトで、マウスイベントが発生する毎にStrokeオブジェクトを生成し、InkPresenterコントロールのストローク管理用のコレクションに追加していきます。

f:id:ch3cooh393:20150730222840p:plain

マウスイベントを受け取る為にMouseLeftButtonUp、MouseMove、MouseLeftButtonDownイベントをそれぞれのイベントハンドラを追加しておきます。

現在のストローク情報をインスタンスフィールドに保持し、指をコントロールに落としたMouseLeftButtonDownイベントハンドラにて、マウスキャプチャーを開始し、コントロール上の座標を取得しStrokeオブジェクトを生成します。

コードをシンプルにする為、ストロークの色は黒色固定としていますが、任意の色を選択できるようにする場合、DrawingAttributes.Colorプロパティで色を指定すると良いでしょう。

using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Phone.Controls;

namespace InkPresenterTest {
    public partial class MainPage : PhoneApplicationPage {
        // コンストラクター
        public MainPage() {
            InitializeComponent();
        }

        private Stroke _currentStroke;

        // 指を付けた
        private void inkPresenter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            // マウスキャプチャーを開始
            inkPresenter.CaptureMouse();

            // マウスポインタの座標を取得
            var pos = e.GetPosition(inkPresenter);

            // インクのストロークオブジェクトを作成
            _currentStroke = new Stroke();
            _currentStroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
            _currentStroke.DrawingAttributes.Color = Colors.Black;

            // ストロークを追加
            inkPresenter.Strokes.Add(_currentStroke);  
        }

指を動かし続けている間は指を動かしたMouseMoveイベントが発生します。既に液晶から指を離した状態であればストローク扱いとしません。

指を液晶に付けた時点から連続して発生したMouseMoveイベントからのみ、Strokeオブジェクトを生成してコレクションに追加しています。

        // 指を動かした
        private void inkPresenter_MouseMove(object sender, MouseEventArgs e) {
            if (_currentStroke == null) {
                // 指が液晶から離れた後なので何もしない
                return;
            }

            // マウスポインタの座標を取得
            var pos = e.GetPosition(inkPresenter);

            // インクのストロークオブジェクトを作成
            _currentStroke = new Stroke();
            _currentStroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
            _currentStroke.DrawingAttributes.Color = Colors.Black;

            // ストロークを追加
            inkPresenter.Strokes.Add(_currentStroke);  
        }

指を液晶から離すと発生するMouseLeftButtonUpイベントにて、_currentStrokeプロパティにnullを設定し、指を離してから発生したMouseLeftButtonUpイベントを無視するようにしました。

        // 指を離した
        private void inkPresenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
            _currentStroke = null;  
        }
    }
}

上記のコードを実行して「CH3COOH」と書いてみました。

f:id:ch3cooh393:20150730222939p:plain

右上に傾いているのは、字の汚い僕が悪いのであって、決してコードが悪いわけではありません。