Grid/Canvas/Ellipse/Borderなどのコントロールでマウス/タッチ/スタイラスのイベントを発生させ、それを処理する方法を解説する。
対象:.NET 3.5以降
ただし、タッチ対応は.NET 4.0以降
マウスやタッチのイベントを拾えなくて困ったことはないだろうか? Grid/Canvas/Borderコントロール(いずれもSystem.Windows.Controls名前空間)やEllipse/Rectangleコントロール(System.Windows.Shapes名前空間)などの幾つかのコントロールは、マウスやタッチのイベントハンドラーを記述しただけではイベントを拾えないのである。しかしその対応は簡単だ。本稿ではその方法を紹介する。なお、本稿のサンプルは「Windows desktop code samples:.NET Tips #1123」からダウンロードできる。
背景色または塗りつぶし色を設定すればよい。透明のままにするには、背景色または塗りつぶし色として「Transparent」を指定する。
Grid/Canvas/BorderコントロールなどではBackgroundプロパティに、Ellipse/RectangleコントロールなどではFillプロパティに色を設定する。
分かってしまえば何ということもないのだが、マウスでクリックしたり指でタッチしたりするときに、そこに何かがなければイベントは発生しないということなのだ。透明であろうとも、背景色または塗りつぶし色が設定されていることが必要なのである。
なお、マウスやタッチのイベントはバブルアップするので、ビジュアルツリーの親要素で一括してハンドリングできる。
以下、簡単なサンプルコードを書いて、確かめてみよう。ここでは無償のVisual Studio Express 2012 for Windows Desktopを使い、.NET 4.0をターゲットにしてコーディングする(タッチ対応の部分を削れば.NET 3.5でも動作する)。
WPFのプロジェクトを作成したら、「MainWindow.xaml」ファイルを次のコードのように編集する。
<Window ……省略……
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="RootGrid" StylusDown="RootGrid_StylusDown"
TouchDown="RootGrid_TouchDown" MouseDown="RootGrid_MouseDown">
<Ellipse Fill="Blue" Opacity="0.1" Width="300" Height="60"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="60,100"/>
<StackPanel Margin="8">
<TextBlock x:Name="TextBlock1" Margin="0,0,0,8" HorizontalAlignment="Left" />
<StackPanel Orientation="Horizontal">
<Border x:Name="Border1" Background="Transparent"
BorderBrush="Green" BorderThickness="4" Width="200" Height="200" />
<Border x:Name="Border2" Background="{x:Null}" BorderBrush="DarkRed"
BorderThickness="4" Width="200" Height="200" Margin="8,0" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
上のXAMLコードでは、Ellipseコントロールに塗りつぶし色が設定してある(「Fill="Blue"」)。従って、このEllipseコントロールの内側をマウスでクリックしたり指でタッチしたりすればイベントが発生する。発生したイベントは、親要素であるGridコントロール「RootGrid」でハンドリングしている。
「RootGrid」には、スタイラスダウン(スタイラスペンが画面に触れたとき)/タッチダウン(指が画面に触れたとき)/マウスダウン(マウスのボタンが押されたとき)の三つのイベントハンドラーをセットしている(この三つのイベントは、ここに書いた順序で発生する)。なお、「RootGrid」自体には背景色を設定していないので、マウスやタッチのイベントは発生しない。これらのハンドラーは、「RootGrid」の子要素であるコントロールからバブルアップしてくるイベントを受け取る。
そして次が、背景を透明に保ったままイベントを受け取れるようにする例だ。Borderコントロール「Border1」には、背景色に「Transparent」を設定してある。これは、マウスやタッチのイベントを受け取れる。
比較のために、Borderコントロール「Border2」では、背景色をnullに設定している(これは既定値なので、背景色を指定しないのと同じ)。これはマウスやタッチのイベントを受け取らない。なお、Borderコントロールの枠線には色と幅を指定してあるので、枠線をクリック/タッチすれば「Border2」でもイベントが発生する。
コードビハインドには次のコードのようにイベントハンドラーを記述する。
// スタイラスペンが画面に触れたとき
private void RootGrid_StylusDown(object sender, StylusDownEventArgs e)
{
Point pos = e.GetPosition(RootGrid);
TextBlock1.Text = string.Format("StylusDown: {0}, {1} ({2})",
pos.X, pos.Y, e.Source.GetType().Name);
e.Handled = true; // TouchDownイベントを抑制
}
// 指が画面に触れたとき
private void RootGrid_TouchDown(object sender, TouchEventArgs e)
{
TouchPoint tp = e.GetTouchPoint(RootGrid);
TextBlock1.Text
= string.Format("TouchDown: {0}, {1} ({2})",
tp.Position.X, tp.Position.Y, e.Source.GetType().Name);
}
// マウスのボタンが押されたとき
private void RootGrid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.StylusDevice != null)
return; // スタイラス操作/タッチ操作のときはスルー
Point pos = e.GetPosition(RootGrid);
TextBlock1.Text
= string.Format("MouseDown: {0}, {1} ({2})",
pos.X, pos.Y, e.Source.GetType().Name);
}
' スタイラスペンが画面に触れたとき
Private Sub RootGrid_StylusDown(sender As Object, e As StylusDownEventArgs)
Dim pos As Point = e.GetPosition(RootGrid)
TextBlock1.Text = String.Format("StylusDown: {0}, {1} ({2})",
pos.X, pos.Y, e.Source.GetType().Name)
e.Handled = True ' TouchDownイベントを抑制
End Sub
' 指が画面に触れたとき
Private Sub RootGrid_TouchDown(sender As Object, e As TouchEventArgs)
Dim tp As TouchPoint = e.GetTouchPoint(RootGrid)
TextBlock1.Text _
= String.Format("TouchDown: {0}, {1} ({2})",
tp.Position.X, tp.Position.Y, e.Source.GetType().Name)
End Sub
' マウスのボタンが押されたとき
Private Sub RootGrid_MouseDown(sender As Object, e As MouseButtonEventArgs)
If (e.StylusDevice IsNot Nothing) Then
Return ' スタイラス操作/タッチ操作のときはスルー
End If
Dim pos As Point = e.GetPosition(RootGrid)
TextBlock1.Text _
= String.Format("MouseDown: {0}, {1} ({2})",
pos.X, pos.Y, e.Source.GetType().Name)
End Sub
実行中の画面は、次の画像のようになる。
前述したような結果になることを確かめてほしい。マウス/タッチに反応して画面左上の文字列が変わるのは、次の場所である。
マウスやタッチのイベントを拾うには、そこに何かしらの存在が必要である。コントロールによっては、背景色または塗りつぶし色の既定値がnullになっているものがある。そのようなコントロールでは、マウスやタッチのイベントを拾うために背景色または塗りつぶし色を設定する必要がある。
なお、サンプルコードでは、スタイラス/タッチ/マウスによるイベントの関係も分かるようにしてあるので、参考にしていただければ幸いである。
利用可能バージョン:.NET Framework 3.5以降
カテゴリ:WPF/XAML 処理対象:イベント
使用ライブラリ:Gridクラス(System.Windows.Controls名前空間)
使用ライブラリ:Borderクラス(System.Windows.Controls名前空間)
使用ライブラリ:Ellipseクラス(System.Windows.Shapes名前空間)
関連TIPS:WPF:ウィンドウを透明にするには?[C#/VB]
関連TIPS:WPF:子ウィンドウを透明にするには?[C#/VB]
Copyright© Digital Advantage Corp. All Rights Reserved.