Passing Form by Reference - How To Upgrade?

S

Steve Ricketts

Posted in languages.vb.upgrade but then I realized it was rarely used so I'm
reposting here.

I have a large number of VB6 apps that I would like to convert to VB.net.
All of them use a standard (here anyway) technique of calling a public sub
and passing the form reference byref so many frequently used subs/functions
can be used without regard to the calling form's name.

private sub Form_Load()
call registerForm(Form1)
end sub

In a common module...

public myForm as form

public sub registerForm(byRef theForm as Form)
set myForm = theForm
end sub

public sub otherSubs()
myForm.caption = "some title" & app.version...
myForm.lstRoles.clear
end sub

I've run a couple of these programs through VB.net 2008 and it warns me of
an error that my controls cannot be referenced because they are in the
generic namespace Form.

I'd like to know how a similar technique is written in .Net? Any direction
greatly appreciated.

Steve
 
A

Armin Zingler

Steve Ricketts said:
private sub Form_Load()
call registerForm(Form1)
end sub

In a common module...

public myForm as form

public sub registerForm(byRef theForm as Form)
set myForm = theForm
end sub

public sub otherSubs()
myForm.caption = "some title" & app.version...
myForm.lstRoles.clear
end sub

I've run a couple of these programs through VB.net 2008 and it warns
me of an error that my controls cannot be referenced because they
are in the generic namespace Form.

I'd like to know how a similar technique is written in .Net? Any
direction greatly appreciated.

Move "otherSubs" into the actual Form.


Armin
 
P

Phill W.

Steve said:
I have a large number of VB6 apps that I would like to convert to VB.net.
All of them use a standard (here anyway) technique of calling a public sub
and passing the form reference byref so many frequently used subs/functions
can be used without regard to the calling form's name.

You rarely need the /name/ of anything in .Net; having a reference to
the "thing" is far more useful.
I've run a couple of these programs through VB.net 2008 and it warns me of
an error that my controls cannot be referenced because they are in the
generic namespace Form.

if you pass something "as Form", then you can only do "Form" things with
it. To get to your own Form Classes, you have to downcast:

Function X( ByVal frm as Form )
If ( TypeOf frm Is MyForm73 ) Then
DirectCast( frm, MyForm73 ).Do73Job()
End If
End Function
I'd like to know how a similar technique is written in .Net? Any direction
greatly appreciated.

One word - Inheritance.

Q. Why did you put these methods into a Module originally?
A. So that you could re-use them in [nearly] every form that you write.

The .Net equivalent is to create a base class from which all your forms
derive and put the common code in there. Each of your forms then access
this functionality via the MyBase keyword, something like

Class WindowBase
Inherits Form

Protected Sub AddVersion()
Me.Text = Me.FixedTitle & " - " & App.Version
End Sub

Protected Overridable Function FixedTitle() as String
Return "(No Title)"
End Function

End Class

Class Window1
Inherits WindowBase

Sub New()
MyBase.New()

MyBase.AddVersion()

End Sub

Protected Overrides Function FixedTitle() as String
Return "Win1 Title"
End Function

End Class

HTH,
Phill W.
 
S

Steve Ricketts

That's my problem. There are many different programs that call OtherSubs
(as well as man other standard routines) and I don't want to copy the code
into every one of them. Changing the code then would require a change in
all of them rather than just a recompile.

sr
 
A

Armin Zingler

Steve Ricketts said:
That's my problem. There are many different programs that call
OtherSubs (as well as man other standard routines) and I don't want
to copy the code into every one of them. Changing the code then
would require a change in all of them rather than just a recompile.

Create a DLL and use it in each application. You only have to change the
source code of the Dll one time.


Armin
 
S

Steve Ricketts

Ah, very nice. That's what I was looking for. That would allow me to do
the things I need to do. One question, just so I have the right mental
image of what's going on... In the WindowBase.AddVersion sub, the "me.text"
part. me.text is just the text (caption) of the WindowBase form.
WindowBase is a... well.. just a form with all the controls I would need for
all my routines: listboxes, images, textboxes, etc. For example:

Class WindowBase ' (form contains a listbox called "lstNames")
Inherits Form

Protected Sub fillName()
lstNames.item.clear()
lstNames.item.addItem "Bob"
lstNames.item.addItem "Ted"
lstNames.item.addItem "Alice"
lstNames.item.addItem "Fido"
End Sub

Protected Overridable Function FixedTitle() as String
Return "(No Title)"
End Function

End Class

Class Window1 ' (also contains a listbox called lstNames)
Inherits WindowBase

Sub New()
MyBase.New()

MyBase.fillName()

End Sub

Protected Overrides Function FixedTitle() as String
Return "Win1 Title"
End Function

End Class

If this example is correct, it would mean that the names of the controls in
WindowBase would have to match the control names in all the forms that will
use the class. Is there any way to deal with different names?

Thanks again for the great advice.

sr
Phill W. said:
Steve said:
I have a large number of VB6 apps that I would like to convert to VB.net.
All of them use a standard (here anyway) technique of calling a public
sub
and passing the form reference byref so many frequently used
subs/functions
can be used without regard to the calling form's name.

You rarely need the /name/ of anything in .Net; having a reference to the
"thing" is far more useful.
I've run a couple of these programs through VB.net 2008 and it warns me
of
an error that my controls cannot be referenced because they are in the
generic namespace Form.

if you pass something "as Form", then you can only do "Form" things with
it. To get to your own Form Classes, you have to downcast:

Function X( ByVal frm as Form )
If ( TypeOf frm Is MyForm73 ) Then
DirectCast( frm, MyForm73 ).Do73Job()
End If
End Function
I'd like to know how a similar technique is written in .Net? Any
direction
greatly appreciated.

One word - Inheritance.

Q. Why did you put these methods into a Module originally?
A. So that you could re-use them in [nearly] every form that you write.

The .Net equivalent is to create a base class from which all your forms
derive and put the common code in there. Each of your forms then access
this functionality via the MyBase keyword, something like

Class WindowBase
Inherits Form

Protected Sub AddVersion()
Me.Text = Me.FixedTitle & " - " & App.Version
End Sub

Protected Overridable Function FixedTitle() as String
Return "(No Title)"
End Function

End Class

Class Window1
Inherits WindowBase

Sub New()
MyBase.New()

MyBase.AddVersion()

End Sub

Protected Overrides Function FixedTitle() as String
Return "Win1 Title"
End Function

End Class

HTH,
Phill W.
 
J

Jack Jackson

Ah, very nice. That's what I was looking for. That would allow me to do
the things I need to do. One question, just so I have the right mental
image of what's going on... In the WindowBase.AddVersion sub, the "me.text"
part. me.text is just the text (caption) of the WindowBase form.

Me.Text is the caption of the form. There is only one form. That
form might have been created by:
Dim frm As New WindowBase
or
Dim frm As New Window1
but in both cases there is only one form control.
WindowBase is a... well.. just a form with all the controls I would need for
all my routines: listboxes, images, textboxes, etc. For example:

Class WindowBase ' (form contains a listbox called "lstNames")
Inherits Form

Protected Sub fillName()
lstNames.item.clear()
lstNames.item.addItem "Bob"
lstNames.item.addItem "Ted"
lstNames.item.addItem "Alice"
lstNames.item.addItem "Fido"
End Sub

Protected Overridable Function FixedTitle() as String
Return "(No Title)"
End Function

End Class

Class Window1 ' (also contains a listbox called lstNames)

I am concerned when you say "also contains a listbox named lstNames".
Windows1 does contain a listbox called listNames, but it is the
listbox inherited from WindowsBase. Windows1 just adds some code to
WindowBase. The Window1 class does NOT create another listbox.
Inherits WindowBase

Sub New()
MyBase.New()

MyBase.fillName()

End Sub

Protected Overrides Function FixedTitle() as String
Return "Win1 Title"
End Function

End Class

If this example is correct, it would mean that the names of the controls in
WindowBase would have to match the control names in all the forms that will
use the class. Is there any way to deal with different names?

The inherited classes contain the same controls as the base class. You
do not define duplicate controls in the inherited class. Inherited
means what it says - the inherited class includes everything in the
base class plus new things.

The inherited classes can add more controls, but the controls from the
base class are there too, and you can not change their names.
 
S

Steve Ricketts

Thanks for the explantation. It makes perfect sense to inherit controls
and therefore not needing to duplicate them, but what confuses me is those
controls need to be placed and seen on the form that inherits WindowsBase.
I've defined a control, let's say, lstNames as listbox, in WindowsBase and
have a public sub within it's class to populate the listbox. How do I show
that control on the Windows1 form?

Thanks again for your reply, it's really helping me a ton.

Steve
 
J

Jack Jackson

Any controls in WindowsBase should be shown in Windows1 just like they
are shown in WindowsBase.
 
S

Steve Ricketts

Ah, that's the rub... even though they are the same controls, they are
always in different places. For example I have three programs, one that
captures video, one that adds action tags to the video, and one that creates
hightlights from multiple videos. They all use a control called lstSport.
However, the layout of the screens are vastly different and lstSport along
with a dozen more controls (time period, formation, possession, etc.) are in
different places on the each of the differnt forms.

In VB6 by passing the form reference, I could just have subroutines do their
thing on the various form controls without having to worry about which
program was being used... or in this case where the controls were located. I
can do a similar thing in .Net by declaring public variables for all the
common controls I use across the applications and in a "registerForm"
function iterate through all the controls on the referenced form and assign
them to those variables, but that seems pretty ugly.

sr
 
L

Lloyd Sheen

Steve Ricketts said:
Ah, that's the rub... even though they are the same controls, they are
always in different places. For example I have three programs, one that
captures video, one that adds action tags to the video, and one that
creates hightlights from multiple videos. They all use a control called
lstSport. However, the layout of the screens are vastly different and
lstSport along with a dozen more controls (time period, formation,
possession, etc.) are in different places on the each of the differnt
forms.

In VB6 by passing the form reference, I could just have subroutines do
their thing on the various form controls without having to worry about
which program was being used... or in this case where the controls were
located. I can do a similar thing in .Net by declaring public variables
for all the common controls I use across the applications and in a
"registerForm" function iterate through all the controls on the referenced
form and assign them to those variables, but that seems pretty ugly.

sr

If you want to access the controls from each form without going thru the
inherit process create an Interface. The definition would be something
like:

Public Interface MyControls
ReadOnly Property ThelstNamesCTL() As Control
End Interface

Then in each form with the lstNames control add an

implements ThelstNamesCTL to the form. If you are using VS it should add
the code stub if you hit Enter at the end of the line.

The implementation would be"

Public ReadOnly Property ThelstNamesCTL as Control
Get
Return lstNames
End Get
End Property

Then if you need to access the lstNames control you would do the following:

Dim ctl as Control
Dim ifrm as MyControls
ifrm = theFormIWantToGetTheControlFor

ctl = ifrm.ThelstNamesCTL

You can put this into a try and if the form does not support the MyControls
interface it will go to the execption handler.


Hope this helps
Lloyd Sheen
 
J

Jack Jackson

I don't see how the locations of the controls matters.

If you change the Modifer property of the controls to Public, then you
can access them with a form reference. If you don't want the code
that access the form to have to know the type of the form, then define
an Interface that contains references to the controls and cast the
form reference to the Interface.
 
S

Steve Ricketts

Great, thanks. Now I've got a couple of alternatives to work with. If I
can get my mind untangled, I'll try both these suggestions and take a look
at the pro's and con's of each.

Thanks again for all your help,

sr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top