【问题标题】:Draw Rectangle over PictureBox在 PictureBox 上绘制矩形
【发布时间】:2018-07-06 12:28:45
【问题描述】:

接下来的代码让您可以用鼠标在窗体中绘制矩形。 为什么不,或者如何在 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

【问题讨论】:

  • 有什么问题?是一样的。
  • 始终使用 PaintEvent 进行所有绘图。 CreateGraphics 几乎总是做错事
  • @Jimi 类似,我之前找到了这段代码,这个代码可以让你直接在表单上手动绘制矩形(不是以编程方式分配的位置),但是如果你有一个 PictureBox 绘图就可以在返回(表单)-如果某些部分仍然可见-,但您不能在 PictureBox 上绘图。这就是问题
  • 让我明白。您只想在 PictureBox 上绘图吗?还是Form和PictureBox?换句话说,您拥有该代码,但您不知道如何调整它以在不同的控件上绘制形状。是这样吗?
  • 如果您没有处理 Paint 事件,那么您做错了。 MouseDownMouseMoveMouseUp 事件应该只记录鼠标位置,然后通过调用 RefreshInvalidateUpdate 强制重绘。绘图应该全部在Paint 事件处理程序中完成,情况总是如此。永远不要打电话给CreateGraphics

标签: vb.net winforms graphics mouseevent picturebox


【解决方案1】:

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

正如许多所说,在这里和之前,使用 Graphics 对象 Paint 事件请提供,以便您的绘图将持续存在。
您从 Control.CreateGraphics() 获得的 Graphics 对象不是 持久性,并且可以在您不想要时擦除/剪切。
仅当您确实计划这样做时才使用它 你知道的原因。


我添加了一个事件处理程序,用于检查是否按下了 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

【讨论】:

  • 我从来没有建议过:规则:矩形必须从左到右,从上到下绘制......但现在在图片框上效果很好!
  • @arc95 你说得对,我没有检查。我已经更新了代码:现在您可以在任何方向上绘制框架/框了。
  • 哇,一段不错的代码,对我帮助很大!!,我更新了项目!!你能帮我确定单个矩形吗?当您在编辑模式下添加矩形时,代码已经在 txt 文件中保存了坐标和“建议的名称”,但我不知道如何取回名称/矩形或放置在矩形附近的标签中。问题:当您单击图片框时,会出现“建议名称”文本框!此外,我在目录部分和书籍部分工作了很多,frmbooks 的第 77 行小问题。 1drv.ms/f/s!AlqVaIM2GTrSlTmW9VKyqG1KzOoE单击矩形区域会显示一条消息
猜你喜欢
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 2011-11-13
相关资源
最近更新 更多