Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Control Arrays in Visual Basic 6

Options
  • 08-05-2003 1:09pm
    #1
    Registered Users Posts: 7,468 ✭✭✭


    I want to access a control in an array of controls in vb6*. So if I have an array of 4 labels called lblArray() and want to access the label at index 2, so I can pass it to a method say, what do I do?
    
    '// Returns control's default value which 
    '// is a string and not a label
    '// Raises a Type Mismatch error
    Call foo(lblArray(2))
    
    Private Sub foo(oControl as Control)
     ...
    end sub
    
    

    I have also tried creating an object of type Control and type Object, then setting that as lblArray(index). The default value is still returned.

    I have also tried lblArray.Item(index) - still returns the default value as well. How do I get my hands on the actual control??






    *Please no responses of 'VB sucks d00d' as I'd like people who actually know something about software development to comment, and nobody else. Thank you.


Comments

  • Closed Accounts Posts: 20 _Nobody113


    Hi, all controls in your array have the same id - You can use this ID concatenated with index to get an access to particular control.

    me.ArrLabel(1)' returns secondth label.


  • Registered Users Posts: 7,468 ✭✭✭Evil Phil


    me.ArrLabel(1) ' returns secondth label.

    It appears it does not. I can't see a difference between using me in the code or not using me.
    Refrencing a control in an array in this manner will not return a reference to the actual control. It seems it always returns the _Default property (which is a hidden field).


  • Moderators, Home & Garden Moderators, Regional Midwest Moderators, Regional West Moderators Posts: 16,723 Mod ✭✭✭✭yop


    I could be getting you wrong but is this what you are trying to do?

    Place an array of 4 labels on the form
    Place a command button
    Put a different caption on each label

    Then put the following code
    Private Sub Command1_Click()
        
        Call GetCaption(label(1))
    
    End Sub
    
    Private Sub GetCaption(lbl As label)
    
    MsgBox "Lable caption is : " & lbl.Caption
    End Sub()
    

    If it is not what you are looking for soz


  • Registered Users Posts: 7,468 ✭✭✭Evil Phil


    Aha, I didn't use Call in the actuall code :rolleyes: Simple. Thanks Yop. _Nobody113, my apologies.

    Does anybody now why I have to use Call? Cos I don't.


  • Registered Users Posts: 2,781 ✭✭✭amen


    the Call statement is not needed
    you can use
    GetCaption Label(1)
    or
    Call GetCaption (Label(1))

    note the extra set of brackets
    I can't remember why u would want to use call but I'll look it up late and reply


  • Advertisement
  • Moderators, Home & Garden Moderators, Regional Midwest Moderators, Regional West Moderators Posts: 16,723 Mod ✭✭✭✭yop


    Good point, never thought why you would use it !

    I always have for some reason!!


  • Registered Users Posts: 15,443 ✭✭✭✭bonkey


    Phil...I'm working a bit from memory here, and this stuff is a bit weird....but here's how I remember it...

    1) The "normal" calling convention for a subroutine is either :

    MySub someParam

    or

    call MySub (someParam)

    In both of these cases, someParam is passed By Reference to MySub.

    However, you can also use the following call syntax :

    MySub (someParam)

    Most people arent aware of it, but this is not the same as the first option I presented above, as it actually forces someParam to be passed By Value, not by reference.

    (If anyone doesnt believe me, you can test that with the sample code I threw together below. Create a form, throw a button (Command1) on it, and paste this code behind it all.)

    Anyway...this difference, subtle though it is, is where your problem comes in, as (and here's where I fall back on memory) either Controls, or Objects in general cannot be passed ByVal in this way due to sime stupid limitation in the language....hence my example using strings and not labels to illustrate what I'm talking about.

    Hope that helps clear things up somewhat....

    jc


    Private Sub Command1_Click()

    Dim x As String

    x = "a"
    Call test(x)
    MsgBox x
    test (x)
    MsgBox x
    test x
    MsgBox x

    End Sub



    Private Sub test(stest As String)

    stest = stest + "x"

    End Sub


  • Registered Users Posts: 15,443 ✭✭✭✭bonkey


    IN case I didnt make it clear....Phil, if you drop the brackets, you dont need the Call keyword, and you will only see this when dealing with Objects or Controls (not sure exactly which), not with primitive types.

    jc


  • Closed Accounts Posts: 9,314 ✭✭✭Talliesin


    bonkey is correct (well, actually it's creating a temporary, passing that by reference and then destroying it rather than passing by value per se - the distinction is subtle though and only something to worry about if you are writing C/C++ code that will interact with the VB code).

    The reason all this happens relates to what parentheses do.
    In VB (as in a lot of languages) parentheses play two roles.
    1. Containing arguments to a function where you use the return value, or to a subroutine or function called using the Call keyword.
    2. Forcing order of evaluation.

    Consider
    x = (a + b) * c
    
    This adds a and b, stores the result in a temporary variable, multiplies the temporary with c, storing the result in y, and then gets rid of the temporary.

    Now consider the difference between x=func(a) and x=func(a+b).
    If func receives its parameter ByRef then it can work on a directly in the first call, but must work on the temporary result of a+b in the second case.

    Now consider x=func((a)). The inner parentheses mean "work out the value of 'a' first". Hence a temporary is created that is equal to a. Then that temporary is passed to func. Hence any changes func attempts to do to its parameter will have no result on a.

    In effect x=func((a)) is the same as tmp=a : x=func(tmp).

    The confusion results because of the way that VB doesn't use parentheses if you are calling a procedure but not doing anything with its return value (and don't use the Call keyword). Hence any parentheses that are there are treated used to force order of evaluation.
    As such func (a) is the same as Call func((a)). It's worth noting that the IDE uses different spacing for each of these, which is the only clue it gives you as to what is going on.

    Hence the meaning of the three calls of "test" in bonkey's examples are:
    Call test(x) ' pass x to test
    
    test (x) ' create a temporary string, assign x to it, pass the temporary to test.
    
    test x 'pass x to test.
    

    This gets more complicated in cases of casting. If you pass an Integer to a function that takes a Long ByRef then a temporary Long will be created, the Integer assigned to it, and that temporary used.

    Even more fun comes along if you have to create a temporary of an object or control, because VB has no copy constructors, and hence no good way of creating a temporary object or control! It's this last case that came into play here.


  • Registered Users Posts: 15,443 ✭✭✭✭bonkey


    Originally posted by Talliesin
    Even more fun comes along if you have to create a temporary of an object or control, because VB has no copy constructors, and hence no good way of creating a temporary object or control! It's this last case that came into play here.

    Ahhh....thats the bit my brain wouldnt yield up to me....copy constructors.

    Cheers :)

    jc


  • Advertisement
Advertisement