Blank string to number

  • Thread starter Thread starter C
  • Start date Start date
C

C

In VB6, CSng("") was 0. CSng(" ") was also 0. This does not work in
VB.net. Is there a simple way around it?

What is the lower right corner of a form? Me.Width is fine, but
Me.Height goes below the corner.

Thanks.
 
TryParse will tell you whether the conversion you are attempting will work
or not.http://msdn.microsoft.com/en-us/library/26sxas5t.aspx

But it won't do the conversion right. Will it?

Looks like "Val" will work on blanks and null string.
To get positions on a form within the border and menu rows etc, use the
form's ClientSize property.http://msdn.microsoft.com/en-us/library/9278sfx2.aspx

Thanks.

Is there a simple way to do Form1.Cls? I cannot put this in Form_Paint
or it will always paint the same. I will have to use a frmImage to
plot things on, and there is no simple way I know of to erase things
on it. Do I need a New Bitmap every time? Thanks.
 
C said:
But it won't do the conversion right. Will it?

The second parameter to TryParse will have the result of parsing, if the
function returns true.
Looks like "Val" will work on blanks and null string.


Thanks.

Is there a simple way to do Form1.Cls? I cannot put this in Form_Paint
or it will always paint the same. I will have to use a frmImage to
plot things on, and there is no simple way I know of to erase things
on it. Do I need a New Bitmap every time? Thanks.

If I understand your question, you are drawing an image in your paint
event handler. If the image is the same image every time, then no, you
just keep it at the class level and redraw it using the graphics object
of the PaintEventArgs, calling graphics.DrawImage. If you always want
an image drawn as large as possible, then you could just add the image
as the backgroundimage of the form, and set the backgroundimageformat
property as appropriate.
 
The second parameter to TryParse will have the result of parsing, if the
function returns true.


If I understand your question, you are drawing an image in your paint
event handler.  If the image is the same image every time, then no, you
just keep it at the class level and redraw it using the graphics object
of the PaintEventArgs, calling graphics.DrawImage.  If you always want
an image drawn as large as possible, then you could just add the image
as the backgroundimage of the form, and set the backgroundimageformat
property as appropriate.

I am having difficulties understanding VB.net terminology. The code I
have written is appended below. It works, but is probably quite
inefficient, and is not in accordance with good programming
practices.

I will try to improve on it to learn how to do these things before
doing serious work, so I will appreciate if you and others could point
out how several things can be improved, including clearing the screen,
putting the plotting part in a subroutine with Form as an argument,
etc. My questions and comments are in the code below.

Public Class Form3
Dim frmImage As Bitmap = New Bitmap(1000, 800) ' screen size?

Private Sub Form3_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim rect As New Rectangle(100, 50, 200, 120)
e.Graphics.DrawImage(frmImage, 0, 0)
e.Graphics.DrawRectangle(Pens.Green, rect) ' the plot area
End Sub

Private Sub cmdClear_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles cmdClear.Click
frmImage = New Bitmap(1000, 800) ' Bad practice?
Me.Invalidate()
End Sub

Private Sub cmdPlot_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles cmdPlot.Click
Dim g As Graphics = Graphics.FromImage(frmImage)
Dim XX(10) As Single, Y1(10) As Single
Dim i As Short, xxx1 As Single, yyy1 As Single
Dim k As Short, xxx2 As Single, yyy2 As Single

For i = 1 To 10
XX(i) = CSng(i) * 0.4 ' In future, Y1 will come from
complicated calculations
Y1(i) = XX(i) * XX(i) * Val(Form2.TextBox1.Text)
Next i

For i = 1 To 9
xxx1 = XX(i) * 200 / (4.0 - 0.0) + 100 ' In future,
x_scale and y_scale will
yyy1 = Y1(i) * 120 / (10.0 - 0.0) + 50 ' be used
xxx2 = XX(i + 1) * 200 / (4.0 - 0.0) + 100 ' A better way
would be to use
yyy2 = Y1(i + 1) * 120 / (10.0 - 0.0) + 50 ' DrawLines but
I don't know how..
g.DrawLine(Pens.Firebrick, xxx1, yyy1, xxx2, yyy2)
Next i
k = 1
Me.Invalidate() : g.Dispose() ' Seems really necessary
End Sub
End Class
 
C said:
But it won't do the conversion right. Will it?

Yes, because "" is not zero.

CSng("") does not work in VB6, too! I've just tried it. Error 13.
Looks like "Val" will work on blanks and null string.

Be aware that Val ignores the local settings.
Thanks.

Is there a simple way to do Form1.Cls? I cannot put this in Form_Paint
or it will always paint the same. I will have to use a frmImage to
plot things on, and there is no simple way I know of to erase things
on it. Do I need a New Bitmap every time? Thanks.

Painting is done in the Paint event (or by overriding OnPaint). You
paint on e.graphics. If you only call e.graphics.clear, it's like
clearing the "screen" (CLS). You can also call the Clear method if you
paint on an Image.
 
A few comments inline... Let me preface by saying every developer has
different styles, and will guide you differently.
C wrote:
I am having difficulties understanding VB.net terminology. The code I
have written is appended below. It works, but is probably quite
inefficient, and is not in accordance with good programming
practices.

I will try to improve on it to learn how to do these things before
doing serious work, so I will appreciate if you and others could point
out how several things can be improved, including clearing the screen,
putting the plotting part in a subroutine with Form as an argument,
etc. My questions and comments are in the code below.

Please add at the top:

Option Strict On

It will show you a few potential problems, in particular implicit
conversions that you are doing.
Public Class Form3
Dim frmImage As Bitmap = New Bitmap(1000, 800) ' screen size?

I believe you really want the clientsize property that James pointed
you. The form is rarely the size of the screen.
Private Sub Form3_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim rect As New Rectangle(100, 50, 200, 120)
e.Graphics.DrawImage(frmImage, 0, 0)
e.Graphics.DrawRectangle(Pens.Green, rect) ' the plot area
End Sub

Private Sub cmdClear_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles cmdClear.Click

When you are done with the previous image, you should execute
frmImage.Dispose(), to free resources used.
frmImage = New Bitmap(1000, 800) ' Bad practice?
Me.Invalidate()
End Sub

Private Sub cmdPlot_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles cmdPlot.Click
Dim g As Graphics = Graphics.FromImage(frmImage)
Dim XX(10) As Single, Y1(10) As Single
Dim i As Short, xxx1 As Single, yyy1 As Single
Dim k As Short, xxx2 As Single, yyy2 As Single

For i = 1 To 10
XX(i) = CSng(i) * 0.4 ' In future, Y1 will come from
complicated calculations
Y1(i) = XX(i) * XX(i) * Val(Form2.TextBox1.Text)

What you are doing in the line above is to use the "default instance" of
a Form2 object. Personally, I don't like that, and prefer an actual
instance of a Form2 that is passed into the constructor or as a property
from the code that creates this object.
Next i

For i = 1 To 9
xxx1 = XX(i) * 200 / (4.0 - 0.0) + 100 ' In future,
x_scale and y_scale will
yyy1 = Y1(i) * 120 / (10.0 - 0.0) + 50 ' be used
xxx2 = XX(i + 1) * 200 / (4.0 - 0.0) + 100 ' A better way
would be to use
yyy2 = Y1(i + 1) * 120 / (10.0 - 0.0) + 50 ' DrawLines but
I don't know how..
g.DrawLine(Pens.Firebrick, xxx1, yyy1, xxx2, yyy2)
Next i
k = 1
Me.Invalidate() : g.Dispose() ' Seems really necessary

Yes dispose(), where possible, is necessary. An alternative I prefer is
to use a using block that would look like:

Using g As Graphics = Graphics.FromImage(frmImage)
' most of the rest of your code
End Using

This automagically disposes the graphics object.
End Sub
End Class

In general, I believe most would draw the plot directly to the "e"
parameter in the paint handler, though technically, your approach is
fine, and would have at least one potential advantage. If you
implimented a print or save image option, you have much already generated.

I hope this helps.
 
For i = 1 To 10
XX(i) = CSng(i) * 0.4 '[snip comment]
Y1(i) = XX(i) * XX(i) * Val(Form2.TextBox1.Text)
Next i


For i = 1 To 10
Dim txtAsInt as Integer
txtAsInt = 0
Integer.TryParse(Form2.TextBox1.Text, txtaAsInt)

XX(i) = CSng(i) * 0.4 '[snip comment]
Y1(i) = XX(i) * XX(i) * txtaAsInt
Next i

This sets the variable to zero, then uses TryParse which only sets the
destination variable if the parsing is successful. When not successful
the value of the variable remains the same.
 
J.B. Moreno said:
For i = 1 To 10
XX(i) = CSng(i) * 0.4 '[snip comment]
Y1(i) = XX(i) * XX(i) * Val(Form2.TextBox1.Text)
Next i


For i = 1 To 10
Dim txtAsInt as Integer
txtAsInt = 0
Integer.TryParse(Form2.TextBox1.Text, txtaAsInt)

XX(i) = CSng(i) * 0.4 '[snip comment]
Y1(i) = XX(i) * XX(i) * txtaAsInt
Next i

This sets the variable to zero, then uses TryParse which only sets the
destination variable if the parsing is successful. When not successful
the value of the variable remains the same.

To do that, shouldn't you use:

if (Integer.TryParse(Form2.TextBox1.Text, txtAsInt))
XX(i) = CSng(i) * 0.4
Y1(i) = XX(i) * XX(i) * txtAsInt
else
' leave values as before
end if
 
Family Tree Mike said:
J.B. Moreno wrote: -snip-

To do that, shouldn't you use:

if (Integer.TryParse(Form2.TextBox1.Text, txtAsInt))
XX(i) = CSng(i) * 0.4
Y1(i) = XX(i) * XX(i) * txtAsInt
else
' leave values as before
end if

Val returns either the converted number or zero, by setting the
variable to zero before passing it into TryParse you get the same
results. So In the above code, he wants Y1(i) to be zero if
Form2.TextBox1.Text is "OP wants zero".
 
A few comments inline...  Let me preface by saying every developer has
different styles, and will guide you differently.

Thanks. These are precisely the kind of comments I am looking for, so
that I form better habits in the beginning. More questions inline.
Please add at the top:

Option Strict On
Yes.


It will show you a few potential problems, in particular implicit
conversions that you are doing.


I believe you really want the clientsize property that James pointed
you.  The form is rarely the size of the screen.

Some day, I let the Form3 be of variable size.
When you are done with the previous image, you should execute
frmImage.Dispose(), to free resources used.

I did not understand this. frmImage is form level variable which will
be used now and then, either for plotting or clearing the plot area,
or possibly to write some calculation results. If I dispose it, will
it be available for the next plot?
What you are doing in the line above is to use the "default instance" of
a Form2 object.  Personally, I don't like that, and prefer an actual
instance of a Form2 that is passed into the constructor or as a property
from the code that creates this object.

OK. This is a small matter. I hope to have a separate subroutine
preparing the Y1 array and that could take in Form2 as a Form variable
as an argument. Another little subroutine could do the plotting -
perhaps something like:

Public Sub plot_one_curve(XX() as single,Y1() as single, FormN as
Form, plotType as Short)

and this could sit in a Module of public subroutines.
Yes dispose(), where possible, is necessary.  An alternative I prefer is
  to use a using block that would look like:

         Using g As Graphics = Graphics.FromImage(frmImage)
          ' most of the rest of your code
         End Using

I guess this might be a cleaner way.
Would g.DrawLines be a better practice than drawing each little line
separately?
This automagically disposes the graphics object.


In general, I believe most would draw the plot directly to the "e"
parameter in the paint handler, though technically, your approach is
fine, and would have at least one potential advantage.  If you
implimented a print or save image option, you have much already generated..

Yes, I hope to save the plots or a part of the screen. I suspect
drawing to e in the Paint would not cause graphics to persist.
I hope this helps.

Thanks again.
 
Some day, I let the Form3 be of variable size.

In that case, you are probably best off to create the image at an arbitrary
fixed size, and copy it to the form using one of the DrawImage methods that
resizes the source image to the size of the destination rectangle.
I did not understand this. frmImage is form level variable which will
be used now and then, either for plotting or clearing the plot area,
or possibly to write some calculation results. If I dispose it, will
it be available for the next plot?

You need it as long as you need to use it in the Paint event, which is as
long as you expect it to keep appearing on the form. Once you no longer
need it for that purpose (the form is closed, for instance) you should
probably dispose of it, if only so that you know where and when you are
disposing of it. In other words, it is better to dispose of it as a result
of some particular event rather than as as part of a general clean up. You
can re-create it next time you need to draw a new image. There's very little
overhead in disposing and re-creating.

If you will always have an image of some sort or another to be drawn on that
form, then the image object does not need to be disposed - just re-use it
for the next drawing. A blank form does not require an image.

Well - it's not actually achieving anything, so I guess you could call it
bad.
I guess this might be a cleaner way.
Would g.DrawLines be a better practice than drawing each little line
separately?

There's not a big difference. It depends on how you are calculating the
lines. But note that if you are drawing into an image of known, fixed size
then most of the scaling issues disappear. It's probably more important to
make sure this code is separated out into its own routine, so that later on
you can come back to a single point where you can safely make detail changes
like this and be fairly confident you won't create errors elsewhere in the
code.
Yes, I hope to save the plots or a part of the screen. I suspect
drawing to e in the Paint would not cause graphics to persist.

If you are drawing to the Paint event graphics object you are not persisting
the graphics - you are re-creating them each time they need to be displayed.
They will 'persist' in the sense that they will be there when needed, but
only because your code is executing the drawing code each time.

As soon as the drawing gets even a little bit complicated the overhead of
re-creating it each time the Paint event executes is more than the overhead
of copying in the prepared image, as per your present approach. Now that
you have it set up like this, it would be sensible to stick with it.
 
C said:
I did not understand this. frmImage is form level variable which will
be used now and then, either for plotting or clearing the plot area,
or possibly to write some calculation results. If I dispose it, will
it be available for the next plot?

What I was trying to convey above was that you need to dispose of the
previously stored image. It will no longer be needed. You are creating
a new image which will be displayed and available, but before you create
it you should dispose the old image to get rid of any resources it took.

We recently had a thread here (or maybe in the C# group) where someone
was creating images in a loop without disposing and got into OutOfMemory
exceptions.
 
A few comments inline...  Let me preface by saying every developer has
different styles, and will guide you differently.




Please add at the top:

Option Strict On

It will show you a few potential problems, in particular implicit
conversions that you are doing.


I believe you really want the clientsize property that James pointed
you.  The form is rarely the size of the screen.

What size do you recommend? Can I write New Bitmap
(Screen.ClientSize.Width, Screen.ClientSize.Height)? I guess
ClientSize might apply only to VB.net objects.

In my case, it sometimes exceeds the size of the screen, and I have to
access some commands with Tab and Enter, particularly with older
computer projectors having 800 by 600 resolution.
When you are done with the previous image, you should execute
frmImage.Dispose(), to free resources used.

Then I can't draw another plot after clearing the plot area.
What you are doing in the line above is to use the "default instance" of
a Form2 object.  Personally, I don't like that, and prefer an actual
instance of a Form2 that is passed into the constructor or as a property
from the code that creates this object.



Yes dispose(), where possible, is necessary.  An alternative I prefer is
  to use a using block that would look like:

         Using g As Graphics = Graphics.FromImage(frmImage)
          ' most of the rest of your code
         End Using

This automagically disposes the graphics object.


In general, I believe most would draw the plot directly to the "e"
parameter in the paint handler, though technically, your approach is
fine, and would have at least one potential advantage.  If you
implimented a print or save image option, you have much already generated..

I suspect this won't work well. I have to plot something depending on
values of variables I can get from some text boxes on that form and
one other form. Then if another plot is desired, I or another user
might clear the plot area on Form3 and plot again something else. How
could I do this directly on e in the Form_Paint?
 
In that case, you are probably best off to create the image at an arbitrary
fixed size, and copy it to the form using one of the DrawImage methods that
resizes the source image to the size of the destination rectangle.

How do I create "at an arbitrary fixed size"?

Does it resize or does it just show truncated to the available size?
You need it as long as you need to use it in the Paint event, which is as
long as you expect it to keep appearing on the form.  Once you no longer
need it for that purpose (the form is closed, for instance) you should
probably dispose of it, if only so that you know where and when you are
disposing of it.  In other words, it is better to dispose of it as a result
of some particular event rather than as as part of a general clean up.  You
can re-create it next time you need to draw a new image. There's very little
overhead in disposing and re-creating.

So I could dispose it in Form_Unload.
If you will always have an image of some sort or another to be drawn on that
form, then the image object does not need to be disposed - just re-use it
for the next drawing.  A blank form does not require an image.


Well - it's not actually achieving anything, so I guess you could call it
bad.

What should I do instead to get rid of the old image (plot)?
 
How do I create "at an arbitrary fixed size"?

Dim frmImage As Bitmap = New Bitmap(1000, 800)

will create an image at the arbitrary size of 1000 x 800.
Does it resize or does it just show truncated to the available size?

That depends on the copy method you choose, although the point of what you
are trying to do would require that you copy the whole of the source image
into the whole of the destination. You might change this rule if you need
to maintain proportion, in which case a small calculation is required to
determine which dimension (horizontal or vertical) will determine the size,
and then adjust the other dimensioon to maintain proportion.
So I could dispose it in Form_Unload.

If you are using it for as long as the form is displayed, that would be an
appropriate place to dispose of it. It all depends on how you use the
object.
What should I do instead to get rid of the old image (plot)?

It depends on what you are trying to get rid of. If you create a bitmap
and overlay it onto the form when required (eg, in the Paint event), you get
rid of the bitmap by disposing of it. You would do this in order to
conserve resources. If you are talking about removing the image from
display (so that the user no longer sees it) then use the Clear method (or
equivalent) for whatever you are displaying the image on.
 
How do I create "at an arbitrary fixed size"?

Dim frmImage As Bitmap = New Bitmap(1000, 800)

will create an image at the arbitrary size of 1000 x 800.
Does it resize or does it just show truncated to the available size?

That depends on the copy method you choose, although the point of what you
are trying to do would require that you copy the whole of the source image
into the whole of the destination. You might change this rule if you need
to maintain proportion, in which case a small calculation is required to
determine which dimension (horizontal or vertical) will determine the size,
and then adjust the other dimensioon to maintain proportion.
So I could dispose it in Form_Unload.

If you are using it for as long as the form is displayed, that would be an
appropriate place to dispose of it. It all depends on how you use the
object.
What should I do instead to get rid of the old image (plot)?

It depends on what you are trying to get rid of. If you create a bitmap
and overlay it onto the form when required (eg, in the Paint event), you get
rid of the bitmap by disposing of it. You would do this in order to
conserve resources. If you are talking about removing the image from
display (so that the user no longer sees it) then use the Clear method (or
equivalent) for whatever you are displaying the image on.
 
What size do you recommend? Can I write New Bitmap
(Screen.ClientSize.Width, Screen.ClientSize.Height)? I guess
ClientSize might apply only to VB.net objects.

You could, but these values do not stay consistent throughout the life of
the program. If you detect when they change and re-create the bitmap at the
new size, then that solves the problem. Or, you can do your copy operation
so that it doesn't matter that the size has changed. But, in that case, the
size that you start with doesn't matter. You could then choose that size to
be conveneient for your plotting and so that it prodces text that is nicely
sized within the graphic.
In my case, it sometimes exceeds the size of the screen, and I have to
access some commands with Tab and Enter, particularly with older
computer projectors having 800 by 600 resolution.

This is an issue to do with the projector and the PC setup. I don't think
you can deal with this problem within your application. However, it does
mean that you cannot simply assume that a certain window size is going to be
available (and, in any case, you shouldn;t make such an assumption). That's
why you need to make sure your image fits properly in whatever size window
the user chooses.
Then I can't draw another plot after clearing the plot area.

Simply create a new bitmap and draw onto that new bitmap.
I suspect this won't work well. I have to plot something depending on
values of variables I can get from some text boxes on that form and
one other form. Then if another plot is desired, I or another user
might clear the plot area on Form3 and plot again something else. How
could I do this directly on e in the Form_Paint?

If you use this approach, then the drawing will hapen whenever the form is
re-drawn. The drawng procedure will use whatever values are currently
entered into the text boxes etc. So if someone changes one of these values
then the next time the image is re-drawn it will use that new value. But
you just wait for that to happen - if someone changes a value then your
application will detect that change, and will issue a Me.Invalidate to force
the image to be redrawn (and it will automatically pick up the new value to
be used in the drawing).
 
Back
Top