dcsimg
Results 1 to 5 of 5

Thread: [RESOLVED] User Drawn Lines in a PictureBox (Color/width)

  1. #1

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    7,309

    Resolved [RESOLVED] User Drawn Lines in a PictureBox (Color/width)

    Okay, so I cheated (and didn't write the following code--stole it from another post from a few years back)...but, it is not quite what I want.

    Code:
    Option Explicit
    
    Dim x1 As Integer
    Dim y1 As Integer
    Dim x0 As Integer
    Dim y0 As Integer
    Dim isDrawing As Boolean
    Dim isStraight As Long
    
    
    'Private Const DrawColor = vbBlack
    Private Const DrawColor = vbRed
    Private Sub Form_Load()
        Picture1.AutoRedraw = True
    End Sub
    
    
    Private Sub Picture1_Mousedown(Button As Integer, Shift As Integer, X As Single, Y As Single)
        isDrawing = True
        If Shift And 2 Then isStraight = True
        x1 = X
        y1 = Y
        x0 = X
        y0 = Y
    End Sub
    
    
    Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
        If isDrawing Then
            If isStraight Then
                Picture1.Line (x0, y0)-(x1, y1), Picture1.BackColor
                Picture1.Line (x0, y0)-(X, Y), DrawColor
            Else
                Picture1.Line (x1, y1)-(X, Y)
                End If
                x1 = X
                y1 = Y
        End If
    End Sub
    
    
    Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
        isDrawing = False
        isStraight = False
    End Sub
    So, what I want is to be able to change first, the width of the line the user draws on a picturebox (the line the code above draws is not very wide--would like something like twice that width).
    Next, I want to be able to change the line color (using a variable, I'd assume, changeable by a control click event).

    I've looked at the line control, but it seems that it applies only to IDE work, not run-time by a user.

    This way, a user can draw one path in once color, and another path in another color.

    Can anyone assist in both my problems (line width AND variable colors (one color for each separate line the user draws)?

    Sam

  2. #2

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    7,309

    Re: User Drawn Lines in a PictureBox (Color/width)

    Well, got the color (thanks to MSDN) ~smile....Forecolor of the picturebox.

    Now, width?

  3. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    18,652

    Re: User Drawn Lines in a PictureBox (Color/width)

    The DrawWidth property of the picturebox should do it. Set it higher than its default of 1.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    7,309

    Re: User Drawn Lines in a PictureBox (Color/width)

    Yeah...just found it...thanks anyway LaVolpe....just returning to mark as Resolved. Simple Persistence and reading!

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,744

    Re: User Drawn Lines in a PictureBox (Color/width)

    Quote Originally Posted by SamOscarBrown View Post
    Well, got the color (thanks to MSDN) ~smile....Forecolor of the picturebox.
    ...
    That is one way to do it. The code you posted also shows you another way, i.e. you pass the color you want to draw to the Line command.
    The code you posted will draw a straight red line from the start point to the point you're dragging if you hold the Control Key down when you do the initial mouse down.
    You see it passes the color Red (vbRed) as the second argument to the Line statement. If passes BackColor as the color parameter of the Line statement before that to do a destructive "erase" of the previously drawn straight line.

    So, you could have the color in a variable and pass it at the end of your Line statement to draw different colored lines, without changing the ForeColor of the picturebox.

    Since the original code draws the straight line in the same drawing context (AutoRedraw = True), it is destructive, i.e. it is wiping out bits of your drawing as it "erases" the previous instances of the straight line as it draws. To avoid destroying the previous drawn parts, the temporary drawing should be done in the temporary context, AKA the screen context (AutoRedraw = False). This only draws on the screen area of the picturebox, not in the memory context of the AutoRedraw buffer.

    Below is a modified version of the code that does this.
    If you select the straight line option by holding the Ctrl-Key when you do the initial mouse down, it set AutoRedraw = False, so you don't draw these temporary instances of the straight line in your permanent (AutoRedraw) drawing buffer.
    Then when you release the mouse button, it restores the drawing state to draw in the AutoRedraw memory context, and draws the final line (the last straight line drawn) again, but this time it becomes a part of your persistent drawing buffer (the AutoRedraw memory buffer).

    Because you draw the final line in the AutoRedraw buffer, the buffer is refreshed to the screen so you see your complete picture, all the previously drawn lines, with the new added straight line.
    Code:
    Option Explicit
    
    Dim x1 As Integer
    Dim y1 As Integer
    Dim x0 As Integer
    Dim y0 As Integer
    Dim isDrawing As Boolean
    Dim isStraight As Long
    
    
    'Private Const DrawColor = vbBlack
    Private Const DrawColor = vbRed
    Private Sub Form_Load()
        Picture1.AutoRedraw = True
    End Sub
    
    
    Private Sub Picture1_Mousedown(Button As Integer, Shift As Integer, X As Single, Y As Single)
        isDrawing = True
        If Shift And 2 Then
          isStraight = True
          Picture1.AutoRedraw = False 'Change to drawing straight line in the screen context
        End If
        
        x1 = X
        y1 = Y
        x0 = X
        y0 = Y
    End Sub
    
    
    Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
        If isDrawing Then
            If isStraight Then
    '            Picture1.Refresh
                Picture1.Line (x0, y0)-(x1, y1), Picture1.BackColor
                Picture1.Line (x0, y0)-(X, Y), DrawColor
            Else
                Picture1.Line (x1, y1)-(X, Y)
                End If
                x1 = X
                y1 = Y
        End If
    End Sub
    
    
    Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
        If isStraight = True Then
          Picture1.AutoRedraw = True   'Turn drawing into the memory context back on
         ' Picture1.Line (x0, y0)-(X, Y), DrawColor  'Draw the final line in the memory context
        End If
        isDrawing = False
        isStraight = False
    End Sub
    Because we're drawing to the screen in this situation, it looks like we're still wiping out the previous drawing, because the screen isn't refreshed from the AutoRedraw buffer unless we change the AutoRedraw buffer, or cause the screen to need to refresh from the AutoRedraw buffer (i.e. drag a window across it, or move the window partially offscreen and back on, or minimize and reshow the window).

    As written, this example does the first option. When the mouse button is release (MouseUp) we change the AutoRedraw buffer by turning the AutoRedraw context back on (AutoRedraw = True), and draw the final straight line again, which draws in the AutoRedraw buffer and triggers an update (by invalidating the picturebox display). The drawing looks like it is being wiped out as we draw the straight line, but as soon as we mouse up and draw the final version of the straight line in the buffer, the buffer is drawn to the screen and we see the completed result, so all the "wiped out" drawing appears to have repaired itself.

    We do have the option to tell VB to update the screen from the AutoRedraw buffer using two different calls, the Invalidate call or Refresh call.
    You would use Invalidate in the case where you modified the AutoRedraw buffer outside of the normal VB methods of drawing, i.e. using the Windows API do do the drawing, bitblt being one of the more common examples.
    If you bitblt an image into a portion of the picturebox, with AutoRedraw set True, this modifies the memory context of the drawing, but VB is unaware that you've done this, so won't transfer the memory context to the screen context so you won't see the result of the bitblt until something causes VB to update the screen from the AutoRedraw buffer. Calling Invalidate is one thing that will cause that to happen, but it is a delayed effect. It is just a notification to VB that the window needs to be updated, and VB will do this later when it processes Windows events and sees that an update needed event has been flagged.

    Calling Refresh doesn't have this delay. It will update the window from the AutoRedraw Buffer when you call Refresh, before continuing with the lines of code that follow the call. This is useful in a situation like we have here. If we're drawing temporary things to the screen that appear to wipe out the existing drawing, we might want to refresh the screen from the AutoRedraw Buffer before each stage of the temporary drawing. Doing a Refresh, is essentially erasing the temporary drawing, and we then redraw the temporary drawing "over top" of the persistent drawing.
    Since doing a Refresh is erasing the temporary drawing, we don't need the line that draws with the backcolor to "erase" the line.
    To see this in action, (after seeing the temporary wipe out version), replace the drawing of the erase line with a call to Refresh (uncomment the Picture1.Refresh line, and comment out the first Line command that follows it). You will see that it looks much better since you don't see the temporary wiping out effect (you should draw a bunch of doodles first without the Ctrl-key pressed so you have some "background" drawing to wipe out).
    Last edited by passel; Aug 5th, 2018 at 10:23 PM.

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width