dポイントプレゼントキャンペーン実施中!

VB2008 Express Edditionを使って、写真画像に直線等の図形を重ねる
プログラムを作っています。

PictureBoxのBackgroundImageに写真画像を設定し、

Dim gp As Graphics = PictureBox1.CreateGraphics()
gp.DrawLine(Pens.Pink, 100, 100, 300, 300)
gp.Dispose()

といった書式で図形が描画できること、それを削除するには

If Not (PictureBox1.Image Is Nothing) Then
PictureBox1.Image.Dispose()
End If
PictureBox1.Image = Nothing

とすれば良いことは分かりました。
次に、例えば(100,100)-(300,300)の直線を(100,100)-(300,290)に
変更するような修正をしたいのですが、上記の図形削除と描画を
組み合わせれば良いと考えてやってみたのですが、一瞬図形が
表示されてすぐに消えてしまいます。
図形削除と再描画を別々のボタンに割り当てるとうまくいくのですが、
1つのボタンに割り当てて続けて行うとダメなようです。
これを回避するにはどうすればいいでしょうか?

A 回答 (2件)

#1 Wizard_Zeroです。



補足の件、検証してみました。

下記のように、PictureBoxを継承したクラスを作り、OnPaintBackgroundとOnPaintをそれぞれオーバーロードした上で、個々の動作を止めてその動作を検証。

Friend Class PictureBoxEx
Inherits Windows.Forms.PictureBox

Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
' 背景の描画を中止
'MyBase.OnPaintBackground(pevent)
End Sub

Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
' Paintの呼び出しを中止
'MyBase.OnPaint(pe)
End Sub
End Class

結果はこうなりました。
結果1. OnPaintBackgroundとOnPaintの両方を止める
真っ黒で何も描画されない。

結果2. OnPaintだけを止め、OnPaintBackgroundを実行させる。
背景色+背景画像が描画される。

結果3. OnPaintBackgroundだけを止め、OnPaintを実行させる。
真っ黒な背景にImageへ描き込んだ画像が描画される。

以上のことから、PictureBoxの描画順序は・・・
1. PictureBoxを黒で塗りつぶす(イベント不明)
2. OnPaintBackgroundで、背景色の塗りつぶしとBackgroundImageに設定した画像の描画が行われる
3. OnPaintで、Imageプロパティに描き込んだ画像が描画される。
となります。

2~3では黒く塗りつぶしているところがないので、ちらつきの原因があるとすれば、1~2に遷移するところだと思います。ただ、私のほうでは特にちらつきは発生しませんでした。

ちらつきの原因は他にあるかもしれません。


Imageを透明色でクリアする点ですが、透明色でクリアしないと背景画像がImageで上書きされてしまいます。「透明で消す」というと不思議な感じがしますが、要はImageを構成する画像のビットを全てTransparent(A:R:G:B = 0:0:0:0)で置き換えるということです。
※黒の場合はA:R:G:B = 255:0:0:0 になります。

ちらつきの原因はImageを透過合成するときかもしれませんが、GDI+が内部でどのように処理しているのかも分からないのでなんとも言えませんねぇ…。
    • good
    • 0
この回答へのお礼

詳細な調査、ありがとうございました。
こちらでも色々試してみたのですが、ちらつきは再描画に関係なく

Dim gp As Graphics = PictureBox1.CreateGraphics()
gp.Clear(Color.Transparent)
PictureBox1.Refresh()
gp.Dispose()

としただけで発生しました。
どうも
gp.Clear(Color.Transparent)
が、透過色ではなく真っ黒に塗り潰しているようです。
試しに
gp.Clear(Color.Black)
に書き換えても、見た目には全く変わりません。VBのバグ?
結局、
PictureBox1.Refresh()
こそが(一時的に描いた)図形を消去していることが分かり、
図形の消去をこの1文だけにすることで、ちらつきもなくなりました。
本筋ではないかもしれませんが、とりあえずやりたいことは問題なく
できるようになりました。
どうもありがとうございました。

お礼日時:2009/08/14 23:54

CreateGraphicsを使った描画だと、PictureBoxが他のウィンドウに隠れた場合や、リサイズ時に再描画されずに消えてしまうのではないでしょうか??


また、PictureBoxのImageプロパティは、再描画時に自動的に描画されるImageオブジェクトを格納するものなので、画像を消去するためだけにDisposeしてしまうのもどうかと・・・。


回避策ではありませんが、VB2005で書いたコードを掲載しておきます。なお、PictureBox1には、あらかじめBackgroundImageが設定されているものとします。


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

' PictureBoxと同じサイズのビットマップを生成しImageプロパティにセットしておく。
' 透過合成するので、24bitRGBではなく32bitARGBで。
PictureBox1.Image = New Drawing.Bitmap(PictureBox1.Width, PictureBox1.Height, Drawing.Imaging.PixelFormat.Format32bppArgb)

End Sub

' Button1のクリックで描画
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

' ImageプロパティからGraphicsを生成
Using gp As Drawing.Graphics = Drawing.Graphics.FromImage(PictureBox1.Image)
' 直線を描画
gp.DrawLine(Drawing.Pens.Pink, 10, 10, 200, 40)
End Using

' PictureBox1を更新
PictureBox1.Refresh()

End Sub

' Button2のクリックで消去
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Using gp As Drawing.Graphics = Drawing.Graphics.FromImage(PictureBox1.Image)
' 透明色で消去。(白や黒だと背景が透過されなくなります)
gp.Clear(Drawing.Color.Transparent)
End Using

PictureBox1.Refresh()

End Sub
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
VBは不慣れなもので、ご指摘、勉強になります。
ちなみに、CreateGraphicsを使った描画だと再描画されないことは
認識していましたが、まずは動くものを作ってみて、改良はその後と
考えていました。

質問に提示した図形消去の方法は、本やWEBで調べた結果、この方法と
「背景色で塗り潰す」という強引な方法しか得られなかったためです。
ご提示の「透明色で塗り潰す」のが目的に非常に近く、この方法に
入れ替えてみたら一応はうまく動作しました。
ただ、VBの仕様かもしれませんが、一旦黒で塗り潰して、Refresh()で
再描画しているようで、画面のちらつきが気になります。
ちらつきを止める方法と、Imageをクリアするのに「透過色で塗り潰す」
のが妥当な方法なのか、引き続きよろしくお願いします。

お礼日時:2009/08/13 08:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!