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つのボタンに割り当てて続けて行うとダメなようです。
これを回避するにはどうすればいいでしょうか?
No.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+が内部でどのように処理しているのかも分からないのでなんとも言えませんねぇ…。
詳細な調査、ありがとうございました。
こちらでも色々試してみたのですが、ちらつきは再描画に関係なく
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文だけにすることで、ちらつきもなくなりました。
本筋ではないかもしれませんが、とりあえずやりたいことは問題なく
できるようになりました。
どうもありがとうございました。
No.1
- 回答日時:
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
アドバイスありがとうございます。
VBは不慣れなもので、ご指摘、勉強になります。
ちなみに、CreateGraphicsを使った描画だと再描画されないことは
認識していましたが、まずは動くものを作ってみて、改良はその後と
考えていました。
質問に提示した図形消去の方法は、本やWEBで調べた結果、この方法と
「背景色で塗り潰す」という強引な方法しか得られなかったためです。
ご提示の「透明色で塗り潰す」のが目的に非常に近く、この方法に
入れ替えてみたら一応はうまく動作しました。
ただ、VBの仕様かもしれませんが、一旦黒で塗り潰して、Refresh()で
再描画しているようで、画面のちらつきが気になります。
ちらつきを止める方法と、Imageをクリアするのに「透過色で塗り潰す」
のが妥当な方法なのか、引き続きよろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ListBoxで改行したい
-
MFCでのコンボボックスについて
-
OpenGLでのオブジェクトの描画上限
-
水平線の描画
-
アルゴリズム : 円描画
-
c言語 ちらつき
-
PictureBoxのダブルバッファリ...
-
コンボボックスのテキストを消...
-
画面に絵を出す方法
-
Word 描画オブジェクトを削除...
-
C# DrawImage 物理サイズでな...
-
VBA シートのボタン名を変更し...
-
worksheetFunctionクラスのVloo...
-
パソコンへの「Dropbox...
-
ユーザーフォームを表示中にシ...
-
VBAがブレークモードになっ...
-
VBA(エクセル)で自動的にボタン...
-
【C#/Java?】try-catchでcatch...
-
カメラスクロールするのを動画...
-
エクセルエラー13型が一致しま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ListBoxで改行したい
-
for文の実行速度を遅くしたいの...
-
VB.NETでグラフィックを描くと...
-
C#でPictureBox内での図形移動...
-
Word 描画オブジェクトを削除...
-
PowerPoint の VBA
-
C#で壁の当たり判定と自キャラ...
-
ピクチャボックスに描画した画...
-
win32api複数のタイマーを同時...
-
C#を用いて描画する四角形の角...
-
円の頂点の求め方を知りたいです。
-
ビットマップに描画をしてピク...
-
給紙トレイをダイアログを使わ...
-
C# DrawImage 物理サイズでな...
-
C++/CLIを用いて画像をクリップ...
-
VB 6.0 PictureBox のプロパテ...
-
MFCでのコンボボックスについて
-
PictureBoxのダブルバッファリ...
-
VC++ MFCチェックボックスの色...
-
Excel 2007で、フリーフォーム描画
おすすめ情報