人気ブログランキング | 話題のタグを見る

コールバック

GUIのプログラミングはイベント駆動型のプログラム様式が使われる。イベント駆動型のプログラムでは、イベントが発生すると、そのイベントに対応した関数が呼び出されて処理が行われる。

この方式のプログラミング環境では、プログラマは発生するイベントの種類とイベントが発生したオブジェクトの情報に応じて、イベントハンドラとなる関数を記述するだけだ。したがって、常に全体を考えてプログラムするフロー駆動型のプログラミング様式と比べて負担が少ない。また、きちんと動いているプログラムを土台に、それに改良を加えていくという方法も簡単にできる。プログラムの一部を変更したために全体が動かなくなってしまうという事態を引き起こすことも少なくなる。

しかし、便利なイベント駆動型のプログラミング様式だが、C言語でプログラムを書ければ、すぐにイベント駆動型のプログラムを書けるという訳ではない。C言語を習ってすぐに書けるのは、フロー駆動型のプログラミングであって、イベント駆動型のプログラムではない。イベント駆動型のプログラムは、イベント駆動型のプログラミングを提供する環境がないと書けない。C言語で書くことはできるが、そのためには、イベント駆動型の環境を提供するライブラリを使うか、自分で作るかしなければならない。

C言語でプログラムを書くときも、最初から最後まで続く長いプログラムを書いていくことはない。まず、部品となる小さい関数を作ったり、ライブラリを利用したりして基本的なプログラムの部品を作っておき、その部品を組み合わせてさらに大きなモジュールを作り、最後にそれをメイン関数にまとめ上げるという作業をする。

このようなフロー駆動型のプログラムでは、部品となる下層の関数から、それを利用する上層の関数が呼ばれたりすることはない。ところが、イベント駆動型のプログラミングでは、インフラとなるライブラリからそれを利用する上層の関数を呼ばないとプログラムできないのだ。

イベントの発生を検知するのは下層のライブラリの関数のしごとだ。しかし、その関数がイベントを検知した場合それに対応するイベントハンドラとなる関数は、上層でプログラミングされていなければならない。

たとえば、サービスステーションに電話で注文するときのことを考えてみよう。あの製品を送って下さい、とか、この製品に加工して下さいとか、ユーザは電話で注文することができる。しかし、それらの加工はステーション側で行われるので、ユーザに加工の依頼がくることはない。しかし、どうしてもユーザの方でも加工をしたいときがある。そういう時はどうするかというと、ユーザの電話番号をステーションに知らせておき、ユーザの手が必要になったときステーションから電話をかけてもらうようにするのだ。

このようにサービスステーションから連絡をもらうために電話番号を教えておくことをコールバックという。イベント駆動型プログラミングでよく出てくるコールバック関数は手続きがこれとよく似ているためにそう呼ばれている。下層のライブラリに上層の関数のアドレスを入れたポインタを引数としてわたして、下層のライブラリから上層の関数を必要に応じて呼び出すことができるようにする仕組みだ。

イベントの発生を監視するのは下層のライブラリの仕事だが、イベントが発生したとき、上層の関数を呼び出せれば、ユーザの方はイベント監視の細かいことについては、ライブラリに任せたままで、イベントが発生した時のプログラムだけに集中できる。C#の場合、.NET のクラスライブラリがそういうイベントの処理を分担してくれている。

便利なイベント駆動型のプログラム様式だが、これを使いこなすためにはポイントがふたつある。ひとつは、ライブラリで処理できるイベントの種類を知らなければならないということ。もうひとつは、コールバック関数をイベントハンドラとしてライブラリに登録する方法を知っておくことだ。

Visual C# のフォームデザイナでプログラミングするとき、ボタンなどのコントロールを選択し、プロパティウィンドウのイベントボタンをクリックしてイベントの種類をダブルクリックすると、Form1.cs が開いてカーソルがコールバックルーチンを編集できるようにして待機するが、このときどういう事が起こっているかというと、たとえば、button1 を選択し、イベントの Click をダブルクリックすると、自動的に

private void button1_Click(object sender, EventArgs e)

というコールバック関数のひな形がForm1.csに作成される。しかし、button1_Click を記述しただけでは、クリックイベントが発生しても button1_Click () が実行されることはない。button1がクリックされたときにこの関数がイベントハンドラーとして働くことをあらかじめ .NET に通知しておかなくてはならない。実は、イベントのフィールドをダブルクリックしたときには見えないところで、Form.designer.cs の InitializeComponent () メソッドに次の文が挿入されているのだ。

this.button1.Click += new System.EventHandler(this.button1_Click);

これは、button1のClickプロパティに、System.EventHandlerクラスの button1_Click 関数を登録したオブジェクトを追加しているという意味がある。これをやっておくと、button1 がクリックされたときに、button1_Click というイベントハンドラーが呼び出されて処理が行われる。

予定していなかったイベントに対するコールバック関数を作ってしまったとき、Form1.cs でその関数を削除してもビルドエラーになる場合、それに対応するコールバック関数を登録する文を Form1.designer.cs で消去するとビルドに成功する。

このように、Form1.designer.cs の中で、button1 などのコントロールの Click などのような、イベント名と同じプロパティに、System.EventHandler オブジェクトを追加するという操作さえ知っておけは、イベントに対応するコールバック関数をプログラムするだけでいいというイベント駆動型プログラム様式のお気楽さを堪能することができる。

イベントに対応するコールバック関数を書き、それをイベントハンドラで登録するという .NET のイベント駆動型プログラミングの基本を理解しておけば、C#でするプログラミングは非常に楽をできるのだということがわかるだろう。
by tnomura9 | 2010-01-27 07:07 | C# | Comments(0)
<< メニューを作る オブジェクトをマウスで動かす >>