連載:放課後VB教室

第4回 図形の描画とSP1と「ゆるキャラ」メーカー

羽山 博
2008/10/17
Page1 Page2 Page3

 私立関崇高校の大福研究会というナゾのサークルに所属する「サブロー」とクラスメイトの「ラスクちゃん」は、ひょんなことからVisual Basicのプログラミングを教えてもらうことになった。先生はサブローの先輩で、大学の先生でもある「ネスト先生」。前回はデータ型の変換と遅延バインディングについて学んだ。さてさて今回は……。

プロローグ 〜 いざ「あんこ選手権」へ!?

おっ、2人とも遅れずに来たね。えーと、のぞみ13号、8時30分出発。これだ。いざ大阪へ向けて出発!

ネスト先生、「あんこ選手権」は明日なのに、なんでこんなに早くから行くんですか。しかも、観戦だけで、チームとして参加するわけでもないんでしょう。

選手権の前に寄っておきたいところがあるからね。喜八洲の「酒まんじゅう」に、復活した池田名物「ことまん」、それから法善寺の「夫婦善哉」も楽しみだし。大福研究会の使命として、あんこの平和を守ることも重要だからね。

私も楽しみ〜。本場の商売が学べるといいな。大阪弁練習しとかなくちゃ。あ、ちゃうちゃう。練習しとかなあかんなー、やった。そやけど、大阪までの3時間ひまやし、プログラミング教えてぇな、ネストはん。

はいはい。じゃあ、今日は楽しくお絵描きをしよう。お絵描きといっても、ただのお遊びじゃない。仕事で使うプログラムでも、グラフを描いたり、チャートを作成したりするのに役立つわけだから、実用的にも大切な知識だ。でもやっぱり楽しい方がいいから、面白い絵にしよう。何か描きたいものはあるかな?

じゃあ、へんな顔。

へ、へんな顔って……。Visual Basicだと、直線や円、円弧、四角形で描けるものだけだから、顔なんてうまく描けないんじゃないですか。

そこが素人の浅はかさだな。写真みたいな絵がすべてじゃない。単純な図形でも、ちょっとした描き方の工夫で実物以上にリアリティが出る。それに、意外な落とし穴もあって、Visual Basicの仕組みもよく分かるから勉強になるぞ。席に着いたらノート・パソコンを広げて、とにかくやってみよう。

図形描画のメソッドを利用する

初めてだから、まずはできるだけ単純なものにしよう。輪郭と目は円で、目玉は塗りつぶした円で描こう。口は円弧でいいかな。サブローくん、図形を描くにはどうしたらいい?

またボクを陥れようとしてますね。さすがのボクでも、LINE文とかCIRCLE文を使うなんていいませんよ。Visual Basic 2008なら、LINE文の代わりにGraphicsオブジェクトのDrawLineメソッドを使い、CIRCLE文の代わりにDrawEllipseメソッドを使います。塗りつぶされた円ならFillEllipseメソッド。ちゃーんと勉強してますよ。

そうだ。Visual Basic 6まではLINE文やCIRCLE文を使っていたが、Visual Basic 2008ではGraphicsオブジェクトのメソッドを使う。Graphicsオブジェクトは……。

おっと、皆までいわないでください。ちゃんとできますから。チョチョイのチョイですよ。ほらね、こんな感じでどうですか。[描画(D)]ボタンをクリックしたら顔が表示されるようにしました。


図1 顔を描画するプログラム
  [描画(D)]ボタンをクリックすれば、顔が表示される。

ほほぅ。サブローくんにしては表情のある顔が描けたじゃないか。コードはどうなってる?

「にしては」は余計ですよ。描画部分のコードはこんな感じです。Graphicsオブジェクトを作成するにはCreateGraphicsメソッドを使います。MeをbtnDrawに書き換えると、ボタンの上に顔を描くこともできますよ。

Private Sub DrawFace(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click

  Dim g As Graphics

  g = Me.CreateGraphics

  g.DrawEllipse(Pens.Black, 100, 100, 50, 50)    ' 輪郭
  g.DrawEllipse(Pens.Black, 105, 125, 10, 10)    ' 左目
  g.DrawEllipse(Pens.Black, 120, 128, 10, 10)    ' 右目
  g.FillEllipse(Brushes.Black, 105, 126, 7, 8)   ' 左目玉
  g.FillEllipse(Brushes.Black, 120, 129, 7, 8)   ' 右目玉
  g.DrawArc(Pens.Black, 110, 138, 8, 5, 10, 190) ' 口

End Sub
サブローが作成した描画プログラム
  Graphicsオブジェクトを参照する変数を宣言。
  Graphicsオブジェクトを作成する。この場合、MeはForm1を意味するのでフォームのGraphicsオブジェクトが作成される。

 DrawEllipseメソッドはだ円を描くメソッドで、引数には、線の色、左上のX座標、Y座標、幅、高さを指定します(図2左)。線の色はPensクラスのメンバを選択すれば、簡単に指定できます。幅と高さを同じにすれば、円になりますね。

 FillEllipseメソッドは塗りつぶされただ円を描くメソッドなので、線の色の代わりに塗りつぶしに使うブラシの色を指定します(図2右)。こちらはBrushesクラスのメンバを選択して色が指定できます。


図2 円(だ円)を描く方法
DrawEllipseメソッドで指定する引数(左)とFillEllipseメソッドで指定する引数(右)の違いは、線の色と塗りつぶしの色だけ。

 DrawArcは円弧を描くメソッドで、引数は線の色、左上のX座標、Y座標、幅、高さ、開始角、終了角です(図3)。DrawEllipseメソッドで描かれるだ円の一部分を描くって感じですね。


図3 円弧を描く方法
角度は時計回りで指定することに注意。角度以外の引数はDrawEllipseメソッドと同じ方法で指定する。

 ここでは、線を描画するDrawLineメソッドや四角形を描画するDrawRectangleメソッドは使ってませんけど、DrawLineメソッドにはペンの色と、始点のX座標、Y座標、終点のX座標、Y座標が指定できます。DrawRectangleメソッドにはペンの色と、始点のX座標、Y座標、幅、高さが指定できますね。

自動的に再描画させるには

あはは、面白い。思ったより簡単に描けるんだね。あれ、でも、ウィンドウを切り替えたりすると、顔が消えちゃうよ。ほら、ウィンドウに隠された部分が消えちゃった。もう一度[描画(D)]ボタンをクリックすれば描画し直されるけど……。


図4 ウィンドウを切り替えると画像が消える
ほかのウィンドウに隠されると、ウィンドウを再表示しても隠された部分の図形が消えてしまう。最小化した後、元のサイズに戻しても図形が消えてしまう。

あれぇ、おかしいな。コードに間違いはないはずなんだけど。そ、そうだ、これはきっとバグだ。ディスプレイ・ドライバがおかしいんだよ、きっと。ラスクのパソコン貸してみて……あれぇ、やっぱり同じか。

すぐに他人のせいにするのはよくないぞ。確かに間違ってはいないが、このコードだと再描画はされないな。Windowsアプリケーションの場合「線を引きました。円を描きました。はい、めでたしめでたし」とはいかないんだ。ウィンドウのサイズが変わったりすることもあるし、背後に隠されてしまうこともある。いろんなことが起こる過酷な環境にいるわけだ。だとすると、必要に応じて再描画しないといけない。

じゃあ、ウィンドウのサイズが変わったときや、ウィンドウが前面に表示されたときに、描画を再実行するコードを書いておけばいいんじゃないですか? でも、いろんな場合があるだろうから、どのイベント・ハンドラにコードを書けばいいのかよく分からないですね……。

そう、個々のイベントにいちいち対処するのは大変だ。だが、再描画に適したPaintというイベントがちゃんと用意されているからそれを使えばいい。フォームやコントロールが再描画される必要があるときには、このイベントが発生する。だから、Paintイベント・ハンドラに描画のためのコードを書いておけば、必要なときにはいつでも自動的に再描画されるというわけだ。

 フォームのPaintイベント・ハンドラにさっきのコードを移動して、少し書き換えよう。

Private Sub DrawFace(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

  Dim g As Graphics = e.Graphics

  g.DrawEllipse(Pens.Black, 100, 100, 50, 50)
  g.DrawEllipse(Pens.Black, 105, 125, 10, 10)
  g.DrawEllipse(Pens.Black, 120, 128, 10, 10)
  g.FillEllipse(Brushes.Black, 105, 126, 7, 8)
  g.FillEllipse(Brushes.Black, 120, 129, 7, 8)
  g.DrawArc(Pens.Black, 110, 138, 8, 5, 10, 190)

End Sub
自動的に再描画されるプログラム
このPaintイベント・ハンドラは、ウィンドウのサイズが変わったり、重なり方が変わったりして再描画が必要になると自動的に呼び出される。書き換えたのは の部分だけ。
  Graphicsオブジェクトを参照する変数を宣言し、参照を代入する。

なるほど。自分で描くんじゃなくて、必要が生じたら再描画してもらう、というように、考え方を360度変えなくちゃならないってことだ。

360度変えたら、元に戻ってしまいまんがな。180度やろー。……って、ツッコむとこだよね。マジでボケたわけじゃないよね。で、今度はCreateGraphicsメソッドはいらないの?

も、もちろんだよ。わざとボケただけだよ。ははは……。

さあ、どうだろうね。サブローくんのことだからね。ま、それはいいとして、Graphicsオブジェクトのことだが、これはイベント・ハンドラのeという名前の第2パラメータを使って参照することができる。だからCreateGraphicsメソッドを使う必要はない。なかなかうまくできてるね。

 

 INDEX
  放課後VB教室
  第4回 図形の描画とSP1と「ゆるキャラ」メーカー
  1.図形描画のメソッドを利用する
    2.ボタンをクリックしたときに図形を動かすには
    3.もっと簡単に図形を描画するには 〜 SP1の新しいコントロール
 
インデックス・ページヘ  「放課後VB教室」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH