frmN.Label31.Text = frmTitle does not work in VB.net

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

C

Earlier I could do this with frmN as Form. Now it does not work. I can
manage without this but it would be good to learn what I should do
instead.

Sub formsize(ByRef FormN As System.Windows.Forms.Form)
FormN.ScaleWidth = 11940 ' ScaleWidth not used in VB.net
FormN.Height = VB6.TwipsToPixelsY(8500) or just 850
FormN.Width = VB6.TwipsToPixelsX(12060)
FormN.BackColor = System.Drawing.ColorTranslator.FromOle(RGB(rrr,
ggg, bbb)) or Color.FromArgb(rrr,ggg,bbb)
FormN.Label30.Width = 800
FormN.Label31.Width = 800
FormN.Label30 = progTitle
FormN.Label31 = progSubtitle
FormN.Label31.ForeColor = RGB(255, 255, 255)
End Sub
 
We've seen you are pretty much a beginner.

In Net you have two things modules (often called or used as shared classes
(static in C#)) and instanced classes (objects)

For forms it are commonly instanced classes (objects). In VB the form is a
little bit strange beast to keep it more or less compatible with earlier
versions of VB. So it is standard instanced automatically (there are 12 ways
to instance a form). In fact that automatically instances confuses at a
certain moment.

However, to make the rest short. You can use simple ScaleWidth in the (form)
class, although mostly is done me.scalewidth, you get then direct
intelisence. (In C languages is 'this' used for me, which is exactly the
same)
 
We've seen you are pretty much a beginner.

In Net you have two things modules (often called or used as shared classes
(static in C#)) and instanced classes (objects)

For forms it are commonly instanced classes (objects). In VB the form is a
little bit strange beast to keep it more or less compatible with earlier
versions of VB. So it is standard instanced automatically (there are 12 ways
to instance a form).  In fact that automatically instances confuses at a
certain moment.

However, to make the rest short. You can use simple ScaleWidth in the (form)
class, although mostly is done me.scalewidth, you get then direct
intelisence.  (In C languages is 'this' used for me, which is exactly the
same)







- Näytä siteerattu teksti -

My main question was what I should do about
FormN.Label30.Text = progTitle

This does not work any more. Is there a good workaround?

FormN is an instanced class of a form. Each form in my program will
have a Label30 which should get the title of the program. I know there
are million ways of doing this, but to make the forms look similar, I
have a subroutine which will make several things on each form similar.
This subroutine formsize is called by every Form*_Load event in VB6,
and I am thinking of doing it in a similar way in VB.net also.

Thanks again for your help.
 
Or is FormN not the form where the code is in.
Then it becomes more complicated and if I see that you don't understand the
code Tom gave, hard to explain.
 
Am 31.07.2010 12:06, schrieb C:
My main question was what I should do about
FormN.Label30.Text = progTitle

This does not work any more. Is there a good workaround?

FormN is an instanced class of a form. Each form in my program will
have a Label30 which should get the title of the program. I know there
are million ways of doing this, but to make the forms look similar, I
have a subroutine which will make several things on each form similar.
This subroutine formsize is called by every Form*_Load event in VB6,
and I am thinking of doing it in a similar way in VB.net also.

You have a solution for a problem in VB6. If you want to solve the problem
in VB.Net, you should find a VB.Net solution. It's not always good to
use the VB6 solution in VB.Net. Often, the solutions are the same, sometimes
they are similiar, sometimes they are completely different.
This is only a general hint for upgrading.

VB6 programming was unsafe programming. IMO, nowadays, this is unacceptable.
In this case, unsafe means using late binding. The type "Form" does not have
a member called Label30. Therefore you can not compile this code. Full stop.
In VB.Net, if you don't enable late binding for very rare cases, the compiler
checks the existence of type members. You are not allowed to access type
members that do not exist for that type. Not every Form has a "Label30".


The big difference is that we now have inheritance and (explicit) interfaces.
This is the VB.Net solution to your problem:

If all your forms have a "Label30", define a common base Form and make use
of Form inheritance. This makes all inherited Forms look like the base form,
and you can add additional controls to the inherited Forms. Put your Resize
code into the base form and all your inherited forms will automatically have
that feature. There is no need to explicitly call that FormSize sub in any of
your derived Forms.

The other way is declare and implement an Interface in all your
Forms, so you will be able to pass them to your FormSize sub that works
on that interface. I guess the Interface solution is the quicker way because
you don't have to change the design of all your Forms. Would be a big
construction zone. In the long run, and for new projects anyway, you should
choose the inheritance solution if possible. So, the Interface solution is:

Interface IForm
Property Width() As Integer
Property Height() As Integer
Property BackColor() As Color
End Interface

Interface IBaseForm
Inherits IForm

ReadOnly Property Label30() As Label
ReadOnly Property Label31() As Label
End Interface

Shared Sub FormSize(ByVal Form As IBaseForm)
Form.Height = 4711
Form.Width = 4712
Form.BackColor = Color.FromArgb(1, 2, 3)
Form.Label30.Width = 800
Form.Label31.Width = 800
Form.Label30.Text = "sdfsdf"
Form.Label31.Text = "sdfsdf"
Form.Label31.ForeColor = Color.White
End Sub

In addition, enter "Implements IBaseForm" (+press Enter-Key) in all your
Forms. Maybe you'll be shocked initially. ;-) All the members for implementing
the interface will be created. As some of the members already exist in the Form
or in the base class, you'll get strange names like Width1 instead of Width.
You can change the signature, for example, change

Public Property Width1() As Integer Implements IForm.Width

to

Private Property IForm_Width() As Integer Implements IForm.Width

Then you'll have to fill the members with meaning:

Private Property IForm_Width() As Integer Implements IForm.Width
Get
Return Width
End Get
Set(ByVal value As Integer)
Width = value
End Set
End Property


In general, class/interface modelling should be done more thoroughly.
I've only inferred the interfaces from the code in your sub. Depending
on the exact design of your Forms, other solutions are possible. I guess
the Forms _are_ different, otherwise you wouldn't need different Form
classes. For example, you could write a Usercontrol putting some of the
common controls into it, then place the Usercontrol on the Forms
(what you already know from VB6). It all depends. To find the best
solution, we would have to discuss what exactly your Forms have in
common, and so on.

I didn't refer to other subjects like ScaleMode etc. These are different
topics.


You may wonder: "Why all this? It was soooo simple in VB6."
This is because of shifted priorities. Late binding like in VB6 is very
slow and it does not make sense to make the run time search for a member
at run time as the compiler is able to see if it exists at compile time.
In addition, if the member is not found, an exception occours (and
maybe your customer complains instead of the compiler enabling you
to fix it)

So, the efforts as suggested above are usually only necessary if you
upgrade a project. If you create a new one and do the right design
steps, it's easier than before, thanks to inheritance.
 
I thought I wrote that.

label30.Text = progTitle
or
me.label30.Text = progTitle

You are trying to be helpful but you don't read half of my messages.
What you are suggesting is trivial and the same thing worked in VB6
also except that labels had captions rather than texts.

The subroutine to size forms sits in a module. Every form calls that
subroutine in Form*_Load. This is what makes it complicated.
 
Or is FormN not the form where the code is in.
Then it becomes more complicated and if I see that you don't understand the
code Tom gave, hard to explain.

The code sits in a module. May be I should think of doing this in a
different way.
 
Am 31.07.2010 12:06, schrieb C:

Thanks for your detailed reply. I have some comments below.
You have a solution for a problem in VB6. If you want to solve the problem
in VB.Net, you should find a VB.Net solution. It's not always good to
use the VB6 solution in VB.Net. Often, the solutions are the same, sometimes
they are similiar, sometimes they are completely different.
This is only a general hint for upgrading.

I agree. I am only a beginner, and am trying to rebuild the program
more or less from scratch instead of letting VB 2008 Express do most
of the conversion on its own. In this way, I hope to learn a little
bit, which should be useful in the long run, although I am not really
a programmer.
VB6 programming was unsafe programming. IMO, nowadays, this is unacceptable.

I would appreciate some more comments about this. VB6 unsafe?
Inefficient? What made it unacceptable? A lot of old VB6 programs are
still in everyday use.
In this case, unsafe means using late binding. The type "Form" does not have
a member called Label30. Therefore you can not compile this code. Full stop.
In VB.Net, if you don't enable late binding for very rare cases, the compiler
checks the existence of type members. You are not allowed to access type
members that do not exist for that type. Not every Form has a "Label30".

I think I understand so far.
The big difference is that we now have inheritance and (explicit) interfaces.
This is the VB.Net solution to your problem:

If all your forms have a "Label30", define a common base Form and make use
of Form inheritance. This makes all inherited Forms look like the base form,
and you can add additional controls to the inherited Forms. Put your Resize
code into the base form and all your inherited forms will automatically have
that feature. There is no need to explicitly call that FormSize sub in any of
your derived Forms.

This is a bit advanced for me, since I am still new to classes and
objects. In VB6, you did not need that.
The other way is declare and implement an Interface in all your
Forms, so you will be able to pass them to your FormSize sub that works
on that interface. I guess the Interface solution is the quicker way because
you don't have to change the design of all your Forms. Would be a big
construction zone. In the long run, and for new projects anyway, you should
choose the inheritance solution if possible. So, the Interface solution is:

 Interface IForm
      Property Width() As Integer
      Property Height() As Integer
      Property BackColor() As Color
   End Interface

   Interface IBaseForm
      Inherits IForm

      ReadOnly Property Label30() As Label
      ReadOnly Property Label31() As Label
   End Interface

I am not familiar with this interface and inheritance concepts. Looks
like I will have to read up a bit.
   Shared Sub FormSize(ByVal Form As IBaseForm)
      Form.Height = 4711
      Form.Width = 4712
      Form.BackColor = Color.FromArgb(1, 2, 3)
      Form.Label30.Width = 800
      Form.Label31.Width = 800
      Form.Label30.Text = "sdfsdf"
      Form.Label31.Text = "sdfsdf"
      Form.Label31.ForeColor = Color.White
   End Sub

In addition, enter "Implements IBaseForm" (+press Enter-Key) in all your
Forms. Maybe you'll be shocked initially. ;-) All the members for implementing
the interface will be created. As some of the members already exist in the Form
or in the base class, you'll get strange names like Width1 instead of Width.
You can change the signature, for example, change

 Public Property Width1() As Integer Implements IForm.Width

to

 Private Property IForm_Width() As Integer Implements IForm.Width

Then you'll have to fill the members with meaning:

     Private Property IForm_Width() As Integer Implements IForm.Width
         Get
            Return Width
         End Get
         Set(ByVal value As Integer)
            Width = value
         End Set
      End Property

In general, class/interface modelling should be done more thoroughly.
I've only inferred the interfaces from the code in your sub. Depending
on the exact design of your Forms, other solutions are possible. I guess
the Forms _are_ different, otherwise you wouldn't need different Form
classes.

Yes, all of them are different, but they have some similarities like
size, BackColor, title lines on Labels30 and 31.

For example, you could write a Usercontrol putting some of the
common controls into it, then place the Usercontrol on the Forms
(what you already know from VB6). It all depends. To find the best
solution, we would have to discuss what exactly your Forms have in
common, and so on.

I didn't refer to other subjects like ScaleMode etc. These are different
topics.

You may wonder: "Why all this? It was soooo simple in VB6."
This is because of shifted priorities. Late binding like in VB6 is very
slow and it does not make sense to make the run time search for a member
at run time as the compiler is able to see if it exists at compile time.
In addition, if the member is not found, an exception occours (and
maybe your customer complains instead of the compiler enabling you
to fix it)

So, the efforts as suggested above are usually only necessary if you
upgrade a project. If you create a new one and do the right design
steps, it's easier than before, thanks to inheritance.

I am trying to create a very similar program from scratch, so I do
have the possibility to think in VB.net and use new concepts. The
trouble is that I am very new to VB.net, and am not a programmer by
profession, so I can't spend a large amount of time on this daily.

Thanks for your reply.
 
Am 31.07.2010 18:36, schrieb C:
I would appreciate some more comments about this. VB6 unsafe?
Inefficient? What made it unacceptable? A lot of old VB6 programs are
still in everyday use.

Unacceptable is that you can access members of types that do not even
exist. It was a matter of luck if it will work. Therefore, there was a higher
risk for errors. You could even pass a Form to a Sub expecting
a Label and the compiler did not even complain. Awesome.

Identifiers (like variable names, method names) are made for programmers.
A compiler is to resolve such names. Working with identifiers during
run time (=late binding) is the wrong point in time (apart from few
exceptions). I can't explain it better.

The key is "type safe" programming, which is early binding in this case.
Your focus is more on designing types, which includes inheritance and
interface implementation. With these features, everything can be solved
without late binding.

Another step is to always switch Option Strict On.
This is a bit advanced for me, since I am still new to classes and
objects. In VB6, you did not need that.

I've been using classes and objects all the time in VB6. :-)
I am trying to create a very similar program from scratch, so I do
have the possibility to think in VB.net and use new concepts. The
trouble is that I am very new to VB.net, and am not a programmer by
profession, so I can't spend a large amount of time on this daily.

Whenever you need a design pattern, tell us the goal to achieve. :)
 
Thanks for your detailed reply. I have some comments below.


I agree. I am only a beginner, and am trying to rebuild the program
more or less from scratch instead of letting VB 2008 Express do most
of the conversion on its own. In this way, I hope to learn a little
bit, which should be useful in the long run, although I am not really
a programmer.


I would appreciate some more comments about this. VB6 unsafe?
Inefficient? What made it unacceptable? A lot of old VB6 programs are
still in everyday use.

Just read up on Visual Basic Evil Type Conversion and maybe you'll
understand :) There were many constructs used in VB.CLASSIC that could
cause performance or even runtime issues if they were not understood.
For example your code :) If you were to pass in a form that did NOT
have a label30 then the code would blow up - at runtime. VB.NET is
preventing that mistake from happening by makeing it more type safe.

For other examples, you might look at:
Dim i, j, k As Integer
Dim o As New MyObject

etc, etc. Both of those were problematic in VB.CLASSIC - yet often
used.
I think I understand so far.


This is a bit advanced for me, since I am still new to classes and
objects. In VB6, you did not need that.

Many of these concepts did in fact exist in VB6 - they just weren't as
obvious or even used that often. For instance, the concept of
interfaces and interface inheritance - it's just that vb6 did not have
explicit interfaces. VB.NET just takes VB6 more advanced object based
concepts and moves them to the next level - true OOP. Giving not only
interface but actual implementation inheritance (with forms this is
sometimes called visual inheritance, but it's really just plain old
implementation inheritance).

So, basically you create a form with all of the common elements layed
out how they should be on all of your other forms. Once you've done
that all your other forms in the project simply inherit form this base
form and they will have all of those elements automatically.

Again, this concept actually makes VB.NET much more powerfull - once
you understand it :)

You should read up on the basics of object oriented programming.
I am not familiar with this interface and inheritance concepts. Looks
like I will have to read up a bit.

Yep - but this concept also existed in VB6. It's just that VB6 didn't
have explicit interfaces. You essentially used classes with empty
implementations as interfaces.
Yes, all of them are different, but they have some similarities like
size, BackColor, title lines on Labels30 and 31.

Personally, I would create a base form and then use inheritance to
accomplish what your after. Basically, you don't have any code to
write if you do that.
 
My main question was what I should do about
FormN.Label30.Text = progTitle

The easiest thing to do (particularly at your skill level) is to change
your signature:

Sub formsize(ByVal FormN As System.Windows.Forms.Form,
ByVal label30 as System.Windows.Forms.Label)

label30.Text = progTitle

End Sub


PS -- you'll notice that I changed your ByRef to a ByVal. There is
only ONE reason to pass an argument ByRef and that's because you want
the option to set the CALLING routine's VARIABLE value. But you can't
do that for "Me" as it isn't really a variable of the calling routine.


Also be aware that if you DO use ByRef and you pass in something that
can't be changed (such as the value of a field of a read only
recordset), you'll get an exception as the routine returns. Very
tricky to track down.
 
I try to understand your message, but VB6 is for those many years active in
this newsgroup almost 10 years behind us. The answers I give are based on
the most mistakes beginning OOP programmers make.

Beside that, are you using VB6 in your way, where you gave us only this
piece of code.


How should I know what you mean with that.
However, if you have passed this as

me = formsize(me) then it probably will work if you change such old beast as
twips and RGB.

That goes much easier, as long as you want to accept that. White for
instance is color.white

A normal passing is byval wich passes the reference, byref is a very little
bit slower as it passes the reference in an extra box.

Be aware that the sense of this kind of code is low, as you can better
create in this kind of programming an own base form.

Cor
 
Am 31.07.2010 18:36, schrieb C:





Unacceptable is that you can access members of types that do not even
exist. It was a matter of luck if it will work. Therefore, there was a higher
risk for errors. You could even pass a Form to a Sub expecting
a Label and the compiler did not even complain. Awesome.

Identifiers (like variable names, method names) are made for programmers.
A compiler is to resolve such names. Working with identifiers during
run time (=late binding) is the wrong point in time (apart from few
exceptions). I can't explain it better.

The key is "type safe" programming, which is early binding in this case.
Your focus is more on designing types, which includes inheritance and
interface implementation. With these features, everything can be solved
without late binding.

I understood this now. Having worked with Fortran IV onwards, I
thought there was nothing with run-time and compile-time errors; one
simply had to be prepared for them. Perhaps this is not considered
wise these days.
Another step is to always switch Option Strict On.


I've been using classes and objects all the time in VB6. :-)



Whenever you need a design pattern, tell us the goal to achieve. :)

Thanks. I am sure I will have to trouble you now and then.
 
Just read up on Visual Basic Evil Type Conversion and maybe you'll
understand :)  There were many constructs used in VB.CLASSIC that could
cause performance or even runtime issues if they were not understood.  
For example your code :)   If you were to pass in a form that did NOT
have a label30 then the code would blow up - at runtime.  VB.NET is
preventing that mistake from happening by makeing it more type safe.

I got the point, but the compiler is trying to be a big brother. It is
only my fault if I don't have a Label30 on every form which calls the
formsize subroutine, and I would notice it while testing the program.
Anyway, I can adapt to the new wisdom.
For other examples, you might look at:
Dim i, j, k As Integer
Dim o As New MyObject

etc, etc.  Both of those were problematic in VB.CLASSIC - yet often
used.

Dim i, j, k as Integer would make i and j variants (Object in VB.net),
while k would be an Integer. Isn't that the same in VB.net?
Many of these concepts did in fact exist in VB6 - they just weren't as
obvious or even used that often.  For instance, the concept of
interfaces and interface inheritance - it's just that vb6 did not have
explicit interfaces.  VB.NET just takes VB6 more advanced object based
concepts and moves them to the next level - true OOP.  Giving not only
interface but actual implementation inheritance (with forms this is
sometimes called visual inheritance, but it's really just plain old
implementation inheritance).

So, basically you create a form with all of the common elements layed
out how they should be on all of your other forms.  Once you've done
that all your other forms in the project simply inherit form this base
form and they will have all of those elements automatically.

I understand. I just am not very familiar with this kind of thinking,
and fear the risk of messing up too much.
Again, this concept actually makes VB.NET much more powerfull - once
you understand it :)

You should read up on the basics of object oriented programming.

I see the point. I have read up OOP a little bit but am not used to
thinking in those terms. I have used non-OOP languages for very long,
and used VB2, VB3, VB4, and VB6 as if they were procedure oriented, so
it will take me some time to get used to the new way of thinking.

Thanks for the explanation.
 
The easiest thing to do (particularly at your skill level) is to change
your signature:

Sub formsize(ByVal FormN As System.Windows.Forms.Form,
          ByVal label30 as System.Windows.Forms.Label)

label30.Text = progTitle

End Sub

Great. This is a nice workaround for my level.
I presume, while calling, I will have to mention Me.Label30, not just
Label30.
PS -- you'll notice that I changed your ByRef to a ByVal.  

Yes.

There is
only ONE reason to pass an argument ByRef and that's because you want
the option to set the CALLING routine's VARIABLE value.  But you can't
do that for "Me" as it isn't really a variable of the calling routine.

Also be aware that if you DO use ByRef and you pass in something that
can't be changed (such as the value of a field of a read only
recordset), you'll get an exception as the routine returns.  Very
tricky to track down.

Yes.

Thanks for this idea.
 
I try to understand your message, but VB6 is for those many years active in
this newsgroup almost 10 years behind us. The answers I give are based on
the most mistakes beginning OOP programmers make.

I appreciate your help.
Beside that, are you using VB6 in your way, where you gave us only this
piece of code.


How should I know what you mean with that.
However, if you have passed this as

me = formsize(me) then it probably will work if you change such old beast as
twips and RGB.

That goes much easier, as long as you want to accept that. White for
instance is color.white

I am learning this slowly. I used mostly RGB, so I now have to use
Color.Argb.
 
Am 01.08.2010 12:27, schrieb C:
I got the point, but the compiler is trying to be a big brother.

It's your own fault to access a not existing member. The compiler just
checks this. (Simplified:) Members are located at certain memory address,
so the compiler must know to which address to resolve a name. It can't
point to nowhere or a random location.
It is
only my fault if I don't have a Label30 on every form which calls the
formsize subroutine, and I would notice it while testing the program.

You must notice it when you are writing the code (or compiling it).
Anyway, I can adapt to the new wisdom.

That's good. :-)
Dim i, j, k as Integer would make i and j variants (Object in VB.net),
while k would be an Integer. Isn't that the same in VB.net?

No, all are Integer.
 
It happens that C formulated :
I got the point, but the compiler is trying to be a big brother. It is
only my fault if I don't have a Label30 on every form which calls the
formsize subroutine, and I would notice it while testing the program.
Anyway, I can adapt to the new wisdom.

Good. Besides the runtime errors, it also causes performance issues -
because every object had to be checked at runtime for the existance of
the label. So, there is more to it then just preventing errors.
Dim i, j, k as Integer would make i and j variants (Object in VB.net),
while k would be an Integer. Isn't that the same in VB.net?

No, all are Integer in VB.NET.

Also, Dim x As New MyOjbect doesn't do delayed instantiation anymore...
I understand. I just am not very familiar with this kind of thinking,
and fear the risk of messing up too much.


I see the point. I have read up OOP a little bit but am not used to
thinking in those terms. I have used non-OOP languages for very long,
and used VB2, VB3, VB4, and VB6 as if they were procedure oriented, so
it will take me some time to get used to the new way of thinking.

Thanks for the explanation.

You do not need OOP to use VB.NET. Not really. You can in the most
part continue on just using objects as you did in VB6 and writing code
in modules - but, learning this stuff will help take better advantage
of what .NET has to offer.
 
Back
Top