何か色々書いてくよ

楽しくなってきた。プログラミングの授業がね。
Win32GDIを扱うようになってから、コンソールのときとテンションとやる気が明らかに違う。
そろそろ最終課題で、何作るか考えなきゃなぁ・・・・。
まぁ、そんなわけで、やったプログラムの一部をば。

長いので、PDFファイルとしてあげときますんで、各自開いて閲覧してください。
PDFファイル→プログラム
見れない人は、Adobe Readerをインストールしてください。

※2011/11/18追記
ファイルが消失してしまったので、現在DL不可です。


では、解説に移ります。

んで、まずこのプログラムが何をしているのか。
これは、ウサギをウィンドウに描画し、両手、両足、両耳を動かし、さらに小刻みに上下しながら右端へ移動し、2回目以降は仲間を連れて最初の位置まで小刻みに上下しながら戻るというプログラム。
本当はEXEファイルを配布し、皆さんにも体感していただきたかったのですが、生憎、このプログラム自体は先生お手製の教育プログラムを、練習用に改造していったものですので、著作権上EXEファイルをアップすることは出来ません;;

で、内容に移りましょうか。
まず、最初に言って置きますが、
これはWindowsプログラムです。その中の、Win32GDIというものを利用しています。

んで、本題の方ですが・・・。
まず最初にプロトタイプ宣言でDrawUsagiという関数を宣言してあります。
これは、ウサギの描画を担当する関数のことです。
次に、Gmainっていう関数があります。これが制御部分です。
ここで、定数宣言と変数宣言がしてあります。

HDC hDC, mDC;
は、デバイスコンテキストを宣言してあります。
デバイスコンテキストについては後ほど触れます。
HBITMAP Bitmap ;
はビットマップハンドルを宣言してあります。
これも後ほど触れます。

まず最初に、ウィンドウの大きさを調べるために、
GetClientRect( Client , &Rect );
という記述があります。
これは、クライアント領域、つまりユーザーが開いたウィンドウのサイズを聞いているわけです。
これを指定することにより、ウィンドウサイズを変えても表示がおかしくなることはありません。
その下は・・・なんだっけ(ぁ
まぁ、コメントに書いてありますがウィンドウの横幅と縦幅の調整でしょうかね。

次に、デバイスコンテキストを作成するために、
hDC   = GetDC( Client );
mDC   = CreateCompatibleDC( hDC );
と言う記述があります。
デバイスコンテキストとは、ウィンドウに図形を描画する絵描きさんのことです。
こいつに、小道具を渡し、描画してもらうのです。
今日はダブルバッファというものもやったので、ここではメモリデバイスコンテキストも作成してあります。
メモリデバイスコンテキストとは、メモリ上に存在する絵描きさんのことです。
こいつは、バックでデバイスコンテキストと同じ働きをします。
詳しい説明は後ほど。

そして、メモリDCが描画するのに必要な仮想ウィンドウを作成するために
Bitmap = CreateCompatibleBitmap( hDC , Width , Height ) ;
Bitmap0 = SelectObject( mDC , Bitmap );
と言う記述があります。
これは、メモリデバイスコンテキストにデバイスコンテキストが取得したウィンドウ情報を仮想ウィンドウとして渡す命令です。

ここで、メモリデバイスコンテキストについて説明。
メモリデバイスコンテキストとは、デバイスコンテキストのクローンのようなものだと思ってください。
なぜ、クローンを作るのか。それは、デバイスコンテキストのみで描画すると、描画する際にちらつきというものが発生します。
それを防ぐために、裏で出力する図形等を描画します。それがメモリデバイスコンテキストです。
裏で作業すれば、描画する様が出力されずにすみますよね。
そんで、メモリデバイスコンテキストが描画を行う仮想ウィンドウ領域を、ビットマップと言います。

しかし、メモリデバイスコンテキストにはウィンドウにビットマップで描画したものを出力する権限は無いんです。
なぜかというと、ウィンドウの領域を知っているのは、デバイスコンテキストであるから。
メモリデバイスコンテキストが描画した図形等を出力するにはデバイスコンテキストと力を合わせて出力する必要があります。
その出力が、BitBlt(ビットブリット)というものです。
これは、高速に図形等をウィンドウに出力する命令です。
ちなみに、この工程を、ダブルバッファと言います。
これを利用すると、ちらつきをなくすことが出来るのです。
先に進みましょうか。

Count = 4;
は、描画する回数を指定しています。
そして、while( Count > 0)で、Countが0になるまで
}
sy = Height - 400 ;
for ( sx = 0 ; sx < Width - 100 ; sx += 3 )
~中略~
 BitBlt( hDC, 0, 0, Width, Height, mDC, 0, 0, SRCCOPY );
   for( Timer = 0 ; Timer < 3500000 ; Timer ++ );
  }
Count -- ;
}
を繰り返すようにしています。
PatBltについては、コメント参照。
ダウンカウンタにしているのは、カウントを増やすよりも減らしていった方がやりやすいからです。
Vrandは、乱数値を格納する変数です。

Vrand = random( 40 );
DrawUsagi( mDC,  sx, sy + Vrand );
これがウサギを上下に動かす命令文。
ちなみに、C言語はフリーフォーマット、つまり記述方法に縛りがないことから、このように小さなプログラムであれば、一行にまとめて書くことが出来ます。
ifでもそうですif(){ }と言う風に書くことが出来ます。
if( Count < 4){ Vrand = random( 40 ); DrawUsagi( mDC,  sx + 100, sy + Vrand ); }
これは、Countが4より小さければウサギをもう一匹右に100ピクセルずらし、乱数を振って上下に動かせと言いう命令。
以下のif文も同じような意味です。
BitBlt( hDC, 0, 0, Width, Height, mDC, 0, 0, SRCCOPY );
ここで、ウィンドウにウサギを出力。SRCCOPYとは、ソースコピーのこと。説明は割愛します。
遅延タイマーについても割愛。

SelectObject( mDC , Bitmap0 ); DeleteObject( Bitmap );
DeleteDC( mDC ); ReleaseDC( Client , hDC );
処理を終了するときは、このように、ビットマップとデバイスコンテキストを消去してあげる必要があります。
メモリデバイスコンテキストはDeleteと書いてありますが、デバイスコンテキストにはReleaseと書いてあります。
これは、リクタングル構造体と言うもので取得した情報を開放してやると言う意味。
つまり、キャッチ アンド リリースと同じことです。
GetClientRect( Client , &Rect );
これですね。ここで得た情報を開放してやるのです。
ゲットしたものは、返却するというのが基本になってます。
ここまでが制御部分。
うへぇ、制御部分の説明だけでこんなに長くなってしまったorz

んで、DrawUsagiについて、ちょこっとだけ解説。
この関数に書いては、ペンとブラシで、ウサギを書いているものだと解釈してください。
Vrand = 8 - random( 20 );
は、縦の乱数で、
Ellipse( hDC , x +  70 , y + 130 + Vrand , x + 120 , y + 145 + Vrand );
で、縦方向に乱数分動かせという命令。

Hrandは横方向のことです。RgtEar、LftEarは右耳と左耳。
動作は上記と同じような動作です。
赤いブラシで描く部分のところでも、RgtEar、LftEarが使われていますが、
RgtEar = 8 - random( 17 );
のような記述がありません。
これは、この記述をしてしまうと、乱数振りなおすと言う意味になってしまい、記述すると図形がぶち壊しになってしまう現象が起こってしまうから。
それを防ぐために、乱数を一回振ったら、振りなおさないようにしてます。

ふぅ・・・すげぇながくなってしまった(^^;
説明下手くそ&いい加減でごめんなさい;;
そして、こんなに長い文を最後まで目を通してくれてありがとう御座います。
書いてたら0時を回ってしまったorz
ま、プログラミングになれている方は、理解できるかと思います。
そんなわけで、長くなりましたがこの辺で失礼しまする。

スポンサードリンク
Pocket
LINEで送る

Comments are closed.