C#のフォームアプリケーションを作っていると、描画の更新などイベントを使わなければ回りくどかったり、難しい場合がある。イベントを使いこなせても、今度は値を渡したいとか、どこで発生したイベントかを知らせたり、渡した値でハンドラの振る舞いを変えたいとかいろいろ出てくる。
イベントに値を追加して、イベントハンドラでその値を受け取らせたい場合は、クラスを作ってそれを入れ物として値を受け渡せばよい。じつはそういう例がMouseイベントでも見られる。マウスMoveはEventArgsではなく、マウスの座標をイベントオブジェクトの中に入れ込んだMouseEventArgsという型をやり取りしている。
MouseEventArgsをMSDNを調べてみると、EventArgsというクラスを継承して作られていることがわかる。
https://msdn.microsoft.com/ja-jp/library/system.windows.forms.mouseeventargs(v=vs.110).aspx
つまり、これと同様にしてEventArgsを継承したクラスを用意し、そのクラスに好きな値を持たせればよいことになる。
※マウスイベントの試し方:pictureBoxやパネルの中にあるマウス系イベントのMouseMoveイベントを、フォームデザイナのプロパティで設定してみると、MouseEventHandlerというハンドラが追加されることがわかる。
※手順:pictureBoxをフォームに追加して、プロパティ画面の雷マークを押すと、イベントのプロパティが現れる。この中に、マウスという項目がある。このなかのMouseDownという項目の右をダブルクリックすると、pictureBox1_MouseDownという関数がフォームデザイナでForm内に自動的に追加される。
//色が変化したときにイベントで飛ばすプロパティを入れたクラス
class ColorEventArgs : EventArgs
{
Color c;
public ColorEventArgs(Color c)
{
this.c = c;
}
public Color color
{
get { return c; }
}
}
上記入れ物をイベントに載せて飛ばすためには、
・その型を持ったイベントの宣言
・その型を持ったオブジェクトを受けられるデリゲートの宣言
の2つが必要。
//イベント
public event ColorEventHandler CurrentColorChange;
//ColorEventArgs型のオブジェクトを返すようにする
public delegate void ColorEventHandler(object sender, ColorEventArgs e);
デリゲートに、イベントが発生したときにやってほしい関数を渡すのを忘れずに。
//イベントで処理する関数を登録
ceditor.CurrentColorChange += new ColorEditor.ColorEventHandler(this.currentColorChanged);
イベントを発生させるには
public void setCurrentColor(Color c)
{
currentColor = c;
if (CurrentColorChange != null)
{
CurrentColorChange(this, new ColorEventArgs(currentColor));
}
}
という風にして、先ほどのイベントを関数のようにして呼ぶ。
そのときに引数として先ほど作ったデータの入れ物型のオブジェクトを作って渡す。
すると、イベントハンドラ先で入れ物を受け取り、そのなかのメンバにアクセスして
データを取り出すことができる。この中には、イベントの送り先とかデータを何でも入れられる。
これによりどこが発生させたイベントかを判別することで振る舞いを変えたりできる。
イベントハンドラはこんな風にかける。
private void currentColorChanged(object sender, ColorEventArgs e)
{
colorNum_t num = e.color;
}
ちなみに、他のイベントハンドラと共用で使いたい場合は、一旦基底クラスのEventArgsで受けておいて、
ほしいクラスのキャストをしてやってもよい。
private void currentColorChanged(object sender, EventArgs e)
{
colorNum_t num = ((ColorEventArgs)e).getColorNum();
}
イベントを使うとかなり色々なことが出来るようになった気になるが、あまり使いすぎたりあちこちからイベントを発生させたりすると、プログラムの流れが全く読めなくなって困る。