読者です 読者をやめる 読者になる 読者になる

プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

UWPのInkCanvasで入力デバイスを指定する

f:id:puni-o:20160613101047j:plain

Windows 10 1511での話です、今後のバージョンアップでどうなるのかしりません

UWPのInkCanvasには

InkCnavas.InkPresenter.InputDeviceTypes

というプロパティがあります

指定するのは下のenumで取りたいデバイスだけを指定することができます

public enum CoreInputDeviceTypes : System.UInt32
{
    None = 0,
    Touch = 1,
    Pen = 2,
    Mouse = 4
}

実装例

<InkCanvas x:Name="ink"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
    <ToggleButton x:Name="Mouse" Content="Mouse" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
    <ToggleButton x:Name="Pen" Content="Pen" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
    <ToggleButton x:Name="Touch" Content="Touch" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
</StackPanel>
private void SetInputDevice()
{
    var type = Windows.UI.Core.CoreInputDeviceTypes.None;
    if (Mouse?.IsChecked ?? false) type |= Windows.UI.Core.CoreInputDeviceTypes.Mouse;
    if (Pen?.IsChecked ?? false) type |= Windows.UI.Core.CoreInputDeviceTypes.Pen;
    if (Touch?.IsChecked ?? false) type |= Windows.UI.Core.CoreInputDeviceTypes.Touch;
    ink.InkPresenter.InputDeviceTypes = type;
}

private void Toggle_Checked(object sender, RoutedEventArgs e) => this.SetInputDevice();

超適当ですがこれでできますね

これを使って

UWPのInkCanvasは上記プロパティがあるおかげなのかなんなのか、InputDeviceTypesに指定した入力はIsHitTestVisibleプロパティの影響を受けません。 IsHitTestVisible="False"とするとInputDeviceTypesに指定したイベントだけがInkCanvasに行って残りはその裏にいるコントロールに渡されます。

<ScrollViewer>
    <Rectangle Width="1000" Height="1000">
        <Rectangle.Fill>
            <LinearGradientBrush>
                <GradientStop Color="Azure"/>
                <GradientStop Color="YellowGreen" Offset=".25"/>
                <GradientStop Color="Orange" Offset=".5"/>
                <GradientStop Color="Blue" Offset=".75"/>
                <GradientStop Color="Magenta" Offset="1"/>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</ScrollViewer>
<InkCanvas x:Name="ink" IsHitTestVisible="False"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
    <ToggleButton x:Name="Mouse" Content="Mouse" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
    <ToggleButton x:Name="Pen" Content="Pen" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
    <ToggleButton x:Name="Touch" Content="Touch" IsChecked="True" Checked="Toggle_Checked" Unchecked="Toggle_Checked"/>
</StackPanel>

先ほどのXAMLを上のように変更します。 InkCanvasの後ろにScrollViewerを置きました。(中身はスクロールしていることが分かればいいだけの四角です)

これを手元の現役Surface Pro2で動かすと

f:id:puni-o:20160613102209g:plain

・はじめのイベントはタッチです。InputDeviceTypesにTouchを入れているのでInkCanvasが拾います

・次にInputDeviceTypesからTouchをはずして同じように動かします。するとTouchイベントはScrollViewerに飛ぶようになるのでScrollViewerのスクロールになります

・最後はペンのみをInputDeviceTypesにしてペンで書きながらタッチで裏をスクロールさせています。筆圧を感知しているのでペン入力だとわかってもらえると思います。

と、こんなことができます。

これを利用すると大きいキャンバスにペンで描画しながらスクロールするとか、ピンチで拡大縮小するとかそんなことが可能になります。(多分) 筆圧が無ければ移動拡大縮小はできたんですけどねぇ・・・