お絵かき

GDI

今回はウインドウに、図形を描きます。
GDI(Graphic Device Interface)というのを使います。意訳するとお絵かき道具セットという意味です。
まず、ウインドウを作ってください。今回はコントロールは何も付けません。何も無いウインドウに絵を描きます。
お絵かきをするには画用紙が必要です。GDIではデバイスコンテキスト(以下DC)といいます。
ウインドウのDC(=画用紙)を取得しないことにはお絵かきができません。
GetDC関数を使います。
GetDC(ウインドウハンドル) As HDC

HDCはDCのハンドルです。ウインドウハンドルと同じハンドルです。HDCはデバイスコンテキストの識別番号です。
つぎに、ペンが必要です。CreatePen関数で作ることができます。戻り値はHPEN、つまりペンのハンドル=識別番号です。
塗りつぶしにはブラシが必要です。CriateSolidBrush関数で作ります。戻り値はHBRUSHです。ハンドルです。
色ですがRGB関数を使います。RGB(赤 ,緑 ,青)で、色を指定します。
CreatePen(スタイル , 太さ , 色) As HPEN
CreateSolidBrush(色) As HBRUSH

道具を作ったら、手に持ちます。SelectObject関数です。
SelectObject(HDC , ペンなどのオブジェクト)

重要なことをいいます。使った物は必ず返さなければなりません。
DeleteObject関数でCreate○○で作ったものを、ReleaseDCでGetDCで取得したものをWindowsに返します。
DeleteObject(ハンドル) As Long
ReleaseDC(ウインドウハンドル , デバイスコンテキストハンドル) As Long

次に、描写方法です。
ヘルプにいっぱいあるので、全部説明しません。
SetPixel(hDC ,x座標 ,y座標 , 色)点を打つ
MoveToEx(HDC ,x ,y , 以前の位置)カレントポジション変更
LineTo(HDC , x , y)カレントポジションから線を引く
Rectangle(HDC , x左上 ,y左上 ,x右下 , y右下)四角形を描く+塗りつぶし

とりあえず、以上の関数でお絵かきはできそうです。問題は、いつ描写するかです。
答えをいうと、タイミングを教えてくれるメッセージが届きます。WM_PAINTです。
WM_PAINTはウインドウの再描写が必要だと教えてくれるメッセージです。
つまりWM_PAINTを受け取ったら、描写処理を実行すればいいのです。

実際にやる

今回は、何も無い(コントロール無しの)ウインドウを作ります。
次に、ウインドウ上で右クリック→イベントコード(C)でWM_PAINTのところをクリックして、コーディングボタンを押します。
メッセージ一覧
Sub MainWnd_Paint(hDC As HDC)

End Sub
こんなコードが作られるので、以下のようにします。
Sub MainWnd_Paint(hDC As HDC)
'すいません。GetDCは必要ないです。引数がHDCでした…
Dim hPen As HPEN
Dim hBrush As HBRUSH
'道具を作ります
hPen = CreatePen(PS_SOLID , 1 , RGB(255 , 0 , 0))
hBrush = CreateSolidBrush(RGB(0 , 255 , 0))

'手に持ちます
SelectObject(hDC , hPen)
SelectObject(hDC , hBrush)

'お絵かき
MoveToEx(hDC , 0 ,0 , ByVal NULL)
LineTo(hDC , 300 , 300)

Rectangle(hDC , 100 , 100 , 150 , 150 )

'お返し
DeleteObject(hPen)
DeleteObject(hBrush)

End Sub
実行結果です。
お絵かきの実行結果

上級編

今度は上級編です。
三角関数を使いますので、VCランタイムをインクルードします。
ABの三角関数でもいいのですが、せっかくなのでVCランタイムを使います。
関数の外ならどこでもいいんですが、読みやすくするため、
MainWnd.sbpの8行目(' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。の下)
に#include<vcrt71.sbp>を入れます。
Sub MainWnd_Paint(hDC As HDC)
Dim hPen As HPEN
Dim x As Double , y As Double
Dim t As Double , k As Double
Dim r As Double , a As Long
a = 4
k = 1
t = 0

hPen = CreatePen(PS_SOLID , 1 , RGB(255 , 0 , 0))
SelectObject(hDC , hPen)

r = a *pow(t , k)
MoveToEx(hDC , 100 - r*cos(t) ,100 -  r*sin(t), ByVal NULL)
For t = 0 To 8 * M_PI Step M_PI/30
    r = a *pow(t , k)
    LineTo(hDC , 100 - r*cos(t) ,100 -  r*sin(t))
Next
DeleteObject(hPen)
End Sub
警告がでますね。Double型からLong型に変換するとか言うのが。でも実行は問題なくできます。気持ち悪いかも知れませんが無視してください。
ぐるぐる