Results 1 to 2 of 2

Thread: [RESOLVED] Drawing on Pictureboxes on FlowLayoutpanel

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2020
    Posts
    13

    Resolved [RESOLVED] Drawing on Pictureboxes on FlowLayoutpanel

    I know I ask odd questions, and my VB skills are bad. I haven't really done much since VB6 (we're talking mid 90's). I'm working on a program for myself for work that calculates wall panel sizes and creates really simple drawings for installers. I'm using flowlayoutpanel because it suites my needs just fine without having to figure out graphics. You enter the number of panels, the width, and the height and it displays a representation on a Panel. (Thanks to borderstyle)
    Name:  flpexample.png
Views: 306
Size:  7.7 KB
    That is actually good enough but i was thinking of adding a simple line and rectangle drawing ability, but can't figure out how to draw on a runtime created control. I've tried adding Addhandlers for mouse events (based on my searches), but I'm not sure how to do that.
    Code:
     Private Sub GProwsPB(ByVal PanelsX As Integer)
            Dim psw As Integer = TBWidth.Text * 2.4
    
            Dim psh As Integer = TBHeight.Text * 2.4
    
            Dim lbw As Integer = psw - 10
            Dim lbh As Integer = psh / 2
    
            For i As Integer = 1 To PanelsX
                Dim fl As New PictureBox
    
                fl.Size = New Size(psw, psh)
                fl.BackColor = Color.White
                fl.Margin = New Padding(0)
    
                fl.BorderStyle = BorderStyle.FixedSingle
                fl.Cursor = Cursors.Hand
                fl.AllowDrop = True
                'AddHandler fl.MouseDown, AddressOf MouseXDown
                'AddHandler fl.MouseMove, AddressOf MouseXMove
                'AddHandler fl.MouseUp, AddressOf MouseXUp
                Dim lbl As New Label
                Dim lblSize As New Label
                lbl.Text = TBLabel.Text & vbNewLine & TBPanelSize.Text
                lbl.AutoSize = False
                lbl.Size = New Size(lbw, lbh)
                lbl.Anchor = AnchorStyles.None
                lbl.TextAlign = ContentAlignment.BottomCenter
                fl.Controls.Add(lbl)
    
                FlpPanels.Controls.Add(fl)
            Next
        End Sub
    That sloppy code draws my pictureboxes and I would like to be able to then draw on them. Afterwards I just save the parent panel as an image file. I could post the code I tried for the mouse events but you might just laugh at me . It could even draw in front of the pictureboxes if that doesn't effect how drawtobitmap works. Is this even possible? Any examples would be much appreciated. Thanks

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Drawing on Pictureboxes on FlowLayoutpanel

    This question really has nothing to do with drawing on a PictureBox. That is EXACTLY the same regardless of whether the control is added at design time or run time. If you can draw on a control added at design time then you can draw on a control created at run time. If you can't draw on a control created at design time then stop what you're doing and learn that first. Once you can do that, the actual question you need to ask is how to attach event handlers to controls created at run time. The answer to that is generic, i.e. it is the same no matter the control and no matter the event, so it has nothing specific to do with drawing on PictureBoxes.

    As an example, here is the code from my CodeBank thread about GDI+ drawing here:
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     'The lines that have been drawn but not saved.
    4.     Private lines As New List(Of Line)
    5.  
    6.     'The start point of the line currently being drawn.
    7.     Private start As Point
    8.  
    9.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    10.         'Place a blank image in the PictureBox control.
    11.         Me.PictureBox1.Image = New Bitmap(Me.PictureBox1.Width, Me.PictureBox1.Height)
    12.     End Sub
    13.  
    14.     Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    15.         'Remember the point at which the line started.
    16.         Me.start = e.Location
    17.     End Sub
    18.  
    19.     Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    20.         'Remember the point at which the line ended.
    21.         Dim [end] As Point = e.Location
    22.  
    23.         'Add the new line to the list.
    24.         Me.lines.Add(New Line(Me.start, [end]))
    25.  
    26.         Dim area As New Rectangle(Math.Min(Me.start.X, [end].X), _
    27.                                   Math.Min(Me.start.Y, [end].Y), _
    28.                                   Math.Abs(Me.start.X - [end].X), _
    29.                                   Math.Abs(Me.start.Y - [end].Y))
    30.  
    31.         'Inflate the rectangle by 1 pixel in each direction to ensure every changed pixel will be redrawn.
    32.         area.Inflate(1, 1)
    33.  
    34.         'Force the control to repaint so the new line is drawn.
    35.         Me.PictureBox1.Invalidate(area)
    36.         Me.PictureBox1.Update()
    37.     End Sub
    38.  
    39.     Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    40.         'Draw each line on the control.
    41.         Me.DrawLines(e.Graphics)
    42.     End Sub
    43.  
    44.     Private Sub Save()
    45.         'Create a Graphics object from the Image in the PictureBox.
    46.         Using g As Graphics = Graphics.FromImage(Me.PictureBox1.Image)
    47.             'Draw each line on the image to make them permanent.
    48.             Me.DrawLines(g)
    49.         End Using
    50.  
    51.         'Clear the temporary lines that were just saved.
    52.         Me.Clear()
    53.     End Sub
    54.  
    55.     Private Sub Clear()
    56.         'Clear all unsaved lines.
    57.         Me.lines.Clear()
    58.  
    59.         'Force the control to repaint so the lines are removed.
    60.         Me.PictureBox1.Refresh()
    61.     End Sub
    62.  
    63.     Private Sub DrawLines(ByVal g As Graphics)
    64.         For Each line As Line In Me.lines
    65.             g.DrawLine(Pens.Black, line.Start, line.End)
    66.         Next line
    67.     End Sub
    68.  
    69. End Class
    70.  
    71. Public Class Line
    72.  
    73.     'The line's start point.
    74.     Private _start As Point
    75.  
    76.     'The line's end point.
    77.     Private _end As Point
    78.  
    79.     'The line's start point.
    80.     Public Property Start() As Point
    81.         Get
    82.             Return Me._start
    83.         End Get
    84.         Set(ByVal value As Point)
    85.             Me._start = value
    86.         End Set
    87.     End Property
    88.  
    89.     'The line's end point.
    90.     Public Property [End]() As Point
    91.         Get
    92.             Return Me._end
    93.         End Get
    94.         Set(ByVal value As Point)
    95.             Me._end = value
    96.         End Set
    97.     End Property
    98.  
    99.     Public Sub New()
    100.         Me.New(Point.Empty, Point.Empty)
    101.     End Sub
    102.  
    103.     Public Sub New(ByVal start As Point, ByVal [end] As Point)
    104.         Me._start = start
    105.         Me._end = [end]
    106.     End Sub
    107.  
    108. End Class
    The event handlers that relate specifically to the PictureBox are these:
    vb.net Code:
    1. Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    2.     'Remember the point at which the line started.
    3.     Me.start = e.Location
    4. End Sub
    5.  
    6. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    7.     'Remember the point at which the line ended.
    8.     Dim [end] As Point = e.Location
    9.  
    10.     'Add the new line to the list.
    11.     Me.lines.Add(New Line(Me.start, [end]))
    12.  
    13.     Dim area As New Rectangle(Math.Min(Me.start.X, [end].X), _
    14.                               Math.Min(Me.start.Y, [end].Y), _
    15.                               Math.Abs(Me.start.X - [end].X), _
    16.                               Math.Abs(Me.start.Y - [end].Y))
    17.  
    18.     'Inflate the rectangle by 1 pixel in each direction to ensure every changed pixel will be redrawn.
    19.     area.Inflate(1, 1)
    20.  
    21.     'Force the control to repaint so the new line is drawn.
    22.     Me.PictureBox1.Invalidate(area)
    23.     Me.PictureBox1.Update()
    24. End Sub
    25.  
    26. Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    27.     'Draw each line on the control.
    28.     Me.DrawLines(e.Graphics)
    29. End Sub
    In order to make that code generic for any PictureBox, rather than specific to PictureBox1, you simply remove the Handles clauses and change any specific references to use the sender parameter instead. It's also a good idea to change the name to something more general:
    vb.net Code:
    1. Private Sub PictureBoxes_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    2.     'Remember the point at which the line started.
    3.     Me.start = e.Location
    4. End Sub
    5.  
    6. Private Sub PictureBoxes_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    7.     'Remember the point at which the line ended.
    8.     Dim [end] As Point = e.Location
    9.  
    10.     'Add the new line to the list.
    11.     Me.lines.Add(New Line(Me.start, [end]))
    12.  
    13.     Dim area As New Rectangle(Math.Min(Me.start.X, [end].X), _
    14.                               Math.Min(Me.start.Y, [end].Y), _
    15.                               Math.Abs(Me.start.X - [end].X), _
    16.                               Math.Abs(Me.start.Y - [end].Y))
    17.  
    18.     'Inflate the rectangle by 1 pixel in each direction to ensure every changed pixel will be redrawn.
    19.     area.Inflate(1, 1)
    20.  
    21.     Dim pb = DirectCast(sender, PictureBox)
    22.  
    23.     'Force the control to repaint so the new line is drawn.
    24.     pb.Invalidate(area)
    25.     pb.Update()
    26. End Sub
    27.  
    28. Private Sub PictureBoxes_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
    29.     'Draw each line on the control.
    30.     Me.DrawLines(e.Graphics)
    31. End Sub
    There is exactly zero change to the drawing code. You now need to attach those event handlers to any PictureBoxes you create at run time, e.g.
    vb.net Code:
    1. Dim pb As New PictureBox
    2.  
    3. AddHandler pb.MouseDown, AddressOf PictureBoxes_MouseDown
    4. AddHandler pb.MouseUp, AddressOf PictureBoxes_MouseUp
    5. AddHandler pb.Paint, AddressOf PictureBoxes_Paint
    The attaching of the event handlers is exactly the same no matter the control or event, e.g. attaching handlers to TextBox.TextChanged or Button.Click events would be exactly the same. When you're done with the controls, you ought to be disposing them and detaching the event handlers too, e.g.
    vb.net Code:
    1. Dim pictureBoxes = myFlowLayoutPanel.Controls.Cast(Of PictureBox)().ToArray()
    2.  
    3. For Each pb In pictureBoxes
    4.     RemoveHandler pb.MouseDown, AddressOf PictureBoxes_MouseDown
    5.     RemoveHandler pb.MouseUp, AddressOf PictureBoxes_MouseUp
    6.     RemoveHandler pb.Paint, AddressOf PictureBoxes_Paint
    7.  
    8.     pb.Dispose()
    9. Next

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width