TabPageに線を描画する方法について

タグの編集
投稿者 hige3  (社会人) 投稿日時 2025/5/22 07:13:57
Visual Studio Community 2022  使用の初心者です。
Formに TabControl で TabPage を作成します。
そのTabPage に線を描画する方法をお知らせ下さい。
ToolBox に Line がないんですね。
ご教授、宜しくお願い致します。  
投稿者 とくま  (社会人) 投稿日時 2025/5/22 09:15:36
TabPage にも Paint イベントは実装されているようです。
前回の質問と何が違うのですか?
https://keijiban.umayadia.com/ThreadDetail.aspx?ThreadId=31013
投稿者 hige3  (社会人) 投稿日時 2025/5/24 06:52:09
とくま様

前回、フォームに描画する方法として下記を教えていただきました。
 Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    e.Graphics.DrawLine(New Pen(Color.Red, 2), 10, 120, 50, 220)
End Sub

今回は Form1 上に作成した TabPage に描画したいんですが、TabPageの指定方法が分からないんです。

因みに下記では不可でした。
    Private Sub TabPage1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
        e.Graphics.DrawLine(New Pen(Color.Gray, 1), 90, 170, 90, 210)
    End Sub
御教授よろしくお願いいたします。
投稿者 KOZ  (社会人) 投稿日時 2025/5/24 07:04:25
VB6 と違い、メソッド名とコントロールのイベントは結びついていません。
Handles の後に続くのがコントロールのイベントです。
つまり、Handles MyBase.Paint ではフォームのイベントになってしまいます。

イベントハンドラーの追加は
第4回 イベントを逃すな
http://rucio.o.oo7.jp/VBNyumon/BEGIN4.htm
「3-2.プロパティウィンドウによるイベントハンドラーの生成」
を読んでください。

投稿者 hige3  (社会人) 投稿日時 2025/5/24 18:17:39
KOZ様

起動時の設定は load しか知りませんでしたが、下記でShown を知りました。
>http://rucio.o.oo7.jp/VBNyumon/BEGIN4.htm

Load ではうまくいかなかったのが、Shown でうまく描画されました。

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        SenKaki_1()
    End Sub

    Private Sub SenKaki_1()
        Me.CreateGraphics.DrawLine(penR, 90, 170, 420, 170)
    End Sub

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
        SenKaki_1()
    End Sub

TabPage の描画については、これから取りかかりますが理解出来るかどうか(泣)

先ずは、急ぎ御礼まで。
有り難う御座いました。
投稿者 KOZ  (社会人) 投稿日時 2025/5/25 07:50:56
フォームを最小化して元に戻してみてください。
書かれたものが消えているはずです。
描画は Paint イベントで行いましょう。
投稿者 とくま  (社会人) 投稿日時 2025/5/26 09:19:30
他のウィンドウ(メモ帳とか)をフォームの上に重ねた後に取り除いても消えると思います。
ディスプレイ上は2次元の話なので、ウィンドウを重ねると下に描画されていたフォームは上書きされて存在しなくなります。
取り除いたときに、もう一度、描画しなおす必要があります。ディスプレイ上では、常に再描画が行われていることを覚えてください。
フォーム自体は、描画する処理が裏の見えない処理に書かれていますが、後からプログラムした描画処理も再描画する
必要があります。この手っ取り早いやり方が Paint イベントです。つまり初心者は、画面に描画する処理で
Paint イベント以外は使ったらNGだと思って下さい。


>    Private Sub SenKaki_1()
>        Me.CreateGraphics.DrawLine(penR, 90, 170, 420, 170)
>    End Sub
これもNG。
Paint イベントの引数(e.Graphics)を使いまわす場合は、裏の処理が後始末してくれるので問題ありませんが、
自分で CreateGraphics するとリソース(メモリ)の確保が行われます。
その場合、解放処理まで自分で書く必要があります。画像系のプログラムはメモリを食うので、
繰り返すと目に見える形でメモリリークが起こる場合があります。
https://dobon.net/vb/dotnet/graphics/drawline.html
>'リソースを解放する
>g.Dispose()
の処理が必要です。
penR も使いまわすのは良いですが、フォームの Dispose イベントで解放するのを覚えたほうが良い場面となります。
penR.Dispose() を呼ぶ必要があります。
投稿者 とくま  (社会人) 投稿日時 2025/5/26 09:45:58
Public Class Form1
    'フォームが生きている限り使いまわす 
    Private penR As Pen
    Private penG As Pen
    Private penB As Pen

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        '初期処理 
        penR = New Pen(Color.Red, 2)
        penG = New Pen(Color.Green, 2)
        penB = New Pen(Color.Blue, 2)
    End Sub

    'TabPage の Paint イベント 
    Private Sub TabPage1_Paint(sender As Object, e As PaintEventArgs) Handles TabPage1.Paint
        'システムが裏で作成した e を利用 
        e.Graphics.DrawLine(penR, 10, 120, 50, 220)
        'オリジナル処理(自分で描画オブジェクト確保) 
        SenKaki_1()
    End Sub

    'オリジナル処理は関数内でリソースも解放しておく 
    Private Sub SenKaki_1()
        'TabPage1のGraphicsオブジェクトを作成 
        Dim g As Graphics = TabPage1.CreateGraphics()
        '画像を描画 
        g.DrawLine(penB, 60, 10, 20, 30)
        'Graphics破棄(メモリ解放) 
        g.Dispose()
    End Sub

    Private Sub Form1_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
        'ペンの破棄(メモリ解放) 
        penR.Dispose()
        penG.Dispose()
        penB.Dispose()
    End Sub
End Class
投稿者 KOZ  (社会人) 投稿日時 2025/5/26 18:54:57
> 他のウィンドウ(メモ帳とか)をフォームの上に重ねた後に取り除いても消えると思います。
XP 以前は消えてたんですが、「Desktop Window Manager(DWM)」が Vista で導入されてから消えなくなってますよ。
各ウインドウはオフスクリーンバッファ(バックバッファ)に描画され、最終的にGPUで合成されるようになりました。
重なったウインドウが移動しても DWMがキャッシュした内容を使って表示するので消えません。
投稿者 hige3  (社会人) 投稿日時 2025/5/27 07:45:12
KOZ様

TabPage に描画する事は出来ました。
問題は、ご指摘通りでTabPageを移動すると消えてしまう事です。

解決策を下記で勉強中でしたが理解力不足で(泣)

初級講座 第2回 絵を書く
http://rucio.o.oo7.jp/main/dotnet/shokyu/standard2.htm


とくま様
>ディスプレイ上では、常に再描画が行われていることを覚えてください。

下記で確認、ビックリポンでした。
    Private Sub TabPage1_Paint(sender As Object, e As PaintEventArgs) Handles TabPage1.Paint
        MessageBox.Show(" TabPage1_Paint ", "確認", MessageBoxButtons.OK)
    End Sub

>つまり初心者は、画面に描画する処理でPaint イベント以外は使ったらNGだと思って下さい。

承知致しました。
勉強不足、理解力不足を痛感しております。

お二方、御教授を有り難う御座いました。
今後ともよろしくお願い致します。