
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で質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルで同じ数字同士を自動で線で結ぶVBAを教えてください 6 2022/04/26 23:13
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- その他(教育・科学・学問) グーグルスプレッドシートの図形描画のバグ?「保存して終了」ボタンが突然消失 2 2022/04/05 13:11
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- Excel(エクセル) EXCELのグラフを画像(JPG形式)で保存、通常実行がうまく行かない。ステップインはうまく行く 3 2022/08/30 12:06
- Visual Basic(VBA) Visual Basic : ImageListの画像がそろったときにメッセージを表示 1 2023/07/20 13:53
- Windows 8 Route Generator の使い方 1 2023/05/03 00:36
- Illustrator(イラストレーター) 「頂点で線分を伸ばす」作業がうまく行かない。 1 2022/09/09 10:19
- 数学 写真の図は中心(a,b)半径rの円とその円周上の(x1,y1)における接線lと円の中心とlを結ぶ任意 4 2023/08/08 16:20
- PowerPoint(パワーポイント) 2016EXCEL→2016PowerPointにコピペすると図形がゆがみます 5 2022/03/31 11:44
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C++/CLIを用いて画像をクリップ...
-
N88BASICでシューティングゲー...
-
アルゴリズム : 円描画
-
給紙トレイをダイアログを使わ...
-
ListBoxで改行したい
-
Excel VBA:コントロールボタン...
-
vb6のTEXTBOX
-
scilabでのグラフ描画時の軸設定
-
C# DrawImage 物理サイズでな...
-
C#でPictureBoxが二重に表示される
-
ExtFloodFill を使った塗り潰し...
-
ビットマップに描画をしてピク...
-
【Delphi】 Canvasへの描画につ...
-
C言語をDXFファイルに変換す...
-
Linux上でのC++言語を用いたメ...
-
VB.netで図形描画ができません^^;
-
for文の実行速度を遅くしたいの...
-
VBA シートのボタン名を変更し...
-
worksheetFunctionクラスのVloo...
-
「Columns("A:C")」の列文字を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ListBoxで改行したい
-
C#を用いて描画する四角形の角...
-
for文の実行速度を遅くしたいの...
-
給紙トレイをダイアログを使わ...
-
PowerPoint の VBA
-
VB.NETでグラフィックを描くと...
-
MFCでのコンボボックスについて
-
PictureBoxのダブルバッファリ...
-
Word:描画オブジェクト内の画...
-
VB PictureBoxの描画範囲
-
VC++ MFCチェックボックスの色...
-
Word 描画オブジェクトを削除...
-
Visual C++ MaskedTextBoxの右...
-
C++/CLIを用いて画像をクリップ...
-
VB.netで図形描画ができません^^;
-
VC;;6.0のMFCで線を簡単に引け...
-
VB.NETでphotoshopのレイヤーの...
-
角が丸い長方形の描画
-
図の削除直後の再描画
-
vb6のTEXTBOX
おすすめ情報