アプリ版:「スタンプのみでお礼する」機能のリリースについて

VBのコード記述作法に自身がなく不安です。

CADのラバーラインのような感じです。
PictureBoxを置いてFormの上下左右にアンカーしてるだけです。

lineモードにXorがないので下記のようにしました。
今は、とりあえず動いてますが、<?>印部分をここに記述しても安定動作しますか?
(メモリの無駄使いとか・CPUの負荷とか)

又Form1_Resizeで再描画してますが、Windowを最小化すると当然でしょうが
PictureBox1.Image = New Bitmap(PictureBox1.Width, PictureBox1.Height)
でエラーになります。
これを防ぐ方法を教えて下さい。


Public Class Form1
Private sx, sy, ex, ey As Integer
Private flg As Boolean = False
Private fg, bg As Graphics   '----<?>----
Private d(100, 4) As Integer
Private po As Integer = 1
'--------------------------------
Private Sub PictureBox1_MouseDown(~~
If flg = False Then
sx = e.X
sy = e.Y
ex = sx
ey = sy
flg = True
fg = PictureBox1.CreateGraphics() '----<?>----

Else
flg = False
ex = e.X
ey = e.Y
PictureBox1.Refresh()
fg.Dispose() '----<?>----

bg = Graphics.FromImage(PictureBox1.Image) '----<?>----
bg.DrawLine(Pens.Black, sx, sy, ex, ey)
bg.Dispose() '----<?>----

PictureBox1.Refresh()
d(po, 1) = sx
d(po, 2) = sy
d(po, 3) = ex
d(po, 4) = ey
po = po + 1

End If
End Sub
'--------------------------------
Private Sub PictureBox1_MouseMove(~~

If flg = True Then
PictureBox1.Refresh()

fg.DrawLine(Pens.Blue, sx, sy, e.X, e.Y)
ex = e.X
ey = e.Y
End If
End Sub
'--------------------------------
Private Sub Form1_Resize(~~

Dim x As Integer

PictureBox1.Image = New Bitmap(PictureBox1.Width, PictureBox1.Height)

bg = Graphics.FromImage(PictureBox1.Image) ' ----<?>----

For x = 1 To po - 1
bg.DrawLine(Pens.Black, d(x, 1), d(x, 2), d(x, 3), d(x, 4))
Next
bg.Dispose() ' ----<?>----
End Sub
'--------------------------------

End Class

A 回答 (2件)

gはペイントイベントの引数のプロパティを使っているのでDisposeする必要はありませんよ


コレは Framework側で管理してますのでユーザー側でDisposeしてしまうとおかしくなってしまいます
Disposeするのはユーザーが作成したオブジェクトと考えればほぼ間違えないでしょう

またオブジェクトが10000とかあるのでしたら描画のしなおしに対し自分自身が描画対象なのか判定する必要が出てくるでしょう
今は Invalidateで無条件に コントロール全体を無効にしています
描画しなおしたい範囲を指定することも可能ですので無効化を
Invalidate(New Rectangle( sx, sy, abs(ex-sx), abs( ey-sy )) )
といった具合にします

描画ルーチンで
 dim rc,rcPaint as Rectangle
 rcPaint = e.ClipRectangle
 For x=1 to po -1
  rc = new Rectangle( d(x,1), d(x,2), abs(d(x,3) - d(x,1)), abs(d(x,4) - d(x,2))
  ' 交差部分があるかチェック
  if rc.IntersectsWith( rcPaint ) then
   g.DrawLine( Pens.Black, d(x,1) ,d(x,2), d(x,3), d(x,4) )
  end if
 next

といった具合にしてみてはいかがでしょう ・・・

この回答への補足

Dispose そうだったんですか。
よくサンプル等でDispose記述があったので書くものだと思ってました。

IntersectsWith これはクリッピングということですね。
「abs」関数がなく、math.absでとうりました。

CPUの使用率を監視すると、負荷が軽減されているような気がします。

でも、PictureBoxを大きくしたり小さくしたりすると、線描画が部分的に欠けたりします。
何か解決法がありましたらご教授お願いできれば幸です。

補足日時:2007/07/17 18:05
    • good
    • 0
この回答へのお礼

いろいろと、ありがとうございました。

お礼日時:2007/07/19 16:21

fg,bgは要らないかも知れないですよ ・・・



線の描画をPaintイベントに任せてしまう
Private PictureBox1_Paint( ... )
 dim g as Graphics = e.Graphics
 ' 記憶した線を描画
 for n as integer = 1 to po-1
  g.DrawLine( Pens.Black, d(x,1),d(x,2),d(x,3),d(x,4))
 next
 if sx<>ex and sy<>ey then
  ' 現在の線を描画
  g.DrawLine( Pens.Blue, sx, sy, ex, ey )
 end if
End Sub

Private sub PictureBox1_MouseDown( ... )
 if flg = false then
  ' 始点を設定
  sx = e.X : sy = e.Y
  ex = sx : ey = sy
  flag = true
 else
  ' 線を登録
  d(po,1) = sx : d(po,2) = sy
  d(po,2) = e.X : d(po,4) = e.Y
  ' 現在の線の始点=終点に設定
  sx = ex : sy = ey
  flg = false
  ' ピクチャーボックス再描画
  PictureBox1.Invalidate()
 end if
End Sub

Private sub PictureBox1_MouseMove( ... )
 if flg then
  ' 現在のマウス位置を終点に設定
  ex = e.X : ey = e.Y
  ' ピクチャーボックス再描画
  PictureBox1.Invalidate()
 end if
End Sub

こんな感じで 上手くいくと思いますよ

この処理だけなら Form1_Resizeは必要ないように思います

この回答への補足

ご指導頂いたコードに2,3の訂正を加え(d(po,3) = e.Xとか)実行しました。
windowを最小化しても大丈夫でした。
For Next文の初期値に As integer を入れれるなんて知りませんでした。

さらに質問ですが、このコードだと青い線を描画し直すたびに、記憶した線も全て描画し直しているのですか?
仮に記憶した線が10000本あったら・・・・
古いPCだったらCPUの負担は大きくなりませんか?

それと、gはどこでDisposeしたらよいのでしょうか?
しなくてもいいのかな?

まだまだVBのマナーを知らなくて、よろしくお願いします。

補足日時:2007/07/17 01:34
    • good
    • 0

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