ビットマップパネルコンポーネントの作成

今回は、GUIコンポーネントの基本的な機能を提供するControlクラスを継承して、独自のコンポーネントを作ってみましょう。このコンポーネントは、128×128ピクセルの描画領域を持ち、マウスでクリックされると黒い点を描くというものです。前回は、コンポーネントのイベントハンドラを別に定義して登録する形で設定していましたが、今回は継承するクラスのイベントハンドラをオーバーライドする形で独自のイベント処理を追加してみることにします。

イベントハンドラのオーバーライドとクラス定義

今回作成するビットマップパネルコンポーネントBPanelの仕様は、以下のとおりです。

  • コンポーネントの大きさは130×130ピクセル
  • 外枠1ピクセルの内側に128×128ピクセルの描画領域を表示
  • 描画領域をマウスでクリックするとそこに1ピクセルの黒点を打つ

この仕様を満たすために、コンポーネント内部に128×128ピクセルのBitmapを保持して、ここにマウスで描かれた結果を保存するようにしましょう。そして、そのBitmapを描画用のイベントハンドラOnPaint()で描画するようにします。

以上のことから、今回のコンポーネントで実装すべき処理は以下のとおりです。

  • 最初にサイズを130×130ピクセルに設定し、描画用Bitmapを作成
  • マウスクリック時に、クリックされた座標に対応するBitmapの座標に黒点を描画
  • 描画時に130×130ピクセルの矩形を描き、その内側にBitmapを描画

このうち、最初の処理はコンストラクタで、「マウスクリック時」と「描画時」の処理はイベントハンドラをオーバーライドして実装してみましょう。まず、最初にコンポーネントの基本クラス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);

      }

  }

これで独自のコンポーネントを作成し、そのコンポーネントをアプリケーションで利用する流れが一通りできましたね。独自のコンポーネントを作成するプログラムの構造はJavaVCLとほとんど同じで、Windowsのハンドルやメッセージ処理を意識する必要もないため非常にわかりやすい構造になっています。

プログラム

プログラムソース表示

プログラムソースを

csc bcm.sc
bvm

などとして実行したら、コンポーネントの内部をクリックしてみてください。クリックした座標に黒点が打たれます。


プログラミング資料庫 > Windowsプログラミング研究室