今回は、GUIコンポーネントの基本的な機能を提供するControlクラスを継承して、独自のコンポーネントを作ってみましょう。このコンポーネントは、128×128ピクセルの描画領域を持ち、マウスでクリックされると黒い点を描くというものです。前回は、コンポーネントのイベントハンドラを別に定義して登録する形で設定していましたが、今回は継承するクラスのイベントハンドラをオーバーライドする形で独自のイベント処理を追加してみることにします。 イベントハンドラのオーバーライドとクラス定義今回作成するビットマップパネルコンポーネントBPanelの仕様は、以下のとおりです。
この仕様を満たすために、コンポーネント内部に128×128ピクセルのBitmapを保持して、ここにマウスで描かれた結果を保存するようにしましょう。そして、そのBitmapを描画用のイベントハンドラOnPaint()で描画するようにします。 以上のことから、今回のコンポーネントで実装すべき処理は以下のとおりです。
このうち、最初の処理はコンストラクタで、「マウスクリック時」と「描画時」の処理はイベントハンドラをオーバーライドして実装してみましょう。まず、最初にコンポーネントの基本クラスControlを継承して独自のクラス(ビットマップコンポーネントクラスBPanelクラス)を定義します。 BPanelクラス宣言 class bpanel:Control このクラスのコンストラクタでは、まず自分のサイズを130×130ピクセルに設定します。続いて描画用ビットマップを作成し、ビットマップのGraphicsを通してビットマップ全体を白く塗りつぶします。 public BPanel() { Width=130; Height=130; bmp=new Bitmap(128,128); g=Graphics.FromImage(bmp); g.Clear(Color.White); } 次に、マウスクリック時のイベントハンドラOnMouseDown()をオーバーライドしてクリックされた座標に対応する黒点をbmp上に描画します。 protected override void OnMouseDown(MouseEventArgs e) { // 親クラスのOnMouseDown()を呼び出す base.OnMouseDown(MouseEventArgs e); // 以下で独自の処理を追加 // bmpの範囲外なら戻る if (e.X<1 || e.X>128 || e.Y<1 || e.Y>128) return; // 黒点を打つ bmp.SetPixel(e.X-1,e.Y-1,Color.Black); // コンポーネントを再描画 Refresh(); } このイベントハンドラでは、最初にbase.OnMouseDown()を呼び出すことでbase(親)クラスのイベントハンドラを実行し、その後独自の処理を行うようになっています。 次に、描画時のイベントハンドラOnPaint()でビットマップを描画します。こちらの方は、コンポーネント全体を自分ですべて描画するのでbaseクラスのOnPaint()を呼ぶ必要はないでしょう。 protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawRectangle(new Pen(Color.Black,1),0,0,129,129); e.Graphics.DrawImage(bmp,6,6); } イベントハンドラの処理は、引数で渡されたイベント情報からコンポーネント描画用のGraphicsを取得し、枠を描いてからbmpを描画するだけです。 以上で、ビットマップコンポーネントBPanelクラスができました。 BPanelクラスclass BPanel:Control { // ビットマップパネル private Bitmap bmp; public BPanel() { Width=130; Height=130; bmp=new Bitmap(128,128); Graphics.FromImage(bmp).Clear(Color.White); } protected override void OnMouseDown(MouseEventArgs e) { // 親クラスのOnMouseDown()を呼び出す base.OnMouseDown(e); // 以下で独自の処理を追加 // bmpの範囲外なら戻る if (e.X<1 || e.X>128 || e.Y<1 || e.Y>:128) return; // 黒点を打つ bmp.SetPixel(e.X-1,e.Y-1,Color.Black); // コンポーネントを再描画 Refresh(); } protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawRectangle(new Pen(Color.Black,1),0,0,129,129); e.Graphics.DrawImage(bmp,1,1); } } 最後に、Formを継承したアプリケーションクラスにBPanelを貼り付けます。 public class test:Form { private BPanel bp; test() { // コンストラクタ // ビットマップパネルのインスタンス生成 bp=new BPanel(); ClientSize=new Size(130,130); // bpを自分(フォーム)に追加 Controls.Add(bp); } public static void Main() { // フォーム生成 test app=new test(); // イベントループに入る Application.Run(app); } } これで独自のコンポーネントを作成し、そのコンポーネントをアプリケーションで利用する流れが一通りできましたね。独自のコンポーネントを作成するプログラムの構造はJavaやVCLとほとんど同じで、Windowsのハンドルやメッセージ処理を意識する必要もないため非常にわかりやすい構造になっています。 プログラムプログラムソースを csc bcm.sc bvm などとして実行したら、コンポーネントの内部をクリックしてみてください。クリックした座標に黒点が打たれます。 |