Results 1 to 17 of 17

Thread: How do you draw on a picturebox outside of the pain event.

  1. #1

    Thread Starter
    New Member
    Join Date
    Aug 2010
    Posts
    6

    How do you draw on a picturebox outside of the pain event.

    Basically Im converting my old VB6 chip8 emulator into Vs2010 version, so far everything works except the drawing routine.

    In Vb6 it was easy, simply

    pict1.line(x1,y1)-(x2,y2),vbwhite, BF

    etc..

    I could write to the picture box directly within a different sub called from main() and also call the form refresh etc.

    In Vb2010 it seems entirely different, you create a graphics object.

    Dim g as graphics

    Then assign it to an object with the create graphics method

    g=picturebox1.creategraphics

    then use g.drawline etc.. <<< this normally goes in the paint event of the object.

    The problem im having is that nothing displays until the paint event, which is not how my code works.

    Basically the emulator procedure framework is:-

    LoadRom
    Initialise stuff
    Emulate
    -Fetch opcodes
    -Interpret
    -Set VxtoVy
    -Set ReturnFromSub
    -DrawRoutine

    As I try to draw on the picture box from within the DrawRoutine sub nothing displays, is there something else needed to cause a draw event to happen?

  2. #2
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: How do you draw on a picturebox outside of the pain event.

    Force it. Me.Invalidate in your emulation loop will force a redraw.

    Painting on a picturebox is an ugly way to do things these days. If you need to do such things, it's easier to just paint on the form itself.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  3. #3

    Thread Starter
    New Member
    Join Date
    Aug 2010
    Posts
    6

    Re: How do you draw on a picturebox outside of the pain event.

    Thanks for the quick reply, Ive inserted me.invalidate into the main interpret procedure but when im debugging and stepping through the code all i see is a form with blank grey box, does this need a doevents call. Im trying to see if the first pixels are displaying at debug time but nothing shows except the grey blank form etc..

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by Jenner View Post
    Painting on a picturebox is an ugly way to do things these days. If you need to do such things, it's easier to just paint on the form itself.
    That's not necessarily true. A PictureBox is optimised for GDI+ and can provide smoother transitions.

    The general principle of GDI+ is very simple:

    1. You store the data that describes the drawing in member variables.
    2. You handle the Paint event, read the data from those member variables and use the Graphics object provided to perform the drawing.
    3. Whenever you want to change the drawing you update the member variables and then call Invalidate and Update or Refresh on the control.

    That's all there is to it, besides the detail of exactly what Graphics methods to call. If you want an example then follow the CodeBank link in my signature and check out my Simple Drawing thread. You'll see there that, each time the user draws a line, the data representing that line is added to a member variable containing all the lines, Invalidate is called to specify what area of the control has changed and Update is called to raise the Paint event. The actual drawing is then done in the Paint event handler. That same principle should be employed no matter what you're drawing.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by jmcilhinney View Post
    That's not necessarily true. A PictureBox is optimised for GDI+ and can provide smoother transitions.
    Really? I always heard it was slower because it was going through another layer of objects.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  6. #6

    Thread Starter
    New Member
    Join Date
    Aug 2010
    Posts
    6

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by jmcilhinney View Post
    That's not necessarily true. A PictureBox is optimised for GDI+ and can provide smoother transitions.

    The general principle of GDI+ is very simple:

    1. You store the data that describes the drawing in member variables.
    2. You handle the Paint event, read the data from those member variables and use the Graphics object provided to perform the drawing.
    3. Whenever you want to change the drawing you update the member variables and then call Invalidate and Update or Refresh on the control.

    That's all there is to it, besides the detail of exactly what Graphics methods to call. If you want an example then follow the CodeBank link in my signature and check out my Simple Drawing thread. You'll see there that, each time the user draws a line, the data representing that line is added to a member variable containing all the lines, Invalidate is called to specify what area of the control has changed and Update is called to raise the Paint event. The actual drawing is then done in the Paint event handler. That same principle should be employed no matter what you're drawing.
    Can you please clarify what you mean by invoking the paint event, heres an example sub which is called from main,

    Code:
    Sub DrawGfx()
    
            Dim G As Graphics
            G = Me.CreateGraphics()
    
            G.FillRectangle(Brushes.Black, 10, 10, 200, 300)
    
            Randomize()
    
            Dim x, y, w, h
            G = Me.CreateGraphics()
            G.Clear(Color.Black)
            x = CInt(Math.Floor((200 - 10 + 1) * Rnd())) + 10
            y = CInt(Math.Floor((300 - 10 + 1) * Rnd())) + 10
    
            w = CInt(Math.Floor((100 - 10 + 1) * Rnd())) + 10
            h = CInt(Math.Floor((200 - 10 + 1) * Rnd())) + 10
            G.FillRectangle(Brushes.White, x, y, w, h)
            Me.Invalidate()
            Me.Refresh()
    
            Label1.Text = Now()
    
            Me.Show()
    
    
    
        End Sub
    When i debug this the rectangle never shows, just a blank form, but if i press a button and event click then this drawing methods works ok, im not sure why. So drawing to the form only seems to work from a event being triggered not by invoking it within a subroutine.

    this works ok:-

    Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim G As Graphics
            G = Me.CreateGraphics()
    
            G.FillRectangle(Brushes.Black, 10, 10, 200, 300)
        End Sub
    how do I synthesize an event so I can draw to the picturebox, because the emulation is determined by the drawing opcode not an event triggered by a button or object etc..

    Hope I've made this clear.
    Last edited by tinmanjo; Aug 25th, 2010 at 12:50 PM.

  7. #7
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: How do you draw on a picturebox outside of the pain event.

    Drawing on a Graphics object, then calling Refresh/Invalidate, will never work. Unlike VB6 (AutoRedraw) .NET Windows Forms don't re-draw the graphics. You need to handle the Paint event or override OnPaint().

  8. #8
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: How do you draw on a picturebox outside of the pain event.

    try this:

    vb Code:
    1. dim img as bitmap
    2.  
    3. Sub DrawGfx()
    4.  
    5.     img = new bitmap(picturebox1.width,picturebox1.height)
    6.     Dim G As Graphics = graphics.fromimage(img)
    7.    
    8.     G.FillRectangle(Brushes.Black, 10, 10, 200, 300)'??? overdrawn in 3 lines from here
    9.  
    10.     Randomize()
    11.  
    12.     Dim x, y, w, h
    13.    
    14.     G.Clear(Color.Black)
    15.     x = CInt(Math.Floor((200 - 10 + 1) * Rnd())) + 10
    16.     y = CInt(Math.Floor((300 - 10 + 1) * Rnd())) + 10
    17.  
    18.     w = CInt(Math.Floor((100 - 10 + 1) * Rnd())) + 10
    19.     h = CInt(Math.Floor((200 - 10 + 1) * Rnd())) + 10
    20.     G.FillRectangle(Brushes.White, x, y, w, h)
    21.    
    22.     picturebox1.image = img
    23.  
    24.     Label1.Text = Now()
    25.  
    26.     'Me.Show()???
    27.  
    28. End Sub

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How do you draw on a picturebox outside of the pain event.

    Have you read my CodeBank thread yet? I created specifically so that we wouldn't have to keep creating the same examples over and over.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: How do you draw on a picturebox outside of the pain event.

    You should just re-draw everything in the Paint event, basically. Why would you even want to draw anything outside of the Paint event?

    P.S. @.paul.
    1. CInt(Math.Floor(x)) is the same as CInt(x).
    2. You should probably use the Random object instead.
    3. You should dispose the Graphics object
    4. You should give a type to x, y, w, and h.
    But I guess it's just an example anyways.

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by minitech View Post
    CInt(Math.Floor(x)) is the same as CInt(x)
    Nope.
    Code:
    MessageBox.Show(CInt(Math.Floor(1.5)).ToString())
    MessageBox.Show(CInt(1.5).ToString())
    CInt rounds, so if you want to truncate then CInt alone won't do.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12

    Thread Starter
    New Member
    Join Date
    Aug 2010
    Posts
    6

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by minitech View Post
    You should just re-draw everything in the Paint event, basically. Why would you even want to draw anything outside of the Paint event?
    Thanks for your tips, this was a really crude example though and im still quite new to .net but vb6 im proficient in, basically the reason I need to paint out of the paint event is because the Chip8 emulator interprets a drawing opcode called DxyN, when this opcode is processed the picturebox needs an Xor drawn to it, so what ever was there is overwritten, and then a certain regiter called reg(&hf) is set to 1 or 0 depending on the Xor, the problem with waiting for the paint event is that the chip8 interprets several more opcodes while waiting for the damn paint event to occur which results in a time delay which throws the whole timing of the drawing process out of sync, in fact the only way to paint directly is from a button event or some similar.

    Have you read my CodeBank thread yet? I created specifically so that we wouldn't have to keep creating the same examples over and over.
    I have read your document thread, but as stated this only shows you have created objects that are triggered by an event (button click etc...) like trying to paint a bmp to the picturebox still will not work until the main form has finished it main procedure.

    To clarify what I mean ive included a template of the emulator:

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
            Init()
            Emulate()
    
        End Sub
    
        Sub Init()
            
        End Sub
    
        Sub Emulate()
            FetchOps()
            Interpret()
    
        End Sub
    
        Sub FetchOps()
            'MsgBox("FetchOps")
        End Sub
    
        Sub Interpret()
            'MsgBox("Interpret")
    
            DrawGfx()
            DoSomething()
    
        End Sub
    
        Sub DoSomething()
    
            For i = 1 To 1000
                For p = 1 To 100
                Next p
            Next i
    
            
    
        End Sub
        Sub DrawGfx()
            Dim G As Graphics
            Dim buffer As Bitmap
            Dim MyBrush As SolidBrush
    
            buffer = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    
            G = Graphics.FromImage(buffer)
            MyBrush = New SolidBrush(Color.Red)
            G.FillEllipse(MyBrush, 0, 0, PictureBox1.Width, PictureBox1.Height)
    
            PictureBox1.Image = buffer
    
    
    
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            
        End Sub
    
    End Class
    As you can see the paint event is never invoked until after the DoSomething() procedure has finished, this is what i mean by timing problems, because until the main() has finished the paint event never happens. So the DoSomething could be a long loop and cause considerable delay until the drawing actually happens.
    Last edited by tinmanjo; Aug 26th, 2010 at 04:50 AM.

  13. #13
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: How do you draw on a picturebox outside of the pain event.

    It's already been mentioned several times but apparently not clearly enough. Just add PictureBox1.Refresh at the end of your DrawGfx sub. Or put it in your button click sub, if that's where you want to trigger repainting.

    The point is that Refresh causes instant repainting (of the whole control). So it will happen before your DoSomething routine starts.

    Invalidate alone means "put the Paint task in a queue". Repainting takes place once the process is idle, so in your case it would happen after DoSomething.

    Invalidate followed by Update has a similar effect to Refresh, but it gives you more flexibility. You can invalidate only the rectangles that need to be changed (and there might be dozens of them, e.g. in a game with animated sprites). The system optimizes drawing so that all invalidated areas of the control are combined, and the affected pixels are redrawn only once. That happens when you perform Update, or when the process has nothing better to do, whichever comes first. If you Refresh each sprite individually, on the other hand, it could slow everything down drastically: changing actual pixels on the screen is much slower than changing bits in memory.

    hope this helps, BB
    Last edited by boops boops; Aug 26th, 2010 at 06:07 AM.

  14. #14
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: How do you draw on a picturebox outside of the pain event.

    CInt rounds, so if you want to truncate then CInt alone won't do.
    Now I know why my integer square root function wasn't working! Thanks! (Rep+ after a while)

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How do you draw on a picturebox outside of the pain event.

    You're determined to do what you want to so you're not actually reading what's being posted:
    Quote Originally Posted by jmcilhinney
    Update is called to raise the Paint event
    We are telling you, ABSOLUTELY, that you do NOT draw outside the Paint event handler or OnPaint method. Accept that and do as we say or keep fighting it and you'll never achieve your aim.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  16. #16
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by jmcilhinney View Post
    You're determined to do what you want to so you're not actually reading what's being posted:We are telling you, ABSOLUTELY, that you do NOT draw outside the Paint event handler or OnPaint method. Accept that and do as we say or keep fighting it and you'll never achieve your aim.
    But jmc, there is no objection is there to defining a new bitmap, using a derived Graphics to draw on it, and then displaying the result in a PictureBox -- see post #12? Of course it should be done correctly (tinmanjo, please dispose of the Graphics after use!). If I'm not mistaken, the PictureBox.Image gets painted only after the Paint Event fires, so the same considerations about Invalidate/Refresh/Update apply.

    BB

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How do you draw on a picturebox outside of the pain event.

    Quote Originally Posted by boops boops View Post
    But jmc, there is no objection is there to defining a new bitmap, using a derived Graphics to draw on it, and then displaying the result in a PictureBox -- see post #12? Of course it should be done correctly (tinmanjo, please dispose of the Graphics after use!). If I'm not mistaken, the PictureBox.Image gets painted only after the Paint Event fires, so the same considerations about Invalidate/Refresh/Update apply.

    BB
    No, that's fine, but drawing on an Image and drawing directly on a control are two different things. An Image is not a UI element and has no events. You can draw on an Image whenever you like.

    The main difference between drawing on an Image and drawing on a control is that drawing on an Image is permanent, so you can't change it once it's done. Because controls get repainted over and over, changing what you've drawn on a control is a simple matter of waiting until the next Paint event, which may mean forcing one yourself, and then doing the new drawing.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

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