WPFでプログラムしてみよう(7)

    1. WPFでプログラムしてみよう(1)-依存プロパティ等のWPF概要説明-
    2. WPFでプログラムしてみよう(2)-環境作成方法とパネルの使い方-
    3. WPFでプログラムしてみよう(3)描画オブジェクト(その1)-
    4. WPFでプログラムしてみよう(4)描画オブジェクト(その2)-
    5. WPFでプログラムしてみよう(5)描画オブジェクト(その3)-
    6. WPFでプログラムしてみよう(6)描画オブジェクト(その4)-


今回から5章のイベントです。


Windows Presentation Foundation プログラミング入門

Windows Presentation Foundation プログラミング入門

5.1 マウス入力

GUIを持つWindowsアプリケーションは、UIに関するすべての情報交換をWindowsメッセージを介して行っています。
そのため、以前はWndProcというメッセージを受けたとった時に実行される関数を使用し、どのメッセージを受け取ったのかを確認してから対応する処理を呼び出して実行するという作業が必要でした。
これに対して現在主流となっているのは、コントロールごとにイベントを定義し、ユーザからのアクションに応じて対応するイベントが呼び出され、そのイベントが委譲された処理を実行するというものです。イベントドリブンなどと言います。


WPFは今までの.NETアプリケーションと同様に、後者のイベントドリブンで動作します。
まずはマウスイベントについてまとめます。


最初にマウスで使用できるイベント一覧です(P.228から抜粋)

イベント名 発生条件 MSDN
MouseDown マウスボタンが押された場合
MouseUp マウスボタンが離された場合
MouseLeftButtonDown マウスの左ボタンが押された場合
MouseLeftButtonUp マウスの左ボタンが離された場合
MouseRightButtonDown マウスの右ボタンが押された場合
MouseRightButtonUp マウスの右ボタンが離された場合
MouseWheel マウスのホイールが回転した場合
MouseEnter マウスカーソルが領域に侵入した場合
MouseMove マウスカーソルが領域内で移動した場合
MouseLeave マウスカーソルが領域から外に出た場合


これらをイベントを使って簡単なプログラムを作成してみます。

using System;
using System.Windows;
using System.Windows.Controls;

using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;

class Test : Window {
	[STAThread]
	public static void Main(){
		Window wnd = new Test();
		Application app = new Application();
		app.Run(wnd);
	}

	// 楕円クラス
	private Ellipse elp;

	public Test() {
		elp = new Ellipse();
		elp.Fill  = Brushes.Blue;
		elp.Width  = 200;
		elp.Height = 200;
		elp.MouseDown    += ellipseMouseDown ;
		elp.MouseUp      += ellipseMouseUp   ;

		Content = elp;
	}

	private void ellipseMouseDown(object sender, MouseButtonEventArgs e){
		if (e.LeftButton == MouseButtonState.Pressed)
			elp.Fill = Brushes.Pink;

		else if (e.RightButton == MouseButtonState.Pressed)
			elp.Fill = Brushes.Orange;

		else if (e.MiddleButton == MouseButtonState.Pressed)
			elp.Fill = Brushes.Red;

		Title    = e.ChangedButton.ToString();
	}

	private void ellipseMouseUp(object sender, MouseButtonEventArgs e){
		elp.Fill = Brushes.Blue;
		Title    = "";
	}

}

これをコンパイルして実行します。
中心に青い円が表示されます。



この円をクリック(左ボタン)します。
# マウスのボタンを押したままにしてください



円がピンクになりました。
また、WindowのタイトルがLeftになっています。


押しっぱなしにしていたボタンを離します。




円の色は青に戻り、タイトルの文字もなくなりました。
次に円を右クリック(これも押しっぱなし)してみます。



円はオレンジ色になり、タイトルはRightと表示されました。
押しっぱなしにしていたボタンを離すと画面は青に戻ってタイトルが消されます。



最後に円をホイールや真ん中のボタンでクリック(くどいようですがこれも押しっぱなしです)して見ます。



円は赤になり、タイトルはMiddleとなります。
で、ボタンを離すと元に戻ります。


MouseDownイベントでどのボタンが押されたのかを判断して色を塗り替え、タイトルにはイベントハンドラに引数として渡されているMouseButtonEventArgsクラスのインスタンスに格納されているChangedButtonを表示しています。
また、MouseUpイベントハンドラには円の塗りつぶしを青にしてタイトルを空文字にするという処理を入れることで画面を初期化しています。


こんな感じでマウスの動作に対するイベントを使うことが出来ます。
その他のイベントの詳細(ハンドラの引数や)についてはMSDNとかMSDNとかMSDNをみてください。

5.2 キーボード入力

パソコンについている入力用インターフェースといえば、マウスとキーボード。
という訳で次はキーボードからの入力についてまとめます。

イベント名 発生条件 MSDN
KeyDown キーが押された場合
KeyUp キーが離された場合


ではさっそくキーボードイベントを使ったプログラムを作ってみます。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;

using System.Collections;

class Test : Window {
	[STAThread]
	public static void Main(){
		Window wnd = new Test();
		Application app = new Application();
		app.Run(wnd);
	}
	
	private Ellipse   elp;
	private Hashtable ColorKeyTable;

	public Test() {
		elp = new Ellipse();
		elp.Fill   = Brushes.Gray;
		elp.Width  = 100;
		elp.Height = 100;

		InitHash();

		Content = elp;
		KeyDown += thisKeyDown;
		KeyUp   += thisKeyUp  ;
	}

	// KeyDownイベントハンドラ
	private void thisKeyDown(object sender, KeyEventArgs e) {
		elp.Fill = (Brush)ColorKeyTable[e.Key.ToString()];
		Title    += e.Key.ToString();
	}

	// KeyUpイベントハンドラ
	private void thisKeyUp(object sender, KeyEventArgs e) {
		elp.Fill = Brushes.Gray;
	}

	// Hashtable初期化
	private void InitHash() {
		ColorKeyTable = new Hashtable();

		ColorKeyTable.Add("A",Brushes.Aqua);
		ColorKeyTable.Add("B",Brushes.Blue);
		ColorKeyTable.Add("C",Brushes.Chocolate);
		ColorKeyTable.Add("D",Brushes.DeepPink);
		ColorKeyTable.Add("E",Brushes.Azure);
		ColorKeyTable.Add("F",Brushes.Firebrick);
		ColorKeyTable.Add("G",Brushes.Green);
		ColorKeyTable.Add("H",Brushes.Honeydew);
		ColorKeyTable.Add("I",Brushes.Indigo);
		ColorKeyTable.Add("J",Brushes.Ivory);
		ColorKeyTable.Add("K",Brushes.Khaki);
		ColorKeyTable.Add("L",Brushes.LightGreen);
		ColorKeyTable.Add("M",Brushes.Maroon);
		ColorKeyTable.Add("N",Brushes.Navy);
		ColorKeyTable.Add("O",Brushes.Olive);
		ColorKeyTable.Add("P",Brushes.PaleGreen);
		ColorKeyTable.Add("Q",Brushes.Plum);
		ColorKeyTable.Add("R",Brushes.Red);
		ColorKeyTable.Add("S",Brushes.Salmon);
		ColorKeyTable.Add("T",Brushes.Tomato);
		ColorKeyTable.Add("U",Brushes.Teal);
		ColorKeyTable.Add("V",Brushes.Violet);
		ColorKeyTable.Add("W",Brushes.Wheat);
		ColorKeyTable.Add("X",Brushes.Orange);
		ColorKeyTable.Add("Y",Brushes.Yellow);
		ColorKeyTable.Add("Z",Brushes.YellowGreen);
	}
}

コンパイルして実行します。


実行すると画面が表示され、中央に円が表示されます。



このフォームをアクティブにした状態でキーボードでA〜Zのいずれかを入力してみてください。
円が押されたボタンに対応した色に塗りつぶしなおされます。
また、押したボタンのキーがタイトルバーに表示されます。
# 今回は画面イメージを取るのが面倒なので画面展開のサンプルは省略します


5章は一度で終わらせようと思っていましたが、まだこれで半分くらいなので詳しくは次にします。
次回はイベントルーティングというイベントが発生して親/子オブジェクトに派生する仕組みと、実行箇所が異なるだけで内容は同じ処理をうまく扱う方法(CommandBinding)についてまとめます。