gpugelni

Hi all,

How to make simple vertical bargraph with panel or picture box, which will take data (byte) from comm port and plot value (com port working -Thanks Carsten!)

I was looking in help but I can find sample, I do not wont to use progresbar, becouse I can draw cross lines in it.

Thanks in advance,




Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi,

I was found this but when it is started form1 is empty...

Public Class Form1

Dim myBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Red)

Dim formGraphics As System.Drawing.Graphics

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

formGraphics = Me.CreateGraphics()

formGraphics.FillRectangle(myBrush, New Rectangle(0, 0, 200, 300))

myBrush.Dispose()

formGraphics.Dispose()

End Sub

End Class






Re: Visual Basic Express Edition Vertical bargraph

SJWhiteley

I would recommend you make a usercontrol.

Add Minimum and Maximum properties, a Value property to it, and draw a fill rectangle based on those values in the Paint event of the control. This is the fundamental starting point for generating such functionality (apart from the fact that I'm a real UserControl freak - encapsulate! encapsulate!)...from here you can start adding tick marks, gradient brush, etc. - you should be able to generate something like this here.






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi,

I still do not know why sample from MSDN help do not work.........

There is lot of data but always something is missing .






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi,

I was find this simple bar, but it goes only in right and down direction. How to make it that it goes up

Public Class Form1

Dim ProgValue As Integer

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

ProgValue += 30

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

Dim myPen As New Pen(Color.Black)

myPen.Width = 2

Me.CreateGraphics.DrawRectangle(myPen, New Rectangle(10, 10, 500, 30))

If ProgValue < 496 Then

Me.CreateGraphics.FillRectangle(Brushes.Red, New Rectangle(12, 12, ProgValue, 26))

End If

End Sub

End Class

Thanks in advance,






Re: Visual Basic Express Edition Vertical bargraph

SJWhiteley

Simple Math. The windows coordinates start from the top left of the control (0,0) and increase as you go down and right. To show a more 'normal' response, you will have to invert the Y axis coordinates. Obviously you are transforming from real world values to pixels.

Perform the math, or use the graphics transform methods (personlly, I perform the math, as there are a few quirks with the transformation functions, and it's significantly slower to plot).






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Well for you maybe is simple but for me and milions isn't. Can we see some examples please..






Re: Visual Basic Express Edition Vertical bargraph

SJWhiteley

You need to determine the location of the rectangle (top and bottom) in pixels.

Dim value As Single = 45.0F

Dim euMinimum As Single = -100.0F

Dim euMaximum As Single = 100.0F

Dim h As Single = ClientSize.Height

Dim euRange As Single = euMaximum - euMinimum

Dim y0 As Single = h * (1.0F + euMinimum) / euRange

Dim y1 As Single = h * (1.0F - (value - euMinimum) / euRange)

If y0 > y1 Then ' Swap them

Dim t As Single = y1

y1 = y0

y0 = t

End If

Now you have the top and bottom, you can fill that area using FillRectangle. I just set a value of 45 as an example, and the Engineering Units range to +-100. This is high school math (perhaps you aren't quite there, my apologies if so), but these a fundamental concepts.

Edit: Corrected a typo, for those who need to know the simplest, most versatile and best way do it: put the above in the paint event of the form, panel or UserControl.




Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Thanks !






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi.

Is this code ok

What means F in 45.0F

Public Class Form1

Dim value As Single = 45.0F

Dim euMinimum As Single = -100.0F

Dim euMaximum As Single = -100.0F

Dim h As Single = ClientSize.Height

Dim euRange As Single = euMaximum - euMinimum

Dim y0 As Single = h * (1.0 + euMinimum) / euRange

Dim y1 As Single = h * (1.0 - (value - euMinimum) / euRange)

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

If y0 > y1 Then ' Swap them

Dim t As Single = y1

y1 = y0

y0 = t

Me.CreateGraphics.FillRectangle(Brushes.Blue, New Rectangle(100, 100, 20, t))

End If

End Sub

End Class






Re: Visual Basic Express Edition Vertical bargraph

SJWhiteley

Put your calculations for pixel position in the paint routine.

Use the Y0 and Y1 variables as parameters for your rectangle (that's the whole point of calculating them).






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi,

Public Class Form1

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

Dim value As Single = 45.0F

Dim euMinimum As Single = -100.0F

Dim euMaximum As Single = -100.0F

Dim h As Single = ClientSize.Height

Dim euRange As Single = euMaximum - euMinimum

Dim y0 As Single = h * (1.0 + euMinimum) / euRange

Dim y1 As Single = h * (1.0 - (value - euMinimum) / euRange)

If y0 > y1 Then

Dim t As Single = y1

y1 = y0

y0 = t

End If

Me.CreateGraphics.FillRectangle(Brushes.Blue, New Rectangle(100, y0, 40, y1))

End Sub

End Class

********************************************************************************************

With this code I can get only overflow error, only if I change eu minimum = 10.0F, then I get bar but then value doesn't change its size and it is stack on the bottom of form1..........................

Debuger says that I can divide with zero,if euminimum is 100 (nothig new...).






Re: Visual Basic Express Edition Vertical bargraph

Carsten Kanstrup

gpugelni

The BarGraphs of SJW looks very good and his method is very generably useable, but for a start you can try to simplify things and actually get quite close.

Since you want to display a byte, you know that the value is between 0 and 255, so if you make your bargraph 256 pixel high you certainly simplify things a lot!

1) Use an image processing program to draw a .gif or .bmp image (I used .gif) 256 pixel high and e.g. 20 pixel wide and fill it with a nice gradient from green at the button over yellow to red and perhaps white at the top.

2) From the tools menu, drag a pictureBox onto your form and select the Size property to 20; 256 and be sure that the SizeMode is Normal (no resizing).

3) Select the BackgroundImage property and Import your .gif background (press the Import button). You should now see the entire gradient in your picture box.

I made the following small test program:

Public Class Form1

Dim InputValue As Integer = 0

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim barGraphics As Graphics = PictureBox1.CreateGraphics

PictureBox1.Refresh()

barGraphics.FillRectangle(Brushes.Black, 0, 0, 20, 256 - InputValue)

barGraphics.Dispose()

InputValue = InputValue + 16

If InputValue > 256 Then

InputValue = 0

End If

End Sub

End Class

Each time I press Button1, the bargraph gets 16 pixel higher until it wraps around. You should of course use your received byte as input (InputValue) instead and activate the routine when you receive your data from the serial port. If you also add a numerical display, you don't need any scale marks on the bargraph.

As you can see, three lines of code is everything you need if you simplify things. The only disadvantage is that the refresh creates a little flicker at the top of the display, but you can use something like this for a start and then improve it later.

Peoply usually make the mistake that they convert to human (engineering) values too soon. When you use an AD converter, you will always scale the amplification before the converter in such a way that you utilize the full range as good as possible. For example, it doesn't matter if the full range of a weight scale is one ton or one gram. The numerical value from the AD converter is in the same range. If you even left shift the data, it doesn't matter if the AD converter is e.g. 12 bit or 16 bit, so you don't need to take all this into consideration when you make your program. You can use these data directly for digital regulators, bargraph displays etc. There is no reason to convert the data to anything else until you want to display the numerical result. This speed up things considerably. A digital regulator may have to make hundreds of calculations per second, but approximately 4 values per second is enough for a display.

EDIT

Sorry, I missed the Dispose() call when I made the post (and program). You should always clean up a graphics object created with CreateGraphics and not let this job up to the automatic garbage collection. The missed dispose call is now inserted in the above code.





Re: Visual Basic Express Edition Vertical bargraph

SJWhiteley

Typo: euMaximum should be +100 (not -100). Remember, treat any code you see on the internet as full of bugs, and check every line .

Do not use creategraphics - it's unnecessary (it is seen a lot in the forums - particularly without a dispose call - and works for demonstration purposes as with most examples but you wouldn't use it in practice, generally). In this case you can use the e.Graphics parameter passed to the paint routine, instead.

The F symbol means 'single' (I think it comes from it being a Float - as in Floating Point Value). It's an old habit I have when declaring real values. You will probably see it a bit when declaring constants in a calculation: the constant by default is a double, which will give a warning that you can't convert a double to a single (which probably means you have Option Explicit not set to On, if you don't get that warning).

Additionally, remember that Y0 and Y1 are the top and bottom of the bar. The rectangle requires a TOP and a HEIGHT. So the last parameter of the rectangle should be (Y1 - Y0), the BOTTOM location minus the TOP location.

Your next step after this is to move the value variable outside the paint routine (make it some kind of global variable): update it when you receive data on your serial port. Once that value has been updated you can call the Invalidate method on your form (since that's where you are drawing your bar).

Always convert to engineering units as soon as possible: if your serial port receives a temperature value (for example), but comes in as a byte, convert it immidiately to a single value. This may not seem to be necessary with simple programs, but as your program grows and you are debugging it, knowing that what you see - wherever you are in your program - is reflecting the real world helps considerably. Unit conversion is one of the biggest problems that I come in to fix (the typical 'this value doesn't look right' issue).

A useful debugging step will probably be to put a slider on your form and set the value variable with the slider: when the slider moves, set the value and invalidate the form. Also, perhaps look at the DoubleBuffered property of the form to prevent any flickering.

(note: the invalidate method on an control will cause the control to receive a 'Paint Yourself' message - this will call the Paint event for that Control to fire. It can also be called from different threads, since no mashalling is necessary, it's a nice way to get a control to update itself from a thread timer or even the serial port event, as it appears you may be doing. Just take care with the rate that data is received as you can use a lot of CPU power updating the form unnecessarily).






Re: Visual Basic Express Edition Vertical bargraph

gpugelni

Hi,

Jupiiii,,, thanks Carsten ! Like I like to say: Simply things, the best things!