投稿者 魔界の仮面弁士  (社会人) 投稿日時 2020/10/13 11:36:28
> Public g As Graphics
> と記述していたので、

インスタンスの生存期間を考えると、
Graphics をフィールド変数として維持するのは都合が悪いですね。


>『 Public g As Graphics 』 と宣言していたため、
>『 Dim g As Graphics = e.Graphics 』と記述することができなかったのが原因でした。

良し悪しは別として、フィールド変数として g が宣言されていても、
同じ名前でローカル変数 g を多重宣言することはできるはずですよ。

ローカル変数とフィールド変数で名前が競合していた場合、
Me.g と書けばフィールド変数に、g と書けばローカル変数にアクセスできます。



> ① Graphics で表示するのは、非常に簡単ではあるが、私には、文字盤
>   (外周円と目盛と時間を示す数字)は最初に一度だけ書いて、時計の3つの針だけを
>   書き直せばいいのではないか?

固定サイズのフォームなら、時計盤をあらわす .png 画像を用意しておいて、
それをデザイン時に背景画像に割り当てておくのがお手軽です。

ファイルとして事前に用意するかわりに、実行時にメモリ上に画像を動的に構築し、
その画像に対して Graphics クラスを利用して描画するという方法も使えます。


> ④ 『 Dim g As Graphics = e.Graphics 』はペイントイベントで書きますが、

書かなくても使えますけれどね。処理としては
 e.Graphics.DrawLine(…)
と一行で書くか、
 Dim g = e.Graphics
 g.DrawLine(…)
と書くかの違いでしかないわけで。

PictureBox1.CreateGraphics() は「メソッド」なので、
呼び出すたびに、新しい Graphics が生成されてしまいます。
そのため、生成されたインスタンスを変数に受けて、それを使う必要がありました。

一方、e.Graphics は「プロパティ」であり、同じイベント内であれば、
何度呼び出しても、同じ Graphics インタンスを得る事ができます。
そのためこちらは、変数に受けずに使うこともできます。


> ペイントイベントの中にサブルーチンを作って、

Visual Basic が .NET 対応になる前は、GoSub ステートメントというものを通じて
【サブルーチン】を呼び出せるようになっていたのですが、現在の Visual Basic では
【サブルーチン】がサポートされていません。

【サブルーチン】の代わりに、「Sub プロシージャー」や「Function プロシージャー」を使ってみてください。
(文意によってはプロシージャーという言葉の代わりに、メソッドやイベントハンドラという名で呼ばれることもあります)

Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    '自作の Sub プロシージャーを呼び出して、時計の針を描く 
    DrawHands(e.Graphics, Now)

    '実際には、Graphics だけだと領域サイズが不明瞭なので、 
    '描画範囲を示す Rectangle も渡した方が良いかもしれません。 
    '(e.ClipRectangle とか、PictureBox1.ClientRectangle とか) 

End Sub

Private Sub DrawHands(g As Graphics, tm As Date)
    '時分秒を整数で得たい場合 
    Dim intH = tm.Hour
    Dim intM = tm.Minute
    Dim intS = tm.Second

    '時分秒を小数点以下も含めて得たい場合 
    Dim span = tm - tm.Date
    Dim h = span.TotalHours
    Dim m = span.TotalMinutes - (span.Hours * 60)
    Dim s = span.Seconds + (span.Milliseconds / 1000.0F)

    DrawHourHand(g, h)
    DrawMinuteHand(g, m)
    DrawSecondHand(g, s)
End Sub

Private Sub DrawHourHand(g As Graphics, h As Single)
End Sub
Private Sub DrawMinuteHand(g As Graphics, m As Single)
End Sub
Private Sub DrawSecondHand(g As Graphics, s As Single)
End Sub


プロシージャ内で局所的に使いたいルーチンの場合には、
メソッドとして切り出すかわりに、ラムダ式というものを使うこともできます。