在 PictureBox 上绘制矩形

Draw Rectangle over PictureBox

下一段代码允许您使用鼠标点击在表单中绘制矩形。 为什么不可以,或者如何在 PictureBox 上绘制?

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

这会捕获第一个点击,矩形的起点或角

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

这部分决定矩形的宽度和高度:

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

这部分确定最后一个坐标,矩形的第二个角:

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

您的代码在 Control.DrawReversibleFrame().
提供的指南的帮助下,使用控件(在本例中为 Form)鼠标事件来绘制矩形形状 您只需为不同的可绘制控件(如 PictureBox)定义相同的事件,并或多或少地重复相同的过程(在清理之后)。

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.


我添加了一个事件处理程序来检查 Control Key 是否被按下。
如果按下Control,则添加一个矩形,否则,只绘制一个矩形。
作为示例,我还包含了一行填充矩形的代码。我认为这很有趣,因为您必须控制无效区域的大小。
注释掉这些代码行以仅绘制框架:

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


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