StrataFrame Forum
Home      Members   Calendar   Who's On
Welcome Guest ( Login | Register )
      



Macro substitutionExpand / Collapse
Author
Message
Posted 07/28/2006 7:08:32 PM


Advanced StrataFrame User

Advanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame User

Group: StrataFrame Users
Last Login: Today @ 8:48:09 AM
Posts: 622, Visits: 19,073
As a VFP developer, the one thing I have missed the most of my old friend "&".

Trying to build controls and/or objects dynamically then loop through them has proven a real PITA, the closest I have come so far is using .NET's control arrays (not even as easy to use as VB6's, but I digress) which have the limitiation of having to be loaded.

So.... being former VFP developers did you put in anything like this?

for x = 1 to n 

l_controlstring = "thisform.txtTextbox" + alltrim(str(n)) + ".backcolor = rgb(255,213,202)"

&l_controlstring

next x

If you did, I'm sold.

Post #1974
Posted 07/28/2006 8:12:33 PM


StrataFrame Developer

StrataFrame Developer

Group: StrataFrame Developers
Last Login: Today @ 4:58:13 AM
Posts: 4,379, Visits: 4,421
This is actually quite easy when you know where to look.  When I first wanted to do this it was extremely frustrating because I just wanted to create a macro like in VFP and execute it.  The good news is that this can be done, in a lot of different ways.  It all comes down to reflection and strong-typing.  Since VFP is a weak-typed language this was just a matter of combining some text and hoping that you didn't get an error.  In .NET, it is equally as easy, but you just have to conform to strong-typing.  Let's take your example and turn it into .NET using SF...keep in mind that ThisForm in VFP is not nearly as important in .NET which is referenced by Me.

Option 1
'-- Establish Locals
Dim loControl As System.Windows.Forms.Control

For Each loControl In Me.Controls

    '-- See if the object is a textbox
    If loControl.GetType() Is GetType(TextBox)
        loControl.BackColor = Color.FromArgb(255,213,202)
    End If

Next

Option 2 - Accessing the Property Directly
Controls("txtTextBox1").GetType().GetProperty("BackColor") = Color.FromArgb(255,213,202)

You can also call methods and create objects dynamically using an activator which is similar to macros in VFP.

Sample Class Creation
'-- Establish Locals
DIm lcCmd As String = "MyClass"
Dim loObj As Object

'-- Create the class
loObj = Activator.CreateInstance(lcCmd)

The topic you are asking about will be covered to some degree in our class.  This is also something we could go on about for a good long while.  There are MANY differents to accomplish this, it just depends on what you are attempting to do.

If this doesn't answer your question please let me know.

Post #1975
Posted 07/28/2006 8:57:38 PM


Advanced StrataFrame User

Advanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame User

Group: StrataFrame Users
Last Login: Today @ 8:48:09 AM
Posts: 622, Visits: 19,073
** why dont tabs work in my posts? and why is bouble spacing forced? makes for sloppy code examples **

perhaps a practical example is best:

here is some code I wrote that may explain my need, this is my workaround so far.....

For Each ctr In Me.Controls

If TypeOf ctr Is CheckBox Then

curCheckbox = ctr

If curCheckbox.Checked = True Then

If curCheckbox.Name.Length = 9 Then

checkid = curCheckbox.Name.Substring(curCheckbox.Name.Length - 1, 1)

Else

checkid = curCheckbox.Name.Substring(curCheckbox.Name.Length - 2, 2)

End If

If checkid <= 30 Then

texttopass = textarray(Val(checkid) - 1)

labeltopass = labelarray(Val(checkid) - 1)

progresstopass = bararray(Val(checkid) - 1)

pingit(texttopass.Text, progresstopass, labeltopass, curCheckbox, checkid)

End If

End If

End If

Next

 

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

I have those arrays of controls textarray, labelarray, and bararrray preloaded with controls that I might want to change the values of in the PINGIT method (I still call them methods, it is really a function/sub). I pass the entire control based on the array index because I dont know how to programatically create a control reference.

If VFP I could just pass the index, then build a control reference variable and execute a macro substitution. I cant (or dont know how).

Lets take your options 2 since I think it was the closest.

Option 2 - Accessing the Property Directly
Controls("txtTextBox1").GetType().GetProperty("BackColor") = Color.FromArgb(255,213,202)

How would I do that without hardcoding the "1" in "Textbox1"? What is the name of the control to be changed was for instance pulled from a table?

Do you see what I am getting at?

Thanks for looking.... this isnt just me. The other developers in my office (all still semi-novices as .NET) cant get an elegant equivilant to the flexibility of the VFP macro.

I guess the bottom line is how do I dynamically make a reference to a control using variables?

This is wrong but is pseuocode for what I want to do

Dim ctrl as Control

ctrl = "me." + <<variable containing textbox name or part of it (index) >>

ctrl.text = "some text"

Post #1976
Posted 07/28/2006 10:27:32 PM


StrataFrame Developer

StrataFrame Developer

Group: StrataFrame Developers
Last Login: Today @ 4:58:13 AM
Posts: 4,379, Visits: 4,421
Here is a sample that shows how to start using reflection.  This is a very basic sample, but should start giving you an idea of how to use reflection.  Honestly, though it may be hard to believe at first, .NET has a much system of communicating with indirect objects.  Once you begin to understand the structure of .NET, the VFP macro will seem clumsy and cumbersome....and practically useless   But believe me, I did not think this at first and I have come a long way since I first wanted to resort back to a weak typed macro.

The first method you need to learn about it GetType().  This method will be instrisically on every object, regardless of the class or control, in .NET.  This is the gateway into reflecting an object or class to get to its properties, methods, events, and so on.

Also, as a side note, you will want to use CType() and GetType() instead of TypeOf.  It will be much faster.  For example, in your code snippet:

If TypeOf ctr Is CheckBox Then

would be faster and more efficient as:

If ctr.GetType() Is GetType(CheckBox) Then

As for the forum questions, press Ctrl+Enter to break for a single line.  Enter takes you to a new paragraph.  As for tab....sorry, you have to use spaces...at least for now.  As for code examples, you can copy from .NET and paste it directly into the editor. It will keep the tabs, but you may have to delete the blank lines and add a Ctrl+Enter to get a single line back in.

Last thing, instead of passing an array over to your pingit method, you should create a generic list with a reference to your controls.

Single Object Type As a CheckBox

'-- Establish Locals
Dim
loCheckBoxesOnly As New System.Collections.Generic.List(Of CheckBox)

loCheckBoxesOnly.Add(Me.CheckBox1)

Any Type Of Control

'-- Establish Locals
Dim loAnyControl As New System.Collections.Generic.List(Of System.Windows.Forms.Control)

loAnyControl.Add(Me.CheckBox1)
loAnyControl.Add(Me.Textbox1)
loAnyControl.Add(Me.Textbox2)

I hope this helps.  Please let me know if things are still a little fuzzy. My explanation may not be the best.



  Post Attachments 
VFPMacroSample.zip (12 views, 684.71 KB)
Post #1977
Posted 07/28/2006 10:45:44 PM


Advanced StrataFrame User

Advanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame User

Group: StrataFrame Users
Last Login: Today @ 8:48:09 AM
Posts: 622, Visits: 19,073
Great stuff there and I may be dense since it is getting late, but....

You code all has a hardcoded reference like "Textbox1"

How do you make your code flexible so that it can accept any/many controls (ie. TEXTBOX(x) ) with passing an explicit reference to a control:

Here is VFP code I cannot reproduce:

IF ALLTRIM(this.Value) <> ALLTRIM(g_emailaddress)
 For x = 1 To 4 && 4 contacts
  l_fieldname = "thisform.pgfCorpInfo.page5.chkCont"+Alltrim(Str(x))+"_primary.value"
  If &l_fieldname = .T.
    l_emailfield = "thisform.pgfCorpInfo.page5.txtCont"+ALLTRIM(STR(x))+"_email.value"
    &l_emailfield = ALLTRIM(this.value)
  Endif
 Next x
ENDIF

See how l_fieldname references 4 controls here since I am BUILDING the name? THAT is what I dont get.

Replection DOES look awesome though.

I must not be explaining myself well, but I do promise to buy ya a beer August 11th for putting up with it

Post #1979
Posted 07/28/2006 10:59:47 PM


StrataFrame Developer

StrataFrame Developer

Group: StrataFrame Developers
Last Login: Today @ 4:58:13 AM
Posts: 4,379, Visits: 4,421
That is what I am trying to illustrate.  TextBox1 is not a direct reference, you could just as easily put in a local variable here.  If I wanted to directly reference the TextBox1, there would not have been quotes and I would have made a call like this:

TextBox1.GetType()

Does that make sense?  Regardless of VFP or .NET, you have to have some base reference.  For example, a form, user control, containter, etc. that you know will exist in order for you to enumerate the controls within it.  Or create controls.  In your example, your base would be "thisform.pgfCorpInfo.page5" which you would then iterate through the Controls collection of this container object and begin using reflection to determine what to do, if anything, with that object.

DIm loControl As Control
Dim loType As System.Type

For Each loControl In Me.pgfCorpInfo.Page5

   '-- Save off the type of the control
   loType = loControl.GetType()

   '-- See if this control need to be updated
   If loType.IsSubClassOf(TextBox) Then
       CType(loControl, TextBox).Text = "MyValue"
   ElseIf loType.IsSubClassOf(CheckBox) Then
       CType(loControl, CheckBox).Checked = True
   End If


Next

So in this example you really are not using as much reflection as just making sure that the objects are properly typed.  For whatever it is worth, you can do what you are trying to do.  You can do practically ANYTHING in .NET.  The thing is that you have to properly reflect the objects in order to set them or execute methods.  You can test on object names, values, literllay anything.  But just as you already knew where you were planning to look in your VFP code, you have to have a point of reference to at least start from before you can reflect to the objects dynamically.

Post #1982
Posted 07/28/2006 11:02:29 PM


Advanced StrataFrame User

Advanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame User

Group: StrataFrame Users
Last Login: Today @ 8:48:09 AM
Posts: 622, Visits: 19,073
Cool Ill try this all out....... thank you.
Post #1983
Posted 07/30/2006 10:03:33 PM


Advanced StrataFrame User

Advanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame UserAdvanced StrataFrame User

Group: StrataFrame Users
Last Login: Today @ 8:48:09 AM
Posts: 622, Visits: 19,073
I found this out on the net somewhere and the light went on:

       For i As Integer = 1 To 3
            CType(Me.Controls("Label" & i), Label).Text = "Text Number " & i
        Next

I get it.............

Post #2009