連載:放課後VB教室

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

羽山 博
2008/10/17
Page1 Page2 Page3

ボタンをクリックしたときに図形を動かすには

へへっ、いいこと考えたっ。このプログラムをうまく使って「ゆるキャラ」作れないかなーって。

「ゆるキャラ」って、「ひこにゃん」とか「いーねくん」みたいなアレ? そんなの作ってどうすんの?

もちろん、一獲千金なのだっ! 目の位置とかを変えて表情を変化させれば新しい「ゆるキャラ」がきっとできるはず。……あ、あれっ? だとすると、自動的に再描画させるんじゃなくて、ボタンをクリックしたときに再描画しなくちゃだ。例えば、ボタンをクリックしたら目玉を右に動かすとか……。

そうだね。そういう場合もあるはずだ。だが、そのときもやはり自分で描くのではなく、イベント・ハンドラに再描画してもらうようにする方がプログラムの構造がシンプルになる。ボタンをクリックしたときに描画のメソッドを呼び出すという方法ではなくて、描画のための適切な値を設定しておいて、Refreshメソッドを呼び出すんだ。Refreshメソッドはコントロールやその子コントロールを再描画するメソッドだ。

 単に再描画するだけなら、ボタンのClickイベント・ハンドラに次の1行を書けばいい。


Me.Refresh()

 ボタンをクリックするたびに表情を変えたいなら、描画の位置やサイズを変数にしておけばいいね。つまり、ボタンをクリックしたら、それらの変数の値を変更してから、Refreshメソッドを呼び出せばいい。えーと、そうだな、RadioButtonコントロールを4つ、移動のためのButtonコントロールを4つ配置して、と。こんなプログラムが作れるね。


図5 顔のパーツを動かすプログラム
  左目、右目、左目玉、右目玉のいずれかを選択する。
  移動させたい方向のボタンをクリックする。

 口の形や目の色も変えられるといいんだけど、取りあえずは目と目玉だけが動かせるようにしよう。コードは長くなりそうだから、少しずつ書いていこうか。まずは、変数の宣言と初期値の設定だね。XとYをまとめて取り扱いたいから構造体を使おう。顔のパーツは配列で表すことにする。こんな感じかな。

Private Structure EyePosition
  Public X As Integer
  Public Y As Integer
End Structure

Private MyPosition(3) As EyePosition
' 0:左目、1:右目、2:左目玉、3:右目玉

Private Sub InitProc(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  ' 初期値の設定
  MyPosition(0).X = 105 : MyPosition(0).Y = 125
  MyPosition(1).X = 120 : MyPosition(1).Y = 128
  MyPosition(2).X = 105 : MyPosition(2).Y = 126
  MyPosition(3).X = 120 : MyPosition(3).Y = 129
End Sub
目や目玉の位置を変数にして初期値を設定する
  位置を表す構造体を作る。
  構造体の配列を宣言する。
  フォームがロードされたときに実行されるイベント・ハンドラ、顔のそれぞれのパーツの初期値を設定している。

うわ。急に難しくなったぁ。構造体っていったい??? 配列はプログラミングの授業で習ったから何となく分かるんだけどなぁ。

変数を個別に宣言してもいいんだけど、関連のあるものはまとめて宣言しておくとコードが書きやすくなるからね。そんなときに便利なのが構造体なんだ。構造体は複数の変数をまとめて取り扱いたいときに使う。上の のコードを図にすればこんな感じかな(図6)。これは実際の変数の宣言ではなく、いわば新しいデータ型を作っているようなものだね。


図6 EyePosition構造体のイメージ
Xという変数とYという変数をまとめて、EyePositionという名前の新しいデータ型であるかのように取り扱える。

 上記リストの では、このEyePositionというデータ型の配列を宣言している。配列のインデックスの最大値は3だから、以下のようなイメージで変数が作成される。Visual Basicで配列を宣言するときには、配列の要素数を指定するのではなく、インデックスの最大値を指定することに注意が必要だね。


図7 顔のパーツの位置を記憶するための配列
構造体の要素(メンバ)を指定するには、「構造体名.メンバ名」と書く。例えば、「MyPosition(1).Y」であれば、右目のY位置ということになる。

 フォームのLoadイベント・ハンドラでは、これらの変数に初期値を設定して、最初の顔の状態を決めている。それが のコード。簡単だね。

図にすると分かりやすいですね。じゃあ、再描画のためのコードはボクが書きます。これまでリテラルで指定していた引数の代わりに、この構造体のメンバを書けばいいだけですね。カンタンカンタン。

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, _
                    MyPosition(0).X, MyPosition(0).Y, 10, 10)
  g.DrawEllipse(Pens.Black, MyPosition(1).X, _
                    MyPosition(1).Y, 10, 10)
  g.FillEllipse(Brushes.Black, _
                    MyPosition(2).X, MyPosition(2).Y, 7, 8)
  g.FillEllipse(Brushes.Black, _
                    MyPosition(3).X, MyPosition(3).Y, 7, 8)
  g.DrawArc(Pens.Black, 110, 138, 8, 5, 10, 190)

End Sub
描画のためのコード
目と目玉の位置に関する引数をリテラルから構造体のメンバに書き直しただけ。構造体のメンバの値を変更すれば、顔の表情も変わる。

分かった! ボタンをクリックしたら、MyPositionのメンバの値を変えて、Refreshメソッドを呼び出すんだ。でも、コードを書くのは、あたしにはちょっと難しいかも……。

大丈夫だよ。どのRadioButtonコントロールが選択されているかを調べて、配列のインデックスを決めればいいよ。例えば、[左目(1)]ラジオボタンのコントロール名がrbLeftEyeだとするね。だとすれば、rbLeftEyeのCheckedプロパティがTrueのときに、MyPositionのインデックスを0にすればいい。上下左右に移動させるには、XとYの値を変えればいいね。

Private Sub MoveEye(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUp.Click, btnRight.Click, btnLeft.Click, btnDown.Click

  Dim idx As Integer

  ' 顔のパーツを選ぶ
  If rbLeftEye.Checked Then
    idx = 0
  ElseIf rbRightEye.Checked Then
    idx = 1
  ElseIf rbLeftEyeBall.Checked Then
    idx = 2
  Else
    idx = 3
  End If

  ' クリックされたボタンによって位置を変える
  If sender Is btnUp Then
    MyPosition(idx).Y -= 1
  ElseIf sender Is btnDown Then
    MyPosition(idx).Y += 1
  ElseIf sender Is btnLeft Then
    MyPosition(idx).X -= 1
  ElseIf sender Is btnRight Then
    MyPosition(idx).X += 1
  End If

  Me.Refresh()

End Sub
ButtonコントロールのClickイベント・ハンドラ
前半ではどのパーツの位置を変更するかを決めて、後半ではそのパーツの新しい位置を計算している。最後にRefreshメソッドを呼び出してフォームを再描画する。

オーケー。2人ともよくできました。ちょっと強引な感じのコードだけど、これでうまくいくね。


 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