4.4 サイズ変更の監視
4.4.1 コントロールの状態変更
コントロールは描画処理と密接な関係を持ちやすいため、プロパティの変更と何らかの処理を対応付ける必要になることがしばしばあります。その中でも特に多いと考えられるのは、コントロールの座標変更や、コントロールのサイズ変更に伴う再描画や再レイアウト処理です。
図や文字をウィンドウのサイズに合わせて動的に配置するプログラムの場合、ウィンドウのサイズが変化すると正しいレイアウトを守れなくなります。そのため、ウィンドウのサイズの変更と同時に座標の再計算を行って描画させなければ、レイアウト崩れてしまうことになります。ウィンドウを再描画して常に最新のレイアウトを維持するには、コントロールのプロパティ値が変更されたことをイベントとして受けます。
コントロールの移動は OnMove() メソッドが Move イベントを呼び出し、コントロールのサイズ変更は OnResize() メソッドが Resize イベントを呼び出します。つまり、コントロールの Left や Top プロパティ、または Location プロパティなど座標を設定するプロパティの値が変更された時点で呼び出されます。Resize イベントも、Width や Height、または Size プロパティが変更されると呼び出されます。
protected virtual void OnMove(EventArgs e)
public event EventHandler Move
protected virtual void OnResize(EventArgs e)
public event EventHandler Resize;
これらのイベントは、コントロールの描画処理を常にコントロールの座標やサイズに同期させる必要がある場合に利用することができます。ゲームの場合、一般的にはウィンドウのサイズが固定されるべきですが、サイズを固定しないような場合はこれらのイベントを再レイアウトの起動タイミングとして使います。
using System; using System.Drawing; using System.Windows.Forms; public class Test : Form { private string text; private void Test_Move(object sender, EventArgs e) { text = "Move:X=" + Left + ",Y=" + Top; Invalidate(); } private void Test_Resize(object sender, EventArgs e) { text = "Resize:Width=" + Width + ",Height=" + Height; Invalidate(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint (e); Font font = new Font(Font.Name, 20); Brush brush = new SolidBrush(Color.Black); Rectangle rect = new Rectangle(0, 0, Width, Height); StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; e.Graphics.DrawString(text, font, brush, rect, format); } public Test() { Move += new EventHandler(Test_Move); Resize += new EventHandler(Test_Resize); } static void Main() { Application.Run(new Test()); } }
コード1は、ウィンドウの座標変更とサイズ変更のイベントが発生すると、メンバ変数 text にイベントに関する情報を保存してウィンドウを再描画するというプログラムです。
OnPaint() メソッドでは、文字列をウィンドウのクライアント領域の矩形の中央に描画するように StringFormat オブジェクトを設定して DrawString() メソッドで text メンバ変数を描画しています。このとき、文字列の表示を常に画面の中央に配置したいと考えたならば、ウィンドウのサイズ変更と描画を同期させなければなりません。サイズ変更イベントを受けない場合、ウィンドウサイズが変更されてもウィンドウを再描画しない限りテキストの位置が更新されることはありませんでした。しかし、このプログラムでは Resize イベントが発生するたびにウィンドウを再描画しているため、テキストは常にウィンドウの中央に描画されます。