東京工芸大学 工学部  電子機械学科 2年 後期 

応用プログラミング 第4回
 2017.10.17
藤木 文彦

http://fujiki.tv/t-kougei/ouyouprog/

fujiki.kougei@gmail.com  
 ■ 1   ■ 2   ■ 3   ■ 4   ■5 5   ■ 6   ■ 7   ■ 8   ■ 9   ■ 10   ■ 11  ■ 12    ■ 13   ■ 14   ■ 15   ■ 00   ■ 00   ■ 00

インデックスに戻る

  1.VC# の起動


 今週は、


を中心に勉強します。

 新規プロジェクトを開いた段階で、プロジェクト名を指定するウインドウが開いたら、名前を、

" Project401 "

として開いてください。


 デザインウインドウの名前も

Form1 -> DrawLine


に変更しておきましょう。(プロパティのなかの、Text を変更)


(プロジェクト名ではなく、内容のわかりやすい名前にしました。ここで付ける名前は、ウインドウの上部に表示されるだけで、プロジェクト名や、ファイル名には関係しません。)
 それから、ウインドウの大きさも、ちょっとだけ大きくしておきましょう。(先週やりましたよね。)



 ここまでが、準備です。

 それでは、実際の演習を始めましょう。

  2.出来上がりイメージ


 初めに今日の演習で作るプログラムの内容と、完成(間近の)イメージを掲げておきます。

 課題1は、
 (x1,y1)-(x2,y2) の各値を入力すると、それを結ぶ直線を順に描画するプログラムを作成します。




  3.画面の作成


 もう、1つ1つの配置を順を追って説明する必要はありませんね。
 とりあえず、次のような状態になるくらいまで自力で配置しましょう。




 なお、下の部分の四角い箱は、ここにこれから図面を描くための領域です。
 これは、 ”PictureBox " というのを選択して配置します。(下図参照)
 大きさは、適当で構いません。その大きさにしたがって、描ける図面の大きさが決まりますので、以下のプログラム実行時に表示される数値に、違いが出ます。




 ここで、 (x1、y1)が、直線の始点、(x2、y2)直線の終点の座標です。
 
初期値に、全て ”0” を入力しておいてください。プロパティの”Text”の部分に ”0” を書きます。

 なお、
座標系は、普通のグラフと違い、左上が、(0,0)で、Y座標は、下がプラスです。

 たとえば、X座標が 0〜200、 Y座標が 0〜100 だとすると、下図のようになります。

 0             →          200
              X座標


 ↓  Y座標



 100 

 4.図面の描画動作の記述



 次に、図形を書くプログラムを挿入します。

 「描画」ボタンを押したら、枠線を描き、指定された直線を枠内にひくプログラムを作ります。

 まず、何はともあれ、
「描画」ボタンをダブルクリックし、次のようなプログラムを入力してみます。

  private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width-1;
int height = this.pictureBox1.Height-1;
g.DrawRectangle(Pens.Black, 0, 0, width,height);
int x1 = int.Parse(textBox1.Text);
int y1 = int.Parse(textBox2.Text);
int x2 = int.Parse(textBox3.Text);
int y2 = int.Parse(textBox4.Text);
Pen redPen = new Pen(Color.Red, 3);
g.DrawLine(redPen, x1, y1, x2, y2);
}



 上のプログラムの textBox1  などは、自分で配置したテキストボックスの番号ときちんと合うように、必要に応じて書き直してください。
 (長さなどから、1を引かないと枠線がうまく表示されません。)

 終了ボタンを以下のように設定するのも忘れないでくださいね。





 ここで、再度、デザインウインドウの名前を変更しておくことを忘れないようにしましょう。
 ウインドウデザインウインドウの名前

Form1 -> DrawLine


に変更しておきましょう。(プロパティのなかの、Text を変更)

(テキストの最初に書いておいたことを再度確認)


 ここで、いったん作業ファイルを保存しておきましょう。

「ファイル」
「名前をつけて Form1.cs を保存」を選び、そこで名前を、
”Project401.cs”として、保存しておきましょう。


 そして、全体のプロジェクトを、保存するために、

「すべてを保存」で保存しておきます。このとき、プロジェクト名が、”Project401”になっているかどうか確認してください。(どうしても名前がうまく変更できないときは、其のままで構いません。)

 では、この辺で一度実行してみましょう。
 実行すると次のような画面が出るはずですので、数値を、たとえば次のように入力します。

 「描画」ボタンを押すと次のようになるはずです。



赤い線の左上が(10,10)の点、
右下が(50,50)の点です。

 数値以外の入力があった場合のエラー処理は、前回やりましたが、簡単のため、ここでは省略します。
 整数であれば、大きくても、マイナスでも大丈夫なはずです。(ただし、数値を入れなおしても、新しい線はひかれません。)


  5.描画前に画面にデータを表示する方法


 入力する数値の大きさの範囲がわからないと、数値を入れにくいので、描画画面の大きさをあらかじめ表示するようにします。

 そのためには、今までの部分とは別の場所に、命令を入力します。
 プログラムの先頭にある、

public Drawline( )    以下の場所に、次のようなプログラムを入力してください。
(場合によっては、 Form1( ) のままになっている人もいるかもしれませんが、その時は、以下の最初の行は書き直さずに2行目からを入力してください。)

 このプログラムは、ほかの入力などが行われる前に実行され、ウインドウの大きさを、画面の右上部分にテキストとして表示するものです。

  public DrawLine()
{
InitializeComponent();
Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width - 1;
int height = this.pictureBox1.Height - 1;
label2.Text = "0 =< x <= " + width + "\n0 =< y <= " + height;
}






 【演習問題1】 


 授業の説明に従って、”Project401" を一緒に作成します。
 途中で一度、「ファイル」メニューから「csファイルに名前を付けて保存」を選び、ファイル名を、 " Project401 " に変更して保存しておきます。

 授業で行ったことを実行しなさい。

 Project401.cs をメールに添付して送ってもらいます。


 


実行画面のコピー方法

 実行時の画面はこんな風になっているはずですが、Word でスクリーンショットを撮ろうとすると、せっかく描いた絵が消えてしまいます。
 そこで、次のようにします。





画面が表示されている状態で、キーボードの右上にある、


「Print Screen」


キーを押します。

このとき、何の変化も起きませんが、画面がバッファに記憶されています。


そのあと、Word画面で、

マウスの右クリックを押し、「貼り付け」を選びます。
貼り付け形式は特に指定しなくても、一通りのはずですが、画面に確認の画像が出てくると思いますから、それで確認してください。




このあと、貼り付けられた画像の一部だけを使うために、「部分的にトリミング」を指定しますが、詳細は省略します。






  6.課題2の出来上がりイメージ


 課題2は、
 マウスでクリックした場所に小さな円を描くものです。


 いったんVC# を閉じて、再度開いて、新規プロジェクト作成を選んでから、

”Project402"
を指定して開始します.

ウインドウのタイトル( Text プロパティ) は、 " DrawCircle " としておきましょう。

  7.マウスクリックという 「イベント」で円を描く


 「マウスがクリックされたら、指定のプログラムが実行される」というようなプログラムを作るときには、

「マウスがクリックされた」という「イベント」の発生によって、実行されるプログラムを書きます。

そのためには、

「イベントで呼び出されるプログラム」

を作成します。

次のように、右のプロパティウインドウで、 「  」ボタンを押してから、その下のメニューの中の
「MouseClick] を選びます。この時、
最初は表示の右側が空白ですが、ダブルクリックすると、自動的にイベント名が入ります。
ここでは、" Form1_MouseClick" となっています。




 次に上の図面の 緑わく内をダブルクリックすると、このプログラムの編集モードになります。
自動的に、マウスクリックイベントを記述するプログラム入力部分が開きますので、ここで、プログラムを入力します。




 入力するのは、次のプログラムの赤字の部分です。

 private void Form1_MouseClick(object sender, MouseEventArgs e)
{

Graphics g = this.CreateGraphics();
Pen dp = new Pen(Color.Black, 1);
Point p = new Point();
p.X = e.X;
p.Y = e.Y;

g.DrawEllipse(dp, p.X, p.Y, 10, 10);

}


プログラムの中身は、どれも今までに見たことのないようなものであると思います。

1行ずつ説明しましょう。

Graphics g = this.CreateGraphics();

これから、グラフィック描画に使う変数名(位置とか、色とか、様々な属性を要素として持つ変数)として、"g" という名前の変数を宣言します。(色やペンの種類などを何種類か使うのなら、この変数名を何個か設定します。)

Pen dp = new Pen(Color.Black, 1);

絵を描くペンの色と太さを設定して、新しいペン属性の変数、"dp" を使うと宣言します。

Point p = new Point();

位置属性(ポイント属性)をもつ変数 "p" を宣言します。

p.X = e.X;
p.Y = e.Y;


"e" というのが、あらかじめシステムが、この変数を呼び出すときに、データとして持ってきた各種の値を入れている変数です。その中から、X座標、Y座標( e.X, e.Y )を取り出し、プログラム中で使う変数 "p" ( p.X, p.Y ) に代入します。

g.DrawEllipse(dp, p.X, p.Y, 10, 10);

ペン "dp" を使って、座標、p.X, p.Y から、縦10 横10 の大きさの楕円(円)を描きます。

いきなりいろいろなことが出てきますが、一旦動かしたあと、この設定をいろいろと変更してみましょう。

 【演習問題2】 


 Project402 を作成し、実行結果画面をプリントして提出し、cs ファイルをメールに添付して送りなさい。

  8.イベントを自分で付け加える方法

マウスクリックなどの外からの操作「イベント」を作成する際には、通常は、前の問題のように、プロパティウインドウからイベントを作成し、自動的に作成される部分にプログラムを入力します。

ただ、自分でイベントを「登録」することで、プログラムを作ることができます。(あまり推奨はされませんが)

以下のように、  Initialize の部分に、自分でイベントを登録する( this.MouseDown += ... の部分 )ことができます。

そのような方法でのプログラムを行ってみましょう。


以下の、
赤文字の部分が、自分で入力するところです。
終了ボタンは自分で作ってください。



namespace Project403
{
public partial class Drawcircle : Form
{
public Drawcircle()
{
InitializeComponent();
this.MouseDown += new MouseEventHandler(fm_MouseDown);
}

public void fm_MouseDown(Object sender, MouseEventArgs e)
{
Graphics g = this.CreateGraphics();
Pen dp = new Pen(Color.Black, 1);
Point p = new Point();
p.X = e.X;
p.Y = e.Y;

g.DrawEllipse(dp, p.X, p.Y, 10, 10);

}




}

}


 【演習問題3】 


 自分でイベントを登録するプログラム Project403 を作成しなさい。

 Project403 を作成し、実行結果画面をプリントして提出し、cs ファイルをメールに添付して送りなさい。

 【演習応用課題4】 


Project404

下の画面にあるように、枠の中では青丸を、枠の外では緑の楕円を描くようなプログラムを作成しなさい。





private void Form1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = this.CreateGraphics();
Pen dp = new Pen(Color.Green, 5);
Point p = new Point();
p.X = e.X;
p.Y = e.Y;

g.DrawEllipse(dp, p.X, p.Y, 20, 10);


}

private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
Pen dp = new Pen(Color.Blue, 3);
Point p = new Point();
p.X = e.X;
p.Y = e.Y;

g.DrawEllipse(dp, p.X, p.Y, 20, 20);




【補足】(これは、問題としてやる必要はありません。)

Project402 では、1つ円を描いたら、その座標はデータとして記録されずに、次の場所に描画していました。
画面上に描画するだけならいいのですが、データとして保存しておきたい場合には、次のようなプログラムになります。
データを、 List<Point> 型の ls に保存しています。

作る場合は、プロジェクト名を Project409 としてください。


public partial class DrawCircle : Form
{

public DrawCircle()

これに、次の1行を足す。

// 次の1行を入れる
private List<Point> ls;     (  ls は 小文字 の エル です。)


こんな風になるはず、

public partial class DrawCircle : Form
{

// 次の1行を入れる
private List<Point> ls;

public DrawCircle()

■次に、

public DrawCircle()
{
InitializeComponent();
ls = new List<Point>();

ls の行を上の位置に入れてください。

■次に、あと2行、追加する。
InitializeComponent();
ls = new List<Point>();
this.MouseDown += new MouseEventHandler(fm_MouseDown);
this.Paint += new PaintEventHandler(fm_Paint);

 ここで、エラーが出るけれど気にしないように。(あとで、全部設定すると消えるはずです。)

//次の行も入れる。今度は、publicから、全部入力する。
//入れる位置に注意。 } で閉じられた後に入れている。(詳細は、ホームページを見ること。)


public void fm_MouseDown(Object sender, MouseEventArgs e)
{
Point p = new Point();
p.X = e.X;
p.Y = e.Y;
ls.Add(p);
this.Invalidate();
}

■その下に、以下の部分も入れる。

//これも挿入する。2
public void fm_Paint(Object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen dp = new Pen(Color.Black, 1);

foreach (Point p in ls)
{
int x = p.X;
int y = p.Y;
g.DrawEllipse(dp, x, y, 10, 10);
this.label1.Text = " ";
this.label1.Text = "X= " + x.ToString() + "Y= " + y.ToString();
};

}

//label1 などが、まだ設定されてないので、エラーになるが、これも当面そのまま。





 namespace WindowsFormsApplication1
{
public partial class DrawCircle : Form
{

// 次の1行を入れる
private List<Point> ls;

public DrawCircle()
{
InitializeComponent();
ls = new List<Point>();
//ここを書いた時には、fm を設定していないので、エラーが下に表示されるはずであるが、別の名前になるかも知れないが、後半を入れると治る。

this.MouseDown += new MouseEventHandler(fm_MouseDown);
this.Paint += new PaintEventHandler(fm_Paint);
}
//これも挿入する。1
public void fm_MouseDown(Object sender, MouseEventArgs e)
{
Point p = new Point();
p.X = e.X;
p.Y = e.Y;
ls.Add(p);
this.Invalidate();
}
//これも挿入する。2
public void fm_Paint(Object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen dp = new Pen(Color.Black, 1);

foreach (Point p in ls)
{
int x = p.X;
int y = p.Y;
g.DrawEllipse(dp, x, y, 10, 10);
this.label1.Text = " ";
this.label1.Text = "X= " + x.ToString() + "Y= " + y.ToString();
};

}

private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}

}
}