Q: Persistent Graphics on Form or PicBox: a real pain!!!

Hi all,

this is kind of a follow up on 2 earlier threads I started. This time the question is a bit more fundamental. It concerns replacement of the persistent graphic methods in VB6 with the Picbox_paint persistent graphics in VB.net.

Whatever I try, and whatever help I ask I simply cannot perform the following task: (heavily simplified)

I have a VB6 program that reads inputvalues (X and Y) from an A/D convertor. It continuously reads values at ~5 per second and plots them as vectors. Aim is to visualize outliers and get a quick view of grouping of the outliers. I definitely need to implement exacly this functionality in VB.net. After a number of days, millions or even billions of vectors are drawn, with only a few outliers. In VB6, I had made a graphic in a picbox1 and simply drew each vector on top of it:

dim x,y,i

For i=1 to 10000000000

x= fyGetX 'some Fn that gets X

y= fyGetY

picbox1.line(0,0)-(x,y), vbblack

'after this the x and y values are disgarded because they are not stored.

next i

Now comes the important part: if I switched on the PicBox1 autoredraw property, than the graphics would be persistent and after being covered by another form they would be automatically refreshed. However, in VB.net autoredraw is no longer supported. Instead we are tought to do all graphics in the paint event of the picbox. That works BUT IT IS ONLY PERSISTENT if I redraw all the billions of vectors from within this paint event. In other words, I have to remember everything I have ever drawn over the many days of running the program. Which is enormously slow AND requires me to store all X and Y values just for repainting purposes. My program writes many more parameters than just x and y, and storing so many data is not an option.

Does this mean that we have really lost this functionality Can anyone explain to me how the old VB6 persistent graphics worked, inside So that I can maybe try to recover from this 'improvement'

Thanks Kesim



Answer this question

Q: Persistent Graphics on Form or PicBox: a real pain!!!

  • Samer Selo

    All right!! for the first time I am starting to see light at the end of the tunnel (has costed me many days).

    That discussion by John has actually yielded persistent graphics in selfdefined cartesian coordinate system!! Thanks.

    BUT to show the graphics with this approach is unbelievably slow, in my approach, because I have to draw millions of line pieces and after each one want to see an update. The update is by

    <Form>

    Dim myGraphics As Graphics

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim penred As New Pen(Color.Red, 0.1) 'this routine: code stolen from Johns example mixed with mine

    PicBox3.Image = New System.Drawing.Bitmap(PicBox3.ClientRectangle.Width, PicBox3.ClientRectangle.Height, Imaging.PixelFormat.Format32bppRgb)

    PicBox3.Image = New System.Drawing.Bitmap(PicBox3.ClientRectangle.Width, PicBox3.ClientRectangle.Height)

    myGraphics = Graphics.FromImage(PicBox3.Image)

    Dim mx3 As New Matrix((PicBox3.Width / 50), 0, 0, (-PicBox3.Height / (4 - -1)), 0, 0) 'THIS scales X 0 to 50, Y -1 to 4

    mx3.Translate(0, -4) 'Move 0,0 to mid left

    myGraphics.Transform = mx3

    End Sub

    'and THIS is what gets so slow:

    Private Sub BtnCalculation01_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnCalculation01.Click

    Dim i As Integer

    Dim penorange As New Pen(Color.Orange, 0.001

    For i = 0 To 50000000

    myGraphics.DrawLine(penorange, 0, 0, i/1000000, sin(i/1000000)) 'just an example formula to show the idea. it actually

    'plots the results of a simulation

    PicBox3.Refresh() 'THIS step takes forever because it is executed 50 million times

    Next

    End Sub

    Anybody with any ideas to resolve this

    Thanks, Kesim.


  • Ute

  • Jessie Zhao

    Hi Kesim,

    Sorry for the late reply I've been out of action due to some knee surgery. Happily Dman1 posted a link to my other thread where I spent some time documenting the techniques you needed.

    Thank you for posting your code. I cut and pasted it into project and fired it up. I see what you mean about the slow speed draws. This is seems to be caused by the picturebox coping the bitmap from memory to its display surface. My guess would be that the larger the bitmap the slower the draws would become.

    There's a couple of things you can do to overcome this problem, but from your source code I don't see any need to make the solution too complex. If you're going to draw everthing in a loop, then the application will be unable to respond to external paint events (requests to repaint part or all of the application in Windows). With this in mind you can simply draw on the picture box itself as well as a bitmap in memory. Once the loop completes you can copy the bitmap from memory to the picturebox.image property. Using this technique will speed things up but it will also result in some ugly looking forms if a user starts messing with other applications that require a repaint of your application.

    Private Sub cmdNonPersist_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdNonPersist.Click

    '3)----The next lines are needed for NON-persistent graphics only

    'Create an off screen bitmap in memory
    Dim myOSB As New System.Drawing.Bitmap(PicBox1.ClientRectangle.Width, PicBox1.ClientRectangle.Height, Imaging.PixelFormat.Format32bppRgb)

    Dim myGraph As Graphics

    'Assign a graphics object to my bitmap in memory
    myGraph = Graphics.FromImage(myOSB)

    'clear my bitmap in memory setting its background color to the same color as my picture box
    myGraph.Clear(PicBox2.BackColor)

    grafiekNonPersist = PicBox2.CreateGraphics

    '------HERE THE GRAFIEK IS SET TO POINT TO picbox1.graphics, which is NON-persistent

    grafiekNonPersist.Transform = MT 'rescale the stuff
    myGraph.Transform = MT 'rescale the off screen image as well

    For i As Long = 1 To 10000
    grafiekNonPersist.DrawLine(penred, data(i - 1, 0), data(i - 1, 1), data(i, 0), data(i, 1)) 'THIS LINE and the next are all it takes

    'make a copy of the line on my off screen bitmap
    myGraph.DrawLine(penred, data(i - 1, 0), data(i - 1, 1), data(i, 0), data(i, 1))

    Next

    'copy the off screen bitmap to my picture box for persistance.
    PicBox2.Image = myOSB

    End Sub

    Johnny


  • John Lieurance

    Interesting; but I think if you drop a picturebox on a form, doc it to form fill, create a bitmap and assign it to the picturebox.image property of the picture box upon the form load event you should get what you need. Realatively simple; however, very different from VB6.


  • Ashish Saxena

    THIS is what I came up with in the end. It works OK but I am open to any suggestions to further improve it.

    Thanks for all who helped.

    Kesim

    Public Class Form1

    'KEES example persistent en non-persistent graphics in VB.net

    'Idea is this: in VB6, you could just draw on a picbox, and setting

    'autoredraw was sufficient to get persistent graphics.

    'In .Net, you have to do that differently.

    '****First, you can graph in a picbox by directly plotting to the graphics object

    'resulting in NON-PERSISTENT graphics.

    '****Second, you can plot to a BitMap that is within a PicBox, and that will yield

    'persistent plots. However, you need to call the refresh method to update the

    'screen after each plotted section.

    'NOTE that a reference to System.Drawing.Drawing2D must be set!!!

    'Form contains PicBox1 and PicBox2 (equal size) and 3 cmdButtons

    Dim grafiekPersist As Graphics 'accesible from all subroutines

    Dim grafiekNonPersist As Graphics 'accesible from all subroutines

    'now just define some things

    Dim penred As New Pen(Color.Red, 0.001)

    Dim Xmax As Single = 10000 'some scaling parameters to make Cartesian coordinates

    Dim Ymin As Single = -1.1 'between 0 < X < 10000 and -1.1 < Y < 1.3, par example

    Dim Ymax As Single = 1.3

    Dim MT As Matrix

    Dim data(10000, 1) As Single

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    'prepare scaling matrix for Cartesian scale

    Dim transforMatrix As New Matrix((PicBox1.Width / Xmax), 0, 0, (-PicBox1.Height / (Ymax - Ymin)), 0, 0)

    transforMatrix.Translate(0, -Ymax) 'Move 0,0 to mid left

    MT = transforMatrix 'MT is globally accesible

    'now prepare some data

    For i As Single = 0 To 10000

    data(i, 0) = i

    data(i, 1) = Math.Sin(i / 100)

    Next

    End Sub

    'Example 1: persistent, SLOW. A MINIMAL version that refreshes after each line so it is very slow

    Private Sub cmdPersist_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPersist.Click

    '1)----The next lines are needed for persistent graphics only

    '------create a bitmap in memory and display it in the picture box.

    PicBox1.Image = New System.Drawing.Bitmap(PicBox1.ClientRectangle.Width, PicBox1.ClientRectangle.Height, Imaging.PixelFormat.Format32bppRgb)

    PicBox1.Image = New System.Drawing.Bitmap(PicBox1.ClientRectangle.Width, PicBox1.ClientRectangle.Height)

    '------this latter statement is needed to make it white

    grafiekPersist = Graphics.FromImage(PicBox1.Image) 'HERE THE GRAFIEK IS SET TO POINT TO THE IMAGE, which is persistent

    grafiekPersist.Transform = MT 'rescale the stuff

    For i As Long = 1 To 10000

    grafiekPersist.DrawLine(penred, data(i - 1, 0), data(i - 1, 1), data(i, 0), data(i, 1)) 'THIS LINE and the next are all it takes

    PicBox1.Refresh()

    Next

    End Sub

    'Example 2: persistent, FAST

    Private Sub cmdPersistFast_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPersistFast.Click

    '2)----The next lines are needed for persistent graphics only

    '------create a bitmap in memory and display it in the picture box.

    PicBox1.Image = New System.Drawing.Bitmap(PicBox1.ClientRectangle.Width, PicBox1.ClientRectangle.Height, Imaging.PixelFormat.Format32bppRgb)

    PicBox1.Image = New System.Drawing.Bitmap(PicBox1.ClientRectangle.Width, PicBox1.ClientRectangle.Height)

    '------this latter statement is needed to make it white

    grafiekPersist = Graphics.FromImage(PicBox1.Image) 'HERE THE GRAFIEK IS SET TO POINT TO THE IMAGE, which is persistent

    grafiekPersist.Transform = MT 'rescale the stuff

    For i As Long = 1 To 10000

    grafiekPersist.DrawLine(penred, data(i - 1, 0), data(i - 1, 1), data(i, 0), data(i, 1)) 'THIS LINE and the next are all it takes

    If i Mod 50 = 0 Then PicBox1.Refresh() 'take this line out for even faster response

    Next

    PicBox1.Refresh()

    End Sub

    'Example 3: NON-persistent, very fast

    Private Sub cmdNonPersist_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdNonPersist.Click

    '3)----The next lines are needed for NON-persistent graphics only

    grafiekNonPersist = PicBox2.CreateGraphics

    '------HERE THE GRAFIEK IS SET TO POINT TO picbox1.graphics, which is NON-persistent

    grafiekNonPersist.Transform = MT 'rescale the stuff

    For i As Long = 1 To 10000

    grafiekNonPersist.DrawLine(penred, data(i - 1, 0), data(i - 1, 1), data(i, 0), data(i, 1)) 'THIS LINE and the next are all it takes

    Next

    End Sub

    End Class


  • shitbhar

    John, could you elaborate a bit on that Or point me to an info source on that

    Thanks, Kesim


  • joeycalisay

    OK. After hours and hours of further searching I found out that THIS IS SIMPLY NO LONGER POSSIBLE!!!

    It is a fundamental choice of vb.net to no longer support this type of things. Workarounds may be perceived by grabbing all graphics into a bitmap that has to be saved by the user, but this of course is not the real thing (because it does not allow later scaling etc).

    See the excellent paper on this by sp!ke in vbcity forum:

    http://vbcity.com/forums/topic.asp tid=128254

    again, too bad. Why doesn't MS simply offer us the choice

    kesim


  • Q: Persistent Graphics on Form or PicBox: a real pain!!!