 今回は、直線のみを使って絵を描くプログラムを作ってみます。
今回は、直線のみを使って絵を描くプログラムを作ってみます。
クライアント領域の、任意の場所でマウスを左クリックします。
そして、ボタンを押したままマウスをドラッグします。
すると、最初にクリックした点を始点として、マウス位置を終点とする直線が、刻々と描かれます。ボタンを放すと、直線の描画が完了します。これを、繰り返して絵を描きます。
失敗しても、やり直しはできません。描画する直線の数には限りがあります。ファイルに保存することはできません。
ともかく、非常に原始的なお絵かきソフトです。
では、プログラムを見てみましょう。
// mouse03.cs
using System;
using System.Drawing;
using System.Windows.Forms;
class mouse03 : Form
{
    Point[] pt;
    int no;
    Point prevpt1, prevpt2;
    const int nMaxNo = 100;
    public static void Main()
    {
        Application.Run(new mouse03());
    }
    public mouse03()
    {
        Text = "猫でもわかるC#プログラミング";
        BackColor = SystemColors.Window;
        
        pt = new Point[nMaxNo];
        no = 0;
        
        MainMenu mm = new MainMenu();
        Menu = mm;
        MenuItem miFile = new MenuItem("ファイル(&F)");
        mm.MenuItems.Add(miFile);
        MenuItem miExit = new MenuItem("終了(&X)");
        miFile.MenuItems.Add(miExit);
        miExit.Click += new EventHandler(miExit_Click);
    }
    void miExit_Click(object sender, EventArgs e)
    {
        Close();
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (no >= nMaxNo)
        {
            MessageBox.Show("設定数を超えました",
                "限界", MessageBoxButtons.OK,
                MessageBoxIcon.Stop);
            return;
        }
        pt[no] = e.Location;
        prevpt1 = e.Location;
        no++;
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        
        pt[no] = e.Location;
        no++;
        Invalidate();
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        for (int i = 0; i < no / 2; i++)
        {
            g.DrawLine(new Pen(new SolidBrush(Color.Red)),
                pt[i * 2], pt[i * 2 + 1]);
        }
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (e.Button == MouseButtons.None)
            return;
        Graphics g = CreateGraphics();
        g.DrawLine(new Pen(new SolidBrush(Color.White)), prevpt1, prevpt2);
        g.DrawLine(new Pen(new SolidBrush(Color.Blue)), e.Location, prevpt1);
        prevpt2 = e.Location;
        g.Dispose();
    }
}
このプログラムは、mouse03クラスしかありません。mouse03クラスのフィールドに、Point構造体の配列ptを用意しました。 直線の始点の座標をpt[0]とすると、終点の座標をpt[1],次の直線はpt[2],pt[3]という具合に、描画した線分の座標を記録していきます。(もちろん、後の章で書きますが、もっと良い方法があります。)
prevpt1, prevpt2には、直前に描画した直線の始点、終点を保存しておきます。
配列ptの要素数はnMaxNoとします。
Mainメソッドは、いつも通りです。
コンストラクタでは、配列を確保したり、メニューを作ったりしています。
miExit_Clickメソッドは、メニューから「終了」が選択されると呼び出されます。 単に、メインフォームを閉じてプログラムを終了します。
次は、このプログラムではかなり重要な、マウスボタンが押されたときの処理です。 ここでは、OnMouseDownメソッドをオーバーライドしています。
noがnMaxNo以上であった場合、配列に書き込めないのでその旨メッセージボックスを出してすぐに制御を返します。
pt[no]に、ボタンが押されたところの座標を記録します。そしてprevpt1にも、その座標を記憶させます。noを一つ進めます。
ボタンが離されたときの処理は、OnMouseUpメンバをオーバーライドして行っています。
ここでは、ボタンが離されたときの座標をpt[no]に蓄え、noを進めます。そして、Painイベントを発生させ、クライアント領域の再描画を行わせます。
マウスボタンが押されたところを始点、離されたところを終点としてpt[no]に記憶しておくことになります。
さて、Paintイベントの処理では、pt[i*2]からpt[i*2+1]の直線を描画します。 iは、0からno/2-1まで変化させればよいですね。
次は、マウスが移動中の時の処理です。
ボタンが押されていないときは、何もせずに戻ります。
最初にprevpt1から、prevpt2まで白で直線を描画し、以前の直線を消します。
そして、現在のマウス位置からprevpt1までを青色の直線で描画します。
では、実行結果を見てみましょう。
 マウスをドラッグ中は、始点とマウス位置までの直線が青色で表示されます。
マウスをドラッグ中は、始点とマウス位置までの直線が青色で表示されます。
 マウスボタンを放すと、直線が赤色で確定します。
マウスボタンを放すと、直線が赤色で確定します。
 簡単な絵を描画することができます。
簡単な絵を描画することができます。
Update 04/Jan/2007 By Y.Kumei