Shapeクラス(設計)

ShapeクラスはImageUtilsのBmpProcを拡張した単純な作図クラスとする。最初はBmpProcを派生しようかとも考えたのだが、privateメンバーが多くて派生しても恩恵に授かれそうにないのでBmpProcをメンバーに持つ形で作ることにした。だいたいの雰囲気はこんな感じ。

ShapeBase
+SetPixel() ...仮想関数にしておく
+DrawLine()
+DrawRectangle()
+FillRectangle()
+DrawEllipse()
+FillEllipse()

Shape1 : ShapeBase, IDisposable
-BmpProc1 proc
+SetPixel() ...基底の関数にoverride

Shape8 : ShapeBase, IDisposable
-BmpProc8 proc
+SetPixel() ...基底の関数にoverride

Shape24 : ShapeBase, IDisposable
-BmpProc24 proc
+SetPixel() ...基底の関数にoverride

Shape32 : ShapeBase, IDisposable
-BmpProc32 proc
+SetPixel() ...基底の関数にoverride

まず作図関数群はShapeBaseという仮想クラスへ作成していく。これらはすべてSetPixel()という仮想関数を呼び出すことで動作するように仕掛けておく。
次にこのShapeBaseからBmpProcの種類数分のShapeXXを派生させる。これらはそれぞれに1つのBmpProcをメンバーに持ち、そのBmpProc特有のSetPixel()をoverrideで実装しておく。
実際に使う側のコードはこうなる予定。

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    int w = ClientSize.Width;
    int h = ClientSize.Height;
    if (w >= 2 && h >= 2)
    {
        Bitmap bmp = new Bitmap(w, h, PixelFormat.Format24bppRgb);
        Shape24 sh = new Shape24(bmp);
        Random r = new Random();
        for (int i = 0; i < 100; i++)
        {
            Color cl = Color.FromArgb(r.Next(256), r.Next(256), r.Next(256));
            int xx = r.Next(-100, w + 100);
            int yy = r.Next(-100, h + 100);
            int ww = r.Next(500);
            int hh = r.Next(500);
            sh.Color = cl;
            switch (r.Next(2))
            {
                case 0:
                    sh.DrawEllipse(xx, yy, ww, hh);
                    break;
                case 1:
                    sh.FillEllipse(xx, yy, ww, hh);
                    break;
            }
        }
        sh.Dispose();
        e.Graphics.DrawImage(bmp, 0, 0);
        bmp.Dispose();
    }
}

本当はBitmap作成からBmpProcを作成してそのBmpProcからShapeを作るような流れにしたかったのだが、BmpProcはビットマップの情報(Width、Height)などを公開していないのでShapeから描画範囲のクリップをするためには、BmpProcの作成はShape内部で行うように考えてこの形になった。