Drawing on a PictureBox control

mcdonnc2004
03-13-2006, 12:40 PM
Hi all,

I have been using the PictureBox control in VB6 to draw on it using the following code:

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Picture1.CurrentX = CurrentX
Picture1.CurrentY = CurrentY

End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 Then
Picture1.Line (Picture1.CurrentX, Picture1.CurrentY)-(CurrentX, CurrentY), vbBlack
End If

End Sub

Very simple stuff. Now I am trying to achieve the same thing in VB.NET as I want to take this and implement it on a PDA (so I can write on a PictureBox or Form). I tried this code to see if it gives similar results to the VB 6 one:

Dim CurrentX
Dim CurrentY

Private Sub pic_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseDown

CurrentX= e.X
CurrentY= e.Y

End Sub

Private Sub pic_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseMove

If e.Button = Windows.Forms.MouseButtons.Left Then
Dim bit As Bitmap = New Bitmap(pic.Width, pic.Height)
Dim g As Graphics = Graphics.FromImage(bit)
Dim myPen As Pen = New Pen(Color.Blue, 3)

g.DrawLine(myPen, CurrentX, CurrentY, e.X, e.Y)

pic.Image = bit
End If

End Sub

All this gets me is actually drawing a line on the picturebox. Can anyone tell me where I am going wrong?

Thanks.

JNewt
03-13-2006, 01:04 PM
Instead of using a new image, try drawing to the graphics object being passed by the Paint event (e.Graphics). So you'd have Dim myPen As Pen = New Pen(Color.Blue, 3)
e.Graphics.DrawLine(myPen, CurrentX, CurrentY, e.X, e.Y)

mcdonnc2004
03-14-2006, 06:04 AM
I am confused about this because in VB 6 I would just put the command to draw a line into the MouseDown event and that would allow me to draw on the picturebox as if it were a canvas.

If I use e.Graphics in the MouseDown event it obviously doesn't recognise it and if I try in the Paint event then I cannot reference the mouse coords!

Maybe I'm over-complicating things...?

Mikecrosoft
03-14-2006, 05:23 PM
into MouseDown event you would need to use:

PictureBox1.CreateGraphics.DrawLine(...........

because the MouseDown eventargs doesn't have any Graphics object in it.

jo0ls
03-14-2006, 06:29 PM
If you createGraphics then the paint will overdraw everything when a paint event occurs (form minimize, window passes over form).
You could draw the bitmap in the paint event as well I suppose.

Paint to a bitmap in the mousemove event.
invalidate after drawing to trigger paint.
In paint draw the bitmap to the control.

Optimisation:
use a custom control and switch on double buffering
invalidate only the area that has changed

Example:

Public Class Form1

' just add an instance of the control.
Private Canvas1 As Canvas
'
Public Sub New()
InitializeComponent()
Canvas1 = New Canvas(Me.Width, Me.Height)
Me.Controls.Add(Canvas1)
Canvas1.Dock = DockStyle.Fill
End Sub
'
End Class
'
Public Class Canvas
Inherits UserControl
'
Private _canvas As Bitmap 'declare these
Private _graphics As Graphics 'here so we dont
Private _pen As Pen 'create them repeatedly
Private _lastX, _lastY As Integer
Private _penDown As Boolean
'

Public Sub New(ByVal Width As Integer, ByVal height As Integer)
' we can set double buffering:
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.UserPaint, True)
Me.UpdateStyles()
Me.Size = New Size(Width, height)
_canvas = New Bitmap(Me.Width, Me.Height)
_graphics = Graphics.FromImage(_canvas)
_pen = New Pen(Me.ForeColor)

End Sub
'
Private Sub Canvas_ForeColorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ForeColorChanged
Me._pen = New Pen(Me.ForeColor)
End Sub
'
Private Sub Canvas_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
_lastX = e.X
_lastY = e.Y
_penDown = True
Else
If e.Button = Windows.Forms.MouseButtons.Right Then
_graphics.Clear(Me.BackColor)
Me.Invalidate() ' paints all
End If
End If
End Sub
'
Private Sub Canvas_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
If e.Button = Windows.Forms.MouseButtons.Left Then
_penDown = False
End If
End Sub
'
Private Sub Canvas_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
If _penDown Then
_graphics.DrawLine(_pen, _lastX, _lastY, e.X, e.Y)
' invalidate only the area we just drew, i.e. a rectangle that encloses that line
Dim leftmostx, topmostY As Integer
If _lastX < e.X Then leftmostx = _lastX Else leftmostx = e.X
If _lastY < e.Y Then topmostY = _lastY Else topmostY = e.Y
Dim wid, hei As Integer
wid = Math.Abs(_lastX - e.X) + 1
hei = Math.Abs(_lastY - e.Y) + 1
Dim recToInvalidate As New Rectangle(leftmostx, topmostY, wid, hei)
Me.Invalidate(recToInvalidate) ' fires paint, only the rec is painted
_lastX = e.X
_lastY = e.Y
End If
End Sub
'
Private Sub Canvas_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
' draw the bitmap.
e.Graphics.DrawImageUnscaled(_canvas, 0, 0)
End Sub
'
Private Sub Canvas_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
' can't have a 0,0 bitmap, this will fire on creation before _canvas is instantiated
If (Me.Width = 0) OrElse (Me.Height = 0) OrElse (_canvas Is Nothing) Then Exit Sub
' need a differently sized bitmap
Dim newCanvas As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
Dim g As Graphics = Graphics.FromImage(newCanvas)
' draw old pic into new
g.DrawImageUnscaled(_canvas, 0, 0)
g.Dispose()
_canvas = newCanvas.Clone
_graphics = Graphics.FromImage(_canvas)
newCanvas.Dispose()
End Sub
'
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
' if you were using lots of instances then you would want to dispose of
' them correctly. As this inherits it's dispose method, we override it,
' get rid of the gdi objects and then call the base class' dispose.
_graphics.Dispose()
_canvas.Dispose()
_pen.Dispose()
MyBase.Dispose(disposing)
End Sub
'
End Class

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum