Visual Basic 初級講座 |
---|
Visual Basic 中学校 > 初級講座 >
この記事が対象とする製品・バージョン (バージョンの確認方法)
VBに慣れる目的で、線を書いたり四角形や丸を書いたり、見た目で楽しいグラフィックのプログラムをとりあげます。ごく初歩的なものですがいわゆるCG=コンピューターグラフィックスと呼ばれるものです。
注意!2014年10月21日に全面改訂しました。改訂前の記事はこちらです。
概要
|
この回で説明する主な内容を動画で見ることができます。 動画を見る ・時間 8分50秒 ・別ウィンドウで開きます。 ・リンク先はYoutube ・音声なし ・動画で使用しているのはVisual Basic 2013(Visual Studio Express 2013 for Windows Desktop) 本文ではすべての内容を説明しています。動画は本文の一部を映像にしたものです。動画が見られない場合は気にせず本文だけをよく読んでください。 |
まずは、シンプルにフォームに線を一本描くプログラムを紹介します。
次の通りにプログラムしてください。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.DrawLine(Pens.Red, 50, 60, 100, 150) End Sub End Class |
■リスト1
プログラムを開始するとフォームに斜めの赤い線が表示されます。
■画像1:赤い線
このプログラムはシンプルですが奥が深く本当にちゃんと理解するのは少し大変です。
このプログラムのポイントは次の4点です。今回はこれらを掘り下げて説明し、VBのプログラムで絵が描けるようになることを目指します。
絵を描くタイミングは、Paintイベント(読み方:Paint = ペイント)の発生時。
絵を描くには、e.Graphics (読み方:e = イー、Graphics = グラフィックス)を使う。
線などの図形を描くには、DrawLineメソッド(読み方:DrawLine = ドロゥライン)などの描画用メソッドを使う。
書く線の種類を指定するには ペン(Pens.Red)(読み方:Pens = ペンズ、Red=レッド)を使う。
線1本描くためにいろいろと知る必要があるのだなとげんなりしてしまうかもしれませんね。
ただ、今回の本当の目的は前回と一緒でVBの雰囲気に慣れてもらうことにあります。この段階ではいろいろなことを覚えきれなかったり理解できなくても気にしないでください。その代り、登場するサンプルはできるだけ実際に入力して動かしてみて慣れる努力をしてみてください。
まず、上記のサンプル(リスト1)がFormのPaintイベント(読み方:Paint = ペイント)を使っていることの確認方法を説明します。
メモ - Paintイベントにプログラムする方法 |
何もない状態からPaintイベントのプログラムを自動生成するには、メソッド名ボックスでPaintイベントを選択するか、プロパティウィンドウでPaintイベントをダブルクリックします。
詳細は 入門講座第4回 イベントを逃すな をご覧ください。
上述のリスト1のようにプログラムがわかっている場合はまるごとコピーして貼り付けてもPaintイベントとして動作します。
プロシージャの名前がForm1_Paintであることからも予想はできますが、ちゃんと確認するには該当箇所にカーソルがあるときにメソッド名ボックスに「Paint」と表示されることからわかります。
■画像2:メソッド名ボックス
また、プログラムの中にある Handles Me.Paint という部分もこれがPaintイベントであることを示しています。
※少し前のバージョンのVBでは Handles MyBase.Paint となっていますが機能は同じです。
実のところForm1_Paintという名前はまったく重要ではなく別の名前に変えても問題ありません。このプログラムがPaintイベント時に実行されるのはすべて Hanles Me.Paint の効果なのです。
Handlesとイベントの関係については別の機会に詳しく説明しますが今はHandlesを目印に何のイベントであるか知ることができるという点を覚えておいてください。
使われているイベントの名前を確認する方法
ただし、高度なプログラムではイベントを複雑に操作する場合があり、これらの方法では確認できない場合もあります。どのような場合にもあてはまる確認方法はありません。
イベントの種類は無数にありますが、すべてのイベントは何かが起こった時に発生します。たとえばClickイベントはクリックされたときに発生し、KesPressイベントはキーボードが押されたときに発生します。
今回使っている Paintイベントは、Windowsによって「描画が必要である」と連絡されたときに発生します。このようなWindowsから送られてくる連絡は「メッセージ」と呼びますので、ここではこの連絡のことを「描画メッセージ」と呼ぶことにします。
Windowsの世界では一度にたくさんのウィンドウが表示でき、最小化されているものや、裏に隠れて表示されていないものなどさまざまな状態があります。
WindowsXPまでは 裏に隠れているウィンドウに対していちいち枠を描いたり背景を塗りつぶしたりする処理を実行するのはCPUやメモリの無駄遣いと判断し、裏に隠れているウィンドウには何も描画していませんでした。
前方のウィンドウが移動するか閉じるなどして裏のウィンドウが本当に表示されるタイミングになってはじめて描画の必要が発生します。Windowsはこのようなタイミングでウィンドウ対し「ウィンドウの内容を描画する必要がありますよ」という連絡、つまり描画メッセージを送ってくるのです。この描画メッセージを受信したときに発生するのがPaintイベントです。
Windowsが描画メッセージを送ってくるタイミングはウィンドウが初めて表示されるときや、前方のウィンドウがどいたとき、ドラッグアンドドロップでウィンドウの上を関係ないものが横切ったときなどさまざまです。実際にどのタイミングでこの連絡が来るかはWindowsのバージョンによっても異なります。 Windows Vista、7、8などの新しいWindowsではこれまでと違い裏に隠れているウィンドウに対しても実際の描画を要求するようになっています。これはウィンドウを次々と切り替えて作業する場合に描画命令の処理が追いつかず一時的にウィンドウが真っ白になってしまうようなことが起こらないようにした方が、ユーザーの使い勝手が良いと判断されたためらしいです。 次のプログラムはPaintイベントが発生すると音を鳴らすのでいつPaintイベントが発生しているかわかります。
■リスト2 |
このPaintイベントの考え方はプログラム初心者にはなかなかなじめずイメージがつかみにくいと思うのでいくつか例をあげます。Windowsのバージョンによって実際の動作は変わりますがPaintイベントの考え方を理解するために簡単に書いています。
特に 1 が初心者の直感と大きくずれているため、ここで勘違いしてしまう人が多いようです。
イベントには追加情報がある場合があり、そのような追加情報は必ずイベントプロシージャの引数 e から受け取ることができるようになっています(※1)。
※1 System.Web.UI.WebControls.CustomValidatorクラスのServerValidateイベントなどごく一部例外があります。
Paintイベントの場合は追加情報として次のものが渡されます。
プロパティ | 読み方 | 意味 | |
---|---|---|---|
ClipRectangle | クリップレクトアングル | 描画が必要な領域。 | |
Graphics | グラフィックス | 描画を担当するオブジェクト。たとえるなら「画家」。 |
■表1
eから追加情報を得たり追加情報を操作するには e の後ろにドットをつけて e. …と書きます。たとえば、次の例はPaintイベントが発生したとのClipRectangleの情報をフォームのタイトルバーに表示します。
メモ - お手軽に情報を表示したいときは ToString が便利 |
ToStringメソッドはすべてのオブジェクトで使用可能で、そのオブジェクトの情報を取得してくれる便利なメソッドです。ToStringメソッドの結果どのような情報が取得できるかはオブジェクトによって異なります。e.ClipRectangle.ToStringの場合は、領域の位置情報が取得できます。
Private Sub
Form1_Paint(sender
As Object, e
As
PaintEventArgs) Handles
Me.Paint Me.Text = e.ClipRectangle.ToString End Sub |
■リスト3
■画像3:ClipRectangle
Windowsからの描画メッセージは常にフォーム全体に対して行われるわけではなくフォームの一部分に対して行われこともあります。どの部分が描画メッセージの対象かはClipRectangleプロパティでわかります。たとえば、マウスを使ってフォームの幅を広げた時は広がって新たに表れた部分にだけ描画が必要です。
とは言え、ClipRectangleで命令された場所に描画するか、そのほかの場所に描画するかはプログラマーの自由です。多くの場合Windowsはフォーム全体に対して描画メッセージを出すので、特に厳しい性能が要求される場合を除きClipRectangleの内容は無視してよいです。
今回の説明でもClipRectangleはもう登場しません。
重要なのはもう1つのGraphicsプロパティの方です。GraphicsプロパティはVBのグラフィック機能の玄関的な存在であり、線を描け、円を描けなどの具体的な命令を受け付けてくれます。Graphicsプロパティの型はGraphics型(プロパティの名前と型の名前が同じ)なので、どのような命令を受け付けてくれるかの詳細はヘルプでGraphicsクラスを調べればわかります。
最初に挙げた例はDrawLineメソッドを使って線を描画していました。
DrawLineなどGraphicsクラスが持っている主な描画用のメソッドには次のようなものがあります。
プロパティ | 読み方 | 機能 | |
---|---|---|---|
DrawArc | ドロゥアーク | 円弧を描画する。 | |
DrawCurve | ドロゥカーブ | 曲線を描画する。 | |
DrawEllipse | ドロゥイリプス | 円を描画する。 | |
DrawImage | ドロゥイメージ | 画像の内容を描画する。 | |
DrawLine | ドロゥライン | 線を描画する。 | |
DrawPie | ドロゥパイ | 扇形を描画する。 | |
DrawRectangle | ドロゥレクトアングル | 四角形を描画する。 | |
DrawString | ドロゥストリング | 文字を描画する。 | |
FillEllipse | フィルイリプス | 塗りつぶされた円を描画する。 | |
FillPie | フィルパイ | 塗りつぶされた扇形を描画する。 | |
FillRectangle | フィルレクトアングル | 塗りつぶされた四角形を描画する。 |
■表2
この表は円や四角形などのよくある図形を簡単に描画するメソッドを中心にまとめています。一言では表せないような複雑な図形を描画したり、グラフィックに対する拡大・縮小や高度なエフェクトなどの変換処理もGraphicsクラスの機能で行うことができますがこのような高度な使用方法は今回は扱いません。
描画用メソッドの使い方はどれも同じようになっているので1つ理解できれば他のメソッドも使用できます。ここではDrawLineを例に説明します。
DrawLineメソッドは5つの引数を取り、順にペン、始点のX座標、始点のY座標、終点のX座標、終点のY座標を表しています。
ペンとは、現実世界のペンと同じ発想で用意されているオブジェクトで、ペンを変えることで線の色や太さなどを変更することができます。ペンの詳細は後で説明しますが、さしあたり簡単に使うにはPens.Redが赤いペン、Pens.Blueは青いペンと覚えておいてください。
座標については、中学校の関数の授業で習うものと考え方は同じですが、原点が左上であることと、Y軸は下がプラスで上がマイナスであるという2点が異なっています。
座標についてよくわからない方は算数・数学講座第3回「座標」を見てください。
■画像4:座標
中学校の数学 | Visual Basic | |
---|---|---|
原点の位置 | 中央 | フォームの左上 |
Y軸の方向 | 上がプラス | 下がプラス |
■表3:中学校で習う座標系とVBの座標系の違うところ
見やすくするために最初に紹介したプログラムをもう一度載せます。DrawLineメソッドの5つの引数と上の説明を見比べてみるとDrawLineメソッドの使い方がわかるでしょう。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.DrawLine(Pens.Red, 50, 60, 100, 150) End Sub End Class |
■リスト4
これであなたは好きな位置に好きな色の線を描けるプログラマーになったはずです。
それでは、四角形を描いたり円を描いたりする他の描画メソッドも使ってみましょう。
四角形を描くDrawRectangleメソッドは次のように使います。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.DrawRectangle(Pens.Red, 50, 60, 100, 150) End Sub End Class |
■リスト5
結果は次のようになります。
■画像5:DrawRectangle
DrawLineメソッドとまったく同じ書き方でいいことがわかります。DrawRectangleメソッドの場合は左上の点の座標と、右下の点の座標を引数に指定していることになります。
円を描くDraeEllipseメソッドはどうでしょうか。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.DrawEllipse(Pens.Red, 50, 60, 100, 150) End Sub End Class |
■リスト6
結果は次のようになります。
■画像6:DrawEllipse
これもDrawLineメソッドとまったく同じです。座標は円に外接する四角形の左上の点と右下の点を表します。
「外接する四角形」の意味がよくわからない人は、この円の外側にぴったりくっついている四角形をイメージしてください。参考に外接四角形を黒で描画する例も紹介しておきます。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint '外接四角形を黒で描画 e.Graphics.DrawRectangle(Pens.Black, 50, 60, 100, 150) '円を赤で描画 e.Graphics.DrawEllipse(Pens.Red, 50, 60, 100, 150) End Sub End Class |
■リスト7
■画像7:外接四角形とDrawEllipse。外接四角形を考えるとDrawEllipseで指定する座標の意味が理解しやすくなります。
扇形、円弧は角度の指定が必要です。使い方はDrawLineメソッドとほぼ同じなので追加で開始角度と中心角の大きさを「度」で指定します。「度」とは1周を360度と定義する角度の単位です。高校で習うラジアンとは異なります。
以下にDrawPieメソッドを使って扇形を描画する例を示します。わかりやすく外接四角形も黒で描画しています。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint '外接四角形を黒で描画 e.Graphics.DrawRectangle(Pens.Black, 50, 60, 100, 150) '扇形を赤で描画(45度の角度から90度分の大きさ) e.Graphics.DrawPie(Pens.Red, 50, 60, 100, 150, 45, 90) End Sub End Class |
■リスト8
結果は次のようになります。
■画像8:扇形
ペンの種類を変えると、線の色や太さを変えることができます。また、現実の世界とはちがって点線にするなどのちょっとしたアレンジもペンを変えることで実現します。自分で好みのペンを作ることもできますが、楽をしたい人のためよくあるペンははじめから用意されていて、既に登場したようにPens.Redなどと書くことでVBにあらかじめ用意されている赤いペンをすぐに取り出すこともできます。
他にどのようなペンがあらかじめ用意されているかはPens. と入力して表示される一覧(インテリセンス)を見るとわかります。
■画像9:Pensクラスのインテリセンス
たとえば、ダークグリーン(濃い緑色)のペンで線を描くには次のようします。
e.Graphics.DrawLine(Pens.DarkGreen, 10, 10, 100, 100) |
■リスト9
はじめから用意されているペンでは物足りない場合自分でペンを作る例を次に紹介します。
この例では太さ5、青のペンを作っています。
Dim myPen As
New Pen(Color.Blue, 5) e.Graphics.DrawLine(myPen, 10, 10, 100, 100) |
■リスト10
■画像10:太い線
このプログラムにはまだ説明していないキーワードNewが登場しています。Newは重要でかつ初級プログラマが必ずつまづくポイントでもあります。説明は少し後回しして別の回にすることにします。
ペンを使うと描く図形にいろいろな変化をつけることができます。代表的なものは色、太さ、線の種類の3つです。色と太さについては上の例でわかると思いますので線の種類についてもう少し説明します。
線の種類とは点線と実線などの違いを指し、DashStyleプロパティ(読み方:DashStyle = ダッシュスタイル)で指定することができます。あらかじめ次の種類が用意されています。自分で新しいパターンを作ることもできますがあまり必要はないでしょう。
値 | 読み方 | 意味 |
---|---|---|
Solid | ソリッド | 実線。通常の線です。 |
Dash | ダッシュ | 短い線でとぎれとぎれに描画します。 |
Dot | ドット | 点線。 |
DashDot | ダッシュドット | ダッシュと点と組み合わせです。 |
DashDotDot | ダッシュドットドット | ダッシュと2つの点の組み合わせです。 |
Custom | カスタム | 自分で新しいパターンを作るときに指定します。 |
■表4:DashStyleの一覧
DashStyleプロパティを使って点線で円を描くには次のようにします。
Dim myPen As
New Pen(Color.Blue, 5) myPen.DashStyle = Drawing2D.DashStyle.Dot e.Graphics.DrawEllipse(myPen, 50, 60, 100, 150) |
■リスト11
結果は次のようになります。
■画像11:点線で描いたDrawEllipse
今度はボタンをクリックしたら何か図形を描画するというプログラムを作ってみます。また、今までFormに直接描画していましたが、趣向を変えてPictureBoxを使ってみます。
ボタンをクリックするとClickイベントは発生しますが、Paintイベントは発生しません。だからこのままでは絵は描けません。
そこで、Invalidateメソッドを使ってWindowsから描画メッセージを送ってもらいます。こうすることでClickイベントからPaintイベントを発生させることができます。
イメージとしては次のようになりますが、このプログラムはまだ意味がありません。
フォームにButtonとPictureBoxを貼り付けて次のプログラムを試してください。PictureBoxは大きめに貼り付けてください。
Public
Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click PictureBox1.Invalidate() End Sub Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint e.Graphics.Clear(Color.Black) e.Graphics.FillEllipse(Brushes.Blue, 10, 10, 90, 90) End Sub End Class |
■リスト12
実行するとPictureBoxがまっ黒くなって、左上に青い円を描画します。さきほどのDrawEllipseではなく、FillEllipseを使っているので円は塗りつぶされます。PaintイベントがFormのPaintイベントではなく、PictureBoxのPaintイベントになっている点に注意してください。間違ってFormのPaintイベントにしてしまうとフォーム全体が真っ黒になります。
ボタンをクリックするとInvalidateメソッドの効果でWindowsからPictureBox1に描画メッセージが送られます。そしてまたPaintイベントが発生します。
しかし、何回Paintイベントが発生しても最初の描いたものと同じものを書くだけなので見た目に変化がなく意味がありません。
そこで、描画する座標の一部を変数にしてボタンをクリックするたびに変数の値が変わるようにしてみます。
次のようにしてください。
Public
Class Form1 Private x As Integer = 10 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click x += 2 PictureBox1.Invalidate() End Sub Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint e.Graphics.Clear(Color.Black) e.Graphics.FillEllipse(Brushes.Blue, x, 10, 90, 90) End Sub End Class |
■リスト13
今度はボタンをクリックするたびに青い円が右に移動するように見えます。
このプログラムで重要な点は次の2つです。
少し形が違う他の方法もあります。たとえば、Invalidateメソッドでは描画メッセージの内容をもっと細かく指定する引数を利用することもできます。またInvalidateメソッドではなくRefreshメソッドを使うこともできます。
今回はVBに慣れるための話題としてお絵かきを取り上げているだけでグラフィックスのプログラミングに深入りするつもりはありませんが、参考のために少しだけ補足します。
線や四角や円などの図形を描くのにはDraw…というメソッドを使いましたが、塗りつぶす場合はFill…というメソッドを使います。だいたいの場合、Draw…に対応したFill…というメソッドが存在します。
たとえば、線で囲まれた四角形を描画するのにDrawRectangleメソッドを使用しましが、塗りつぶされた四角形を描画するにはFillRectangleメソッドを使用します。このとき、色はペンではなく、Brush(読み方:ブラシ)と呼ぶオブジェクトで指定します。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.FillRectangle(Brushes.Red, 50, 60, 100, 150) End Sub End Class |
■リスト14
一色での塗りつぶしのようなお手軽な指定はこの例のように簡単にできますが、グラデーションなどちょっと凝った塗りつぶしをするには何行がプログラムする必要があります。詳細は割愛しますがグラデーションの例だけ紹介します。
Public Class
Form1 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint Dim b As New Drawing2D.LinearGradientBrush(New Point(50, 60), New Point(150, 210), Color.Red, Color.Blue) e.Graphics.FillRectangle(b, 50, 60, 100, 150) End Sub End Class |
■リスト15
このプログラムを実行すると下記のようになります。
世の中にはたくさんの描画機能があり、VBでもいろいろなものが使用できます。今回紹介しているのはVBでデフォルトで搭載されていてもっとも簡単に使える GDI+ (読み方:GDI+ = ジーディーアイプラス)というものです。
GDI+は2Dの描画に関してはかなり高機能なのですが、動作が遅いのが欠点で、高性能が要求される描画には向きません。Visual Basic 中学校ではGDI+を使ったシューティングゲームを公開していますので、どの程度の性能か気になる方は見てみてください。
他によく使われるのはWPF(読み方:WPF=ダブリューピ−エフ)とDirectX(読み方:DirectX = ダイレクトエックス)です。WPFは性能は良く、GDI+と比べる回転や拡大・縮小にも強いのですが、ほとんどの場合XAML(読み方:XAML = ザムル)という癖のある言語と一緒に使うことになりかなりとっつきにくいです。ビジュアルな画面作りには良いのですがゲームには向かないように思います。
DirectXは強力で、3Dも得意で性能もよいです。その分プログラムは難しいのですが、ゲームを作ってみたい人はやってみる価値はあります。ただ、プログラムするにはVBのほかにDirectX SDKをインストールする必要がありプログラミング初心者にはちょっとハードルが高いです。そもそもどこから何をダウンロードしてインストールすればよいかわからないかもしれません。