WPFでキーボードやマウス、スタイラス、マルチタッチなどによる入力を処理する方法と、アニメーションを実現する、ストーリーボードなどの各種機能を解説。
powered by Insider.NET
今回は入力イベントとアニメーションについて説明していく。
前回までの説明は、Visual Studioの無償版であるVisual C# ExpressやVisual Basic Expressでも試すことができた。しかし、今回は、有償製品のExpression Blendの利用が前提となる説明が多くなっている。その点ご容赦いただきたい。Expression Blendを利用するのは、Visual Studioにはアニメーションを視覚的に編集する機能がないためだ。
一応、視覚的な編集ツールが不要で、Expression Blend付属のライブラリだけなら、無償で入手可能なBlend SDKをインストールすれば利用可能である。
* 本稿での「ユーザー」という表記はすべて、WPFアプリケーションを利用する「エンド・ユーザー」を指す。
連載第6回で説明したように、モデル(=見た目と関係なく成り立つロジックやデータ)に対するイベント通知はコマンド(=意味論的なイベント処理機構)という層を通して行うことが多く、この用途で入力イベントを直接処理する機会は多くないだろう。入力イベントは以下のような場面で利用することになる。
●入力に関連するクラス
WPFでは、キー入力関連ならKeyboardクラス、マウス入力関連ならMouseクラス(いずれもSystem.Windows.Input名前空間)というように、入力デバイスの種類ごとにルーティング・イベントを定義するクラスが存在する。例えば、キー・ダウン・イベントの場合、KeyboardクラスのKeyDownEventルーティング・イベントが発生する。
また、UIElementクラス(System.Windows名前空間)には、UI要素がこれらのルーティング・イベントを受け取ったときに発生するCLRイベントが定義されている。従って、XAMLコード中では、以下のような2通りのイベント・ハンドラ登録の方法がある。
<!-- Keyboard クラスのルーティング・イベント(添付イベント) -->
<TextBox Keyboard.KeyDown="TextBox_KeyDown" />
<!-- UIElement クラスのイベント -->
<TextBox KeyDown="TextBox_KeyDown" />
●バブル・イベントとトンネル・イベント
入力イベントにはバブル・イベントとトンネル・イベント(第6回参照)があり、トンネル・イベントの名前には語頭に「Preview」が付いている(付いていないものはバブル・イベント)。例えば、キー・ダウンなら、バブル・イベントが「KeyDown」、トンネル・イベントが「PreviewKeyDown」となる。
コントロールなどでは、バブル・イベントを「処理済み」(=それ以上イベントが親要素に伝搬(でんぱ)しない)にしてしまうものがある(例えば、ボタンはマウス・クリックを、テキストボックスはキー・ダウンを処理済みにする)。子要素の種類によらず、親要素側でイベントを拾いたい場合にはトンネル・イベント(=Previewで始まるイベント)を利用する。
次節からは個々のイベントについて、主要なものを紹介していこう。1つの入力イベントに対して関連するプロパティやメソッド、イベントが複数あるが、命名規則は一貫しているので使い分けは難しくない。次節以降では、例えば、「KeyboardクラスのKeyDownイベント」といった場合、以下のようなものが存在するものと読み替えてほしい。
◆ Keyboardクラス中:
◆ UIElementクラス中:
また、「Preview」を付けることでトンネル・イベントとなるので、バブル・イベントのみを紹介する。
●キーボード
Keyboardクラス(System.Windows.Input名前空間)に以下のようなイベントが定義されている。
○キー
どのキーが押されたかは、イベント・ハンドラの第2引数(KeyEventArgsクラス)のKeyプロパティで取得できる。また、KeyEventArgsクラスにはKeyboardDeviceプロパティ(KeyboardDeviceクラス)があり、これを介して[Shift]キーなどの修飾キーに関する情報も取得できる。
○フォーカス
また、イベント駆動ではなく、能動的にキーボードの状態を調べるために、KeyboardクラスにはIsKeyDownやGetKeyStatesなどの静的メソッドも定義されている。
○キーボード・フォーカスと論理フォーカス
WPFのフォーカスには、以下のように、2種類の概念が存在する。
KeyboardクラスのGotKeyboardFocusイベントおよびLostKeyboardFocusイベントはキーボード・フォーカスの取得/消失で発生するイベントである。一方で、論理フォーカスに関しては、FocusManagerクラス(System.Windows.Input名前空間)に以下のようなイベントが定義されている。
Movie 1にキーボード・フォーカスと論理フォーカスの差を確認する例を示す。
この例では、フォーカスを得た瞬間にアニメーションを開始するようにしてある。テキストボックスを移動した際にはキーボード・フォーカスと論理フォーカスの両方が変化するのに対して、ウィンドウを切り替えた際にはキーボード・フォーカスだけが変化する。
●テキスト入力
キーボードからのキー入力とは別に、キーボード/手書き認識/音声認識のいずれの入力かを問わないテキスト入力のためのイベントとして、TextCompositionManagerクラス(System.Windows.Input名前空間)に以下のイベントが定義されている。
TextInputStartイベントやTextInputUpdateイベントを利用すれば、IMEによる日本語変換の途中の状態を取得することもできる。
Movie 2に、音声認識、手書き認識、および、IME経由によるテキスト入力の例を示す。
TextInputイベントが起こるたびに、入力されたテキストを右側のリストボックスに追加している(左側はただのテキストボックス)。
●マウス
Mouseクラス(System.Windows.Input名前空間)に以下のようなイベントが定義されている。
○マウス・ボタン/ホイール
これらMouseクラスで定義されているイベントのほかに、UIElementクラスでは以下のようなイベントが定義されている。
マウスの左ボタンを押した際にはMouseDownイベントとMouseLeftButtonDownイベントの両方が発生するので利用の際には注意が必要である。
ちなみにダブル・クリックに関するイベントは、UIElementクラスにはなく、ControlクラスでMouseDoubleClickイベントが定義されている。
○マウス移動
マウスのキャプチャ(=マウス・ポインタの位置によらず、コントロールがすべてのマウス入力コマンドを受け取るようにようにマウスを捕捉すること)は、UIElementクラスのCaptureMouseメソッドで、キャプチャ解除はReleaseMouseCaptureメソッドで行う。
また、マウス・ポインタの位置は、MouseクラスのGetPosition静的メソッドか、MouseDeviceクラス(=イベント・ハンドラの第2引数からオブジェクトを取得可能)のGetPositionメソッドを使って取得できる。GetPositionメソッドは、引数にUI要素を与えることで、そのUI要素の左上座標を起点とした相対座標を取得する。
UI要素上にマウス・ポインタを乗せたときに、カーソルの形状を変化させたい場合、FrameworkElementクラス(System.Windows名前空間)のCursorプロパティを利用する。Cursorプロパティに指定するカーソルは、CursorクラスのコンストラクタでWindowsのカーソル・ファイル(拡張子は「.cur」や「.ani」)を読み込んだものか、Cursorsクラス(System.Windows.Input名前空間)の静的プロパティとして定義されている標準カーソルのいずれかを利用する。
また、FrameworkElementクラスのForceCursorプロパティの値を「true」にすることで、(子要素でのCursorプロパティの設定を無視して)自身のCursorプロパティの値を強制することができる。
●ドラッグ&ドロップ
DragDropクラス(System.Windows.Input名前空間)に以下のようなイベントが定義されている。
●スタイラス
Stylusクラス(System.Windows.Input名前空間)にスタイラス関連のイベントが定義されている。
スタイラスはマウスとしても認識される(=スタイラス・イベントと同時にマウス・イベントが発生する)ため、スタイラス固有の機能を利用しない場合にはマウス・イベントの処理だけでもアプリケーションを作成できる。
MouseDownイベントに対してStylusDownイベントがあり、CaptureMouseメソッドに対してCaptureStylusメソッドがあるなど、マウス・イベントから類推できるスタイラス・イベントも多い。一方、スタイラス固有のイベントとしては以下のようなものがある。
*1 スタイラス・ジェスチャとは、例えばタップやドラッグなどのこと。利用可能なジェスチャについては、SystemGesture列挙体(System.Windows.Input名前空間)のメンバを参照してほしい。
●マルチタッチ
Windows 7のマルチタッチ対応に合わせて、WPF 4でタッチ・イベントが追加された。WPF 4では方針が変更されたようで、マウス・イベントでいうところのMouseクラスに相当するTouchクラスやManipulationクラス(いずれもSystem.Windows.Input名前空間)にはルーティング・イベントが(publicには)定義されていない。UIElementクラスにTouchDownなどのイベントが定義されているので、これらを利用する。
マルチタッチ・デバイスに関連したイベントには以下の2つの種類がある。
*2 タッチ・ジェスチャとは、例えばパンやズームなどのこと。詳しくは、windows.microsoft.comの「Windows 7 タッチ ジェスチャ」を参照してほしい。すなわち、操作イベントとは、フレームワーク上でタッチ・イベントを要約して、平行移動や拡大/縮小などの、プログラマーに分かりやすい情報に変換してからイベントを発生させるものである。
前者のタッチ・イベントは、スタイラス同様、マウス・イベントも発生させるため、マウス・イベントの処理だけでもある程度のアプリケーションを作成できる。イベント名も、MouseDownイベントに対してTouchDownイベントがあるなど、マウス・イベントから類推可能である。
一方、操作イベントには以下のようなものがある。
Movie 3に操作イベントの利用例を示す。
この例では、Blend SDK付属のTranslateZoomRotateBehaviorを利用して、操作イベントに応じてUI要素の回転・拡大・平行移動を行っている。詳細は本稿の後半で説明するが、動画を見てのとおり、UI要素にビヘイビアを付与する(Expression Blend上ではドラッグ&ドロップ操作で付与可能)だけで、操作イベントに応じて回転・拡大・平行移動ができる。
Copyright© Digital Advantage Corp. All Rights Reserved.