07.03 キャンパスの作成


少々復習しながら前に進めていきましょう。

1.コンストラクターとデストラクター
このクラスが起動(インスタンス化)した際、最初に呼ばれるのが「コンストラクター」というクラス名と同じ名前の処理でした。
そこでまず、ここにこれから使用するビットマップとグラフィックス オブジェクトを一回だけ作成しておきます(以前から言っておりますようにビットマップを使用する描画方法以外にもいろいろやり方はあると思いますが、最初に勉強したこの方法で進んでいきます)。



2.グローバル変数
C言語の入門編で勉強してきたと思いますが変数を定義する際、関数内部に定義する変数はローカル変数で関数内部でしか使用できませんが、下記のようにクラス内で「public」という宣言の次に使用すると同じ名前空間上であればどこでも使用できます。従って、コンストラクター内でインスタンス化しても、ビットマップ イメージオブジェクトとグラフィックオブジェクトは同名前空間上のすべてで有効となります。



3.プリコンパイル インクルード(#include)とプラグマ(#pragma once)
プログラムの先頭に””がついた行があります。これはコンパイラを制御する記号で「プリコンパイル用宣言」といって、コンパイルが処理を開始する前に行う「宣言」や「処理」を指します。

A)#include(インクルード)
「#include <math.h>」という行があります。lこの機能は、この行を無くすと直ぐにわかります.ちなみに一時的に行(ステートメント)を一時的に無効にする場合は前に”//”を付けることによって「コメント化」します。コメント化の後にビルドしてみると、以降に登場する「sin」「cos」が存在しないというエラーになります。つまりこのインクルードというのは事前に「”math.h”というヘッダーファイルを所定の場所から読んできてコンパイルを開始しろという命令」です。”math.h”というのはVC++が内部で持っている数学用関数のヘッダーファイルで、コンパイラーで使用できる関数は.NET Framework以外にも、このような数学用・標準入出力用・ウィンドウズ標準・イーサネット用など様々なものが用意されていて必要な関数のヘッダーをインクルードで呼んでくるということになります。 これはVC++のリファレンスマニュアルで使用したい関数を検索したときに「必要ヘッダーファイル」として記載があるものを、順次追加していくことになります。これは最終的に出来上がった容量の問題やコンパイル完了までの時間を短くするためにオプション化されています。

B)#pragma once
プラグマ ワンス」は、「MyFrom.cpp」を見ていただくとわかるのですが、「MyForm.h」はヘッダーファイルとしてインクルードされています。ソリューションエクスプローラ内で現在作成しているヘッダーは、必ず何かの「本体(.cpp)」にインクルードされる主従関係を持っています。但しプログラマーは同じヘッダーを必ず一回だけしかインクルードしてはいけないという制約はありません。しかし複数存在するということは定義したい変数等を重複して定義するということになってしまいます。このため 複数のファイル内でインクルードされていても「一回だけしか処理しません」という宣言となります。

C)#記号
皆さんはTwitterなどSNSやっていますか?
そこにハッシュタグという言葉がありキーワードのように使用してハッシュタグ検索してまとめて表示するなどに使用されます。この「ハッシュ」というのは、ここに出てくる”#”(ハッシュ記号)の記号のことです。実はこの記号全角で見ると面白いことが分かります。
同じような形のものがありますがすべて違うのです。

音楽記号シャープ ””   ハッシュ記号 ””  漢字のいげた桁”

だいぶ違いますよね!
今回のように半角の場合は同じですが、全角の場合はこのように違って、#includeを全角で書くと真ん中のハッシュ記号となります。
なぜならハッシュタグの起源は#includeの前についているプリコンパイル用ハッシュ記号であるからです。

ご存知でした?


#pragma once
#include <math.h>

namespace ProtoType {

  using namespace System;
  using namespace System::ComponentModel;
  using namespace System::Collections;
  using namespace System::Windows::Forms;
  using namespace System::Data;
  using namespace System::Drawing;

  public ref class MyForm : public System::Windows::Forms::Form
  {
  public:
    Graphics^      gf;
    Bitmap^       canvas;

    MyForm(void)
    {
      InitializeComponent();
      //pictureBoxを対象とするビットマップImageオブジェクトを作成する
      canvas = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);

      //ImageオブジェクトのGraphicsオブジェクトを作成する
      gf = Graphics::FromImage(canvas);
    }

  protected:




07.04 アニメーションの作成


次に前回学んだ方法でTimerコントロールを貼り付け、インターバル時間は変更せずにおいてください。

【Timerの設置】



開始用のボタンコントロールを追加したら内容を次のように入力してきてください。


void  draw_pair(void)
{
  double     r;
  int       PosX=0;
  int       PosY=0;
  int       th;
  Random^     rr;

//  gf->Clear(Color::White);

  rr = gcnew Random();
  r = rr->Next(0,10);
  th = rr->Next(0, 360);
  PosX += (int)(r * cos((double)th));
  PosY += (int)(r * sin((double)th));

  gf->DrawEllipse(Pens::Black, PosX+pictureBox1->Width/2,
      PosY+pictureBox1->Height/2, 10, 10);
  pictureBox1->Image = canvas;
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
  timer1->Enabled = true;
}

private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
  draw_pair();
}



起動すると下記のような動作になります。



【 ブラウン運動 失敗例1】


いよいよ画面で動くものができましたが なんだか変です!

真ん中あたりから真っ黒になっていきます。 どうしてでしょうか?


それはキャンバスに使用したビットイメージがグローバル変数として初回一回だけ設定しただけのため、同じキャンバスに描画していったので以前描いた絵が残っているためです。

ではプログラムを少々改修してみましょう!
プログラム途中に下記の部分がありますが、文中の”//”を削除してみて下さい。

// gf->Clear(Color::White);

さあ!やってみましょう!!