今回は、直線のみを使って絵を描くプログラムを作ってみます。
クライアント領域の、任意の場所でマウスを左クリックします。
そして、ボタンを押したままマウスをドラッグします。
すると、最初にクリックした点を始点として、マウス位置を終点とする直線が、刻々と描かれます。ボタンを放すと、直線の描画が完了します。これを、繰り返して絵を描きます。
失敗しても、やり直しはできません。描画する直線の数には限りがあります。ファイルに保存することはできません。
ともかく、非常に原始的なお絵かきソフトです。
では、プログラムを見てみましょう。
// 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