arc95
arc95

Reputation: 97

Draw Rectangle over PictureBox

The next code lets you draw Rectangles in the Form with mouse clics. Why not, or how can be draw over a PictureBox?

Public Class Form1
Dim SelectRect As Rectangle = New Rectangle()
Dim ps As Point = New Point()
Dim pe As Point = New Point()

This catch the first click, starting point or corner of the rectangle

Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
    SelectRect.Width = 0
    SelectRect.Height = 0
    SelectRect.X = e.X
    SelectRect.Y = e.Y
    ps.X = e.X
    ps.Y = e.Y
    pe = ps
End Sub

This part determine the width and height of the rectangle:

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    If (e.Button = MouseButtons.Left) Then
        ControlPaint.DrawReversibleFrame(Me.RectangleToScreen(SelectRect), Color.Black, FrameStyle.Dashed)
        SelectRect.Width = e.X - SelectRect.X
        SelectRect.Height = e.Y - SelectRect.Y
        ControlPaint.DrawReversibleFrame(Me.RectangleToScreen(SelectRect), Color.Black, FrameStyle.Dashed)
    End If

End Sub

This part determine the last coordinate, the second corner of the rectangle:

Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
    Dim g As Graphics = Me.CreateGraphics()
    Dim p As Pen = New Pen(Color.Blue, 2)
    ControlPaint.DrawReversibleFrame(Me.RectangleToScreen(SelectRect), Color.Black, FrameStyle.Dashed)
    g.DrawRectangle(p, SelectRect)
    g.Dispose()
End Sub
   End Class

Upvotes: 2

Views: 5269

Answers (1)

Jimi
Jimi

Reputation: 32248

Your code uses a control (a Form in this case) mouse events to enable the drawing of rectangular shapes, with the help of guidelines, provided by Control.DrawReversibleFrame().
You just have to define the same events of a different, drawable, control - like a PictureBox - and repeat, more or less, the same procedure (after a cleanup).

As many have stated, here and before, use the Graphics object that the Paint event kindly offers, so that your drawing will persist.
The Graphics object you get from Control.CreateGraphics() is not persistent, and it can be erase/clipped when you don't want to.
Use it only if that is really what you have planned to do for the reasons you know.


I've adden an event handler that checks if Control Key is pressed.
If Control is pressed, you add a rectangle, if not, only one rectangle is drawn.
I've also included, as an example, a line of code that fills the rectangle. I think it's interesting, because you have to control the size of the invalidated Region.
Comment out these lines of code to draw just the frame:

SelectRect.Inflate(CInt(-_pen.Width / 2), CInt(-_pen.Width / 2))
e.Graphics.FillRectangle(_brush, SelectRect)


enter image description here

Dim SelectRect As Rectangle = New Rectangle()
Dim _pen As Pen = New Pen(Color.Green, 4)
Dim _brush As SolidBrush = New SolidBrush(Color.Orange)
Dim _ControlPressed As Boolean = False

Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    _ControlPressed = (e.Modifiers And Keys.Control) = Keys.Control
End Sub

Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
    _ControlPressed = (e.Modifiers And Keys.Control) = Keys.Control
End Sub


Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
    SelectRect.Location = e.Location
    SelectRect.Size = New Size(0, 0)
End Sub

Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    If (e.Button = MouseButtons.Left) Then
        ControlPaint.DrawReversibleFrame(PictureBox1.RectangleToScreen(SelectRect), PictureBox1.BackColor, FrameStyle.Dashed)
        SelectRect.Width = e.X - SelectRect.X
        SelectRect.Height = e.Y - SelectRect.Y
        ControlPaint.DrawReversibleFrame(PictureBox1.RectangleToScreen(SelectRect), PictureBox1.BackColor, FrameStyle.Dashed)
    End If
End Sub

Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp

    If (e.Y < SelectRect.Y) Then
        SelectRect.Location = If(SelectRect.Location.X > e.X,
                                 New Point(e.X, e.Y), New Point(SelectRect.X, e.Y))
        SelectRect.Size = New Size(Math.Abs(SelectRect.Width), Math.Abs(SelectRect.Height))
    Else
        If SelectRect.Location.X > SelectRect.Right Then
            SelectRect.Location = New Point(e.X, SelectRect.Y)
            SelectRect.Size = New Size(Math.Abs(SelectRect.Width), Math.Abs(SelectRect.Height))
        End If
    End If

    If _ControlPressed Then
        Dim _InflatedRect As Rectangle = New Rectangle(SelectRect.Location, SelectRect.Size)
        _InflatedRect.Inflate(CInt(_pen.Width / 2), CInt(_pen.Width / 2))
        PictureBox1.Invalidate(_InflatedRect)
    Else
        PictureBox1.Invalidate()
    End If

End Sub

Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    'Draw the outer rectangle with the color of _pen
    e.Graphics.DrawRectangle(_pen, SelectRect)

    'Fill the rectangle with the color of _brush
    'It's half Pen.Width smaller so it doesn't erase the contour
    SelectRect.Inflate(CInt(-_pen.Width / 2), CInt(-_pen.Width / 2))
    e.Graphics.FillRectangle(_brush, SelectRect)

End Sub

Upvotes: 2

Related Questions