DOBON.NETプログラミング道掲示板

[ 最新記事及び返信フォームをトピックトップへ ]

■33851 / inTopicNo.1)  2枚のPictureBoxを合成した上で描画したい
  
□投稿者/ K-1 一般人(5回)-(2018/06/10(Sun) 11:51:28)
  • アイコン環境/言語:[VB.NET(2017)] 
    分類:[.NET] 

    VB.NET(2017)を使用しています。
    PictuteBoxの画像を合成し、その上で描画を行いたく、テストとして3枚のPictureBoxを同じサイズ(640x640)で作成し、以下のようなコードを作成しました。
    
    Public Class Form1
        Private Grp1 As Graphics
        Private GrpWrite As Graphics
        Private GrpBack As Graphics
        Private Bmp1 As Bitmap
        Private BmpWrite As Bitmap
        Private BmpBack As Bitmap
    
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            'グラフィック初期化
            '表示領域
            Bmp1 = New Bitmap(640, 640)
            ViewPictureBox.Image = Bmp1
            Grp1 = Graphics.FromImage(Bmp1)
    
            '描画領域
            BmpWrite = New Bitmap(640, 640)
            WritePictureBox.Image = BmpWrite
            GrpWrite = Graphics.FromImage(BmpWrite)
    
            '背景領域
            BmpBack = New Bitmap(640, 640)
            BackPictureBox.Image = BmpBack
            GrpBack = Graphics.FromImage(BmpBack)
    
            'クリア
            GrpBack.Clear(Color.White)
            GrpWrite.Clear(Color.White)
    
            '背景領域描画
            GrpBack.DrawLine(New Pen(Color.Red, 1), 0, 0, 640, 640)
    
            '描画領域描画
            GrpWrite.DrawLine(New Pen(Color.Black, 1), 640, 0, 0, 640)
    
            '背景領域と描画領域を合成して表示領域に表示
            BmpWrite.MakeTransparent(Color.White)       '透明化設定
            Grp1.DrawImage(BmpBack, 0, 0, 640, 640)
            Grp1.DrawImage(BmpWrite, 0, 0, 640, 640)
    
            '表示領域描画
            Grp1.DrawLine(New Pen(Color.Black, 1), 320, 0, 320, 640)
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            '描画領域描画
            GrpWrite.DrawLine(New Pen(Color.Black, 1), 0, 320, 640, 320)
    
            BmpWrite.MakeTransparent(Color.White)
            Grp1.DrawImage(BmpBack, 0, 0, 640, 640)
            Grp1.DrawImage(BmpWrite, 0, 0, 640, 640)
    
        End Sub
    End Class
    
    背景領域と描画領域表示が合成され、表示領域に表示されることまでは出来ました。
    PushButton押下時にさらに描画領域に横線を書き足して表示領域に表示させたいのですが、横線が出ません。
    
    透明化設定が悪さをしているのかと思って透明化設定2箇所をコメントにして見ましたが状況は変わりませんでした。
    

マルチポストを報告
違反を報告
引用返信 削除キー/
■33852 / inTopicNo.2)  Re[1]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ Azulean 大御所(496回)-(2018/06/10(Sun) 17:11:22)
  • アイコンNo33851に返信(K-1さんの記事)
    > PushButton押下時にさらに描画領域に横線を書き足して表示領域に表示させたいのですが、横線が出ません。

    Grp1 への書き込みによって、ViewPictureBox に設定している Bmp1 が変化するかもしれませんが、ViewPictureBox は変わったことを知らない状態です。
    よって、画面の再描画(絵の描き直し)が行われません。

    ViewPictureBox に対して Invalidate メソッド(書き直しが必要なことを教える)を呼び出したら変わるかもしれません。
違反を報告
引用返信 削除キー/
■33853 / inTopicNo.3)  Re[2]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ K-1 一般人(7回)-(2018/06/10(Sun) 18:23:18)
  • アイコン2018/06/10(Sun) 18:25:59 編集(投稿者)
    2018/06/10(Sun) 18:25:45 編集(投稿者)

    No33852に返信(Azuleanさんの記事)
    PushButton処理の最後に
    ViewPictureBox.Invalidate()
    を付け加えてみましたが、効果ありませんでした。

    いろいろ実験していて気がついたのですが、PushButtonの中で行っている
    '描画領域描画
    GrpWrite.DrawLine(New Pen(Color.Black, 1), 0, 320, 640, 320)
    が、そもそも描画できていないようです。
    そこで、そこのあとに
    WritePictureBox.Invalidate()
    を付け加えてみたのですが、描画自体行われていませんでした。

    試しにForm1_Loadで行っている
    BmpWrite.MakeTransparent(Color.White) '透明化設定
    を削除したところ(合成はダメになりましたが)横線描画は正常に動作しました。

    やはりなにか透明化の副作用とかあるんでしょうか・・・

違反を報告
引用返信 削除キー/
■33854 / inTopicNo.4)  Re[3]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ Azulean 大御所(497回)-(2018/06/10(Sun) 20:17:05)
  • アイコンNo33853に返信(K-1さんの記事)
    > 試しにForm1_Loadで行っている
    > BmpWrite.MakeTransparent(Color.White) '透明化設定
    > を削除したところ(合成はダメになりましたが)横線描画は正常に動作しました。
    >
    > やはりなにか透明化の副作用とかあるんでしょうか・・・

    そのようです。
    改めて MakeTransparent のソースコードを調べてみると、このメソッドは呼び出すと、Bitmap クラスの内部のネイティブインスタンスが差し替わるようです。

    https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Bitmap.cs,705fe8a7fda4a24f,references

    以降、その Bitmap に対して Graphics 操作をしたいのであれば、Graphics.FromImage で作り直してください。

    なお、Graphics.FromImage で得た Graphics は持ち続けるのではなく、不要になった段階で Dispose するというように、「必要なときに都度確保する」考え方をした方が良い性質のものです。
違反を報告
引用返信 削除キー/
■33855 / inTopicNo.5)  Re[4]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ K-1 一般人(8回)-(2018/06/10(Sun) 21:13:09)
  • アイコンNo33854に返信(Azuleanさんの記事)
    以下のようにしてみましたところ、想定どおりの画面が出るようになりました。

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    '描画領域描画
    GrpWrite = Graphics.FromImage(BmpWrite)
    GrpWrite.DrawLine(New Pen(Color.Black, 1), 0, 320, 640, 320)
    WritePictureBox.Invalidate()

    Grp1.DrawImage(BmpBack, 0, 0, 640, 640)
    Grp1.DrawImage(BmpWrite, 0, 0, 640, 640)

    ViewPictureBox.Invalidate()
    End Sub

    なんとなくGraphicsの初期化は最初にやっとけばいいかと思っていたのですが、必要に応じて再定義が必要な性格のものだったのですね。
    ありがとうございました。
解決み!
違反を報告
引用返信 削除キー/
■33856 / inTopicNo.6)  Re[5]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ 魔界の仮面弁士 大御所(1111回)-(2018/06/12(Tue) 11:17:19)
  • アイコンNo33855に返信(K-1さんの記事)
    > GrpWrite = Graphics.FromImage(BmpWrite)
    > GrpWrite.DrawLine(New Pen(Color.Black, 1), 0, 320, 640, 320)
    ここは
     Using GrpWrite = Graphics.FromImage(BmpWrite)
      GrpWrite.DrawLine(Pens.Black, 0, 320, 640, 320)
        :
     End Using
    もしくは
     Using GrpWrite = Graphics.FromImage(BmpWrite), P As New Pen(Color.Black, 1)
      GrpWrite.DrawLine(p, 0, 320, 640, 320)
        :
     End Using
    にすべきかと思います。

    Graphics, Bitmap, Font, Pen, Brush などは IDisposable ですので、
    「Graphics.FromImage」や「New Pen」で生成したオブジェクトは、
    使用後直ちに Dispose を呼び出すようにすることが望ましいです。


    ただし Pens.Black や、Paint イベントの e.Graphics などは Dispose しないようにします。
    (これらは共有物であり、自分で生成したオブジェクトではないため)
解決み!
違反を報告
引用返信 削除キー/
■33861 / inTopicNo.7)  Re[6]: 2枚のPictureBoxを合成した上で描画したい
□投稿者/ K-1 一般人(9回)-(2018/06/16(Sat) 10:45:53)
  • アイコン2018/06/16(Sat) 10:46:15 編集(投稿者)

    No33856に返信(魔界の仮面弁士さんの記事)
    Grahicsは後生大事にとっておくモノでもないということなんですね。
    ありがとうございます。
解決み!
違反を報告
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

Mode/  Pass/


- Child Tree -