文字盤を描く際は三角関数の初歩的な知識が必要となります(右図参照)。この時、用いる単位はラジアン値となります。これは点の円周上での移動距離を元にした単位で、1周、つまり 360度 = 2πラジアン となります。度数をラジアンに直す時は、" 1度 = (π/180) ラジアン " となりますので、「度数 x π / 180」とすれば求められます。逆にラジアンを度数に直す時は、" 1ラジアン = (180/π) 度 " ですので、「ラジアン x 180 / π」となります。(下記 "数字と点の描画" を参照)
描画に当たっては、まずイメージオブジェクトを作成して描画を行い、描画終了後に、フォームの背景に設定しています。この時、まず、三角関数を用いて30度毎の座標を確定し、続いて、再び三角関数で数字や点の描画サイズから調整値を算出して、これを座標から引いています(for文の箇所)。
なお、下記のサンプル中、SmoothingMode ではアンチエイリアス処理を指定しています。これがないと線にギザギザが出てしまいます。さらに、文字にアンチエイリアスをかけるには、TextRenderingHint を利用します。
GDI+の基本的な描画メソッドをあげておきます。
| DrawLine | 直線を描画 | DrawRectangle | 四角形(線)を描画 |
| DrawEllipse | 楕円(線)を描画 | DrawArc | 円弧(線)を描画 |
| DrawPie | 扇形(線)を描画 | FillRectangle | 四角形(塗りつぶし)を描画 |
| FillEllipse | 楕円(塗りつぶし)を描画 | FillPie | 扇形(塗りつぶし)を描画 |
| DrawString | 文字列の描画 | | |
' 背景画像の設定
Private Sub SetBackground()
Dim m As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height) ' イメージ
Dim g As Graphics = Graphics.FromImage(m) ' グラフィックオブジェクト
' 全体の設定
g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias ' 線のアンチエイリアス
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias ' 文字のアンチエイリアス
g.Clear(SystemColors.Control) ' 全体の背景色
' 文字盤の背景の描画
Dim brsBack As New Drawing2D.HatchBrush( _
Drawing.Drawing2D.HatchStyle.HorizontalBrick, Color.Wheat, Color.WhiteSmoke)
g.FillEllipse(brsBack, nCenterX-nRadius, nCenterY-nRadius, nRadius*2, nRadius*2)
brsBack.Dispose()
'外周の円の描画
Dim penRing As New Pen(Color.Peru, 3)
penRing.Alignment = Drawing.Drawing2D.PenAlignment.Outset ' 円周の外側に描画
g.DrawEllipse(penRing, nCenterX-nRadius, nCenterY-nRadius, nRadius*2, nRadius*2)
penRing.Dispose()
' 時を表す数字と点の描画
Dim oFontFamily As New FontFamily("Times") ' 数字部分のフォントファミリー
Dim oFont As New Font(oFontFamily, 24, FontStyle.Bold, GraphicsUnit.Pixel) ' フォント
Dim fDescent As Single = CSng(oFont.Size _
* oFontFamily.GetCellDescent(FontStyle.Bold) _
/ oFontFamily.GetEmHeight(FontStyle.Bold)) ' フォントのディセント部分の高さ
Dim fDotDiam As Single = nRadius / 10 ' 時間の点の直径
Dim i As Integer
For i = 1 To 12
Dim fRad As Double = (90 - i * 30) / 180 * fPi ' ラジアン値(30度毎)
Dim X As Single = nCenterX + CSng(Math.Cos(fRad) * nRadius) ' X座標
Dim Y As Single = nCenterY - CSng(Math.Sin(fRad) * nRadius) ' Y座標
fRad = (180 - i * 30) / 180 * fPi ' ラジアン値(調整分)
If i Mod 3 = 0 Then
' 3, 6, 9, 12時は数字を描画
Dim szNum As SizeF = g.MeasureString(i.ToString, oFont) ' 描画サイズ
X -= szNum.Width * CSng((Math.Sin(fRad) + 1) / 2)
Y -= (szNum.Height - fDescent) * CSng((Math.Cos(fRad) + 1) / 2)
g.DrawString(i.ToString, oFont, Brushes.Navy, X, Y)
Else
' 3, 6, 9, 12時以外は点を描画
X -= fDotDiam * CSng((Math.Sin(fRad) + 1) / 2)
Y -= fDotDiam * CSng((Math.Cos(fRad) + 1) / 2)
g.FillEllipse(Brushes.RoyalBlue, X, Y, fDotDiam, fDotDiam)
End If
Next
oFont.Dispose()
oFontFamily.Dispose()
Me.BackgroundImage = m ' 描画したイメージを背景に設定
g.Dispose() ' リソースの解放
End Sub
上記中、MesureString は、文字を描画した時のサイズを取得します。また、数字の描画で fDescent は、数字では使われないフォントの下部(g や j などの文字で下にはみ出す部分)の高さで、12時位置以外の描画では、これが下の余白となってしまうので、計算して取り除いています。この時、使われている単位はデザイン単位の em となりますので、割合を利用して適当な単位に変換する必要があります。 なお、HatchStyle の模様については、本ページ末のサンプルも参考にしてください。また、色の名称に関しては 「カラーキーワード」(名前付きカラー) のページも参考にしてください。 Color.FromArgb を使用するとより細かな色の設定ができます。 ちなみに、上記のサンプルで、点の代わりにすべて数字を描画することも可能です(右図)。また、数字や点の位置を特定する方法は一通りではありませんので、上記の式にこだわる必要はありません。もっとすっきりと算出できるかもしれません。
|

|