Cannot (always) use Objects as parameters

Discussion in 'Bug Reports' started by Woinowski, Aug 28, 2007.

  1. Woinowski

    Woinowski Active Member Licensed User

    To show what I mean an example below.

    Problem is: Sometimes you can use a parameter to assign it to the Value property of an object (e.g. of a TreeView Node ), sometimes you can't.

    When it does not work you get an error message like "cannot convert [...].String to System.Windows.Forms.TreeView"

    Funny thing is: In most cases it works directly at the beginning of a sub. It never (?) works further down in the body of a sub.

    Following example sub ist not working (assume TempNode is a TreeView node which has been initialized):

    [I have tried several variants]

    ' parameter ile is a file opened with FileOpen for writing
    ' node is a TreeView node object
    Sub RecursiveWrite (file, node)
    ' First use of node sometimes works
    TempNode.Value = node ' Remark: or node.value, try both
    FileWrite(file, TempNode.text)

    nodeCount = TempNode.Count - 1
    for i = 0 to nodeCount
    RecursiveWrite(file, TempNode.GetNode(i))
    ' or:
    ' TempNode.Value = TempNode.GetNode(i)
    ' RecursiveWrite(file, TempNode.Value)

    ' Reset TempNode, never works
    TempNode.Value = node ' or node.value, does not matter :-(
    node
    End Sub
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    First, it should always be node.Value.
    Are you sure that node is not an empty node?
     
  3. Woinowski

    Woinowski Active Member Licensed User

    Yes, you are right, it should also be .value on the right hand side of the "="

    I am sure that it is not an empty node. Especially I had the case that within one call the first use worked and the second not, although I did not change 'node' within one call.

    It might be the cause that recursion is the real problem. In general, if you do recursive calls I expect a stack of local parameters and variables. Is this expectation correct fpr B4PPC?

    Unfortunaley I just overwrote my whole code with save as (desaster is one short click away :-( ), otherwise i could send you the complete thing. [I do not assume it is possible to decompile B4PPC-Programs]
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    When you use a recursive call a stack of local variables is created.
    Note that objects (like a tree node) and controls are global and not local.
     
  5. Woinowski

    Woinowski Active Member Licensed User

    To prevent further theoretical discussions, I just coded some fully working example (see below, you can use copy&paste).

    You need
    Form1 : Form
    Component added : TreeView.dll
    Tree: TreeView
    Node, TempNode: Node

    ---
    Here's the error message:

    An error occured on sub recursivedescent

    Line numer: 70

    TempNode.Value = nodeAsParameter
    Error description:
    Das Object mit dem Typ System.Int32 kann nicht in den Typ Systems.Windows.Forms.TreeNode konvertiert werden.
    Continue?

    [Buttons Yes/No]

    Translation of error:

    The object with type System.Int32 cannot be converted to type Systems.Windows.Forms.TreeNode.

    ---

    Heres the sample code:

    -- 8< -- snip -
    Sub Globals
    'Declare the global variables here.
    Dim Result
    End Sub

    Sub App_Start
    Form1.Show

    ' Initialize Tree
    Tree.New1("Form1", 0, 0, 200,200)
    Tree.AddNewNode("Root")
    Node.New1
    Node.Value = Tree.GetNode(0)
    Node.AddNewNode("Level 1.1")
    Node.AddNewNode("Level 1.2")
    Node.AddNewNode("Level 1.3")
    Node.Value = Node.GetNode(0)
    Node.AddNewNode("Level 2.1")
    Node.AddNewNode("Level 2.2")
    Node.Value = Node.Parent
    Node.Value = Node.GetNode(1)
    Node.AddNewNode("Level 2.3")
    Node.AddNewNode("Level 2.4")
    Tree.ExpandAll

    ' Initialize TempNode
    TempNode.New1

    ' Prepare Result of recursive call
    Result = ""

    ' Initialize node for recursive call
    Node.Value = Tree.GetNode(0)

    ' No recursion: Works fine!
    UseNode(Node.Value)

    ' Recursice Call
    RecursiveDescent(Node.Value)

    ' Use result
    Msgbox(Result,"Result")
    End Sub

    Sub UseNode(nodeAsParameter)
    ' Assign Temp Node
    TempNode.Value = nodeAsParameter

    ' Sample use
    Msgbox(TempNode.Text, "It Works")
    TempNode.Text = "New name"
    Msgbox(TempNode.Text, "It Still Works")
    End Sub

    Sub RecursiveDescent(nodeAsParameter)
    ' Assign Temp Node (works!)
    TempNode.Value = nodeAsParameter
    Msgbox(TempNode.Text, "It Works in First Line")

    ' Do something for each node:
    Result = Result & TempNode.Text & crlf

    nodeCount = TempNode.Count - 1
    For i = 0 To nodeCount
    ' This will overwrite TempNode
    TempNode.Value = TempNode.GetNode(i)
    RecursiveDescent(TempNode.Value)

    ' Reset TempNode after recursion (does not work!!!)
    ' Exactly the same as in first line of sub!
    TempNode.Value = nodeAsParameter
    Next
    End Sub

    -- 8< -- snip -
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    You can't pass an object value to a sub.
    You should use the object's name instead:
    Code:
    Sub UseNode(nodeName)
       
    ' Assign Temp Node
       TempNode.Value = Control(nodeName).Value
    ...
    End Sub
    ...
    UseNode(
    "Node")
     
  7. Woinowski

    Woinowski Active Member Licensed User

    Thanks for all your quick replies.

    To sum it all up and "close" the bug

    1. Why does the first line of my recursive function work then?

    2. Using the name of the object won't help for the recursion - it is essential to be able to re-assign the original reference

    3. As a workaround I think it should be possible to implement something similar to the iterators known form C# or Java. As soon as I have some code I'm gonna post it in the correct Main Category (Code Samples)
     
    Last edited: Aug 28, 2007
  8. Erel

    Erel Administrator Staff Member Licensed User

    1. In a nutshell, Basic4ppc remembers the last object value returned and then it uses it the next time an object is required. Again you should not pass objects to subs as it will not work consistently.
    2. Why won't it work? I think it should work properly.
     
  9. agraham

    agraham Expert Licensed User

    Hi Erel
    I see his problem (I think). There is only a single TempNode in the scope of the recursion, whereas he needs a different local node reference for each level of descent because he is recursing in a loop and needs the original reference to identify the next node to recurse into.

    When you do "Node.AddNewNode("Level 1.1")" what is the name of the added node or is it anonymous? Is there any way of saving a node reference in a local variable -I've tried it and it doesn't error but also doesn't work!
     
  10. agraham

    agraham Expert Licensed User

    How about this?

    Code:
    Sub Globals
       
    'Declare the global variables here.
       Dim Result 
    End Sub

    Sub App_Start
       form1.Show
    Tree.New1(
    "Form1"00200,200)
    Tree.AddNewNode(
    "Root")
       
    Node.New1
       
    Node.Value = Tree.GetNode(0)
       
    Node.AddNewNode("Level 1.1")
       
    Node.AddNewNode("Level 1.2")
       
    Node.AddNewNode("Level 1.3")
       
    Node.Value = Node.GetNode(0)
       
    Node.AddNewNode("Level 2.1")
       
    Node.AddNewNode("Level 2.2")
       
    Node.Value = Node.Parent
       
    Node.Value = Node.GetNode(1)
       
    Node.AddNewNode("Level 2.3")
       
    Node.AddNewNode("Level 2.4")
       Tree.ExpandAll
       
    Msgbox(GetControls("Tree"))
       
    ' Initialize TempNode
       TempNode.New1
       
    ' Prepare Result of recursive call
       Result = ""
       
    ' Initialize node for recursive call
       Node.Value = Tree.GetNode(0)
       
    ' Recursice Call
       RecursiveDescent("Node"1)
       
    ' Use result
       Msgbox(Result,"Result")
    End Sub


    Sub RecursiveDescent(NodeName, Level)
       
    ' Do something for each node:
       Result = Result & Control(NodeName).Text & " "
       SubNode = 
    "Node"&Level
       AddObject(SubNode, 
    "Node")
       
    Control(SubNode).New1
       nodeCount = 
    Control(NodeName).Count - 1
       
    For i = 0 To nodeCount
          
    Control(SubNode).Value = Control(nodeName).GetNode(i).Value
          RecursiveDescent (SubNode, Level+
    1)   
       
    Next
       
    Control(SubNode).Dispose
    End Sub
     
  11. Cableguy

    Cableguy Expert Licensed User

    Check out my backup utility in the samples forum....maybe it helps
     
  12. Woinowski

    Woinowski Active Member Licensed User

    I did not think of AddObject...

    This is an extremely cool solution. Although I am now working without recursion I definitely will remember this one :)

    So, thanks
     
  13. Woinowski

    Woinowski Active Member Licensed User

    Sample for Tree Iterator on TreeView

    You will find the workaround in the following open source project:

    http://www.basic4ppc.com/forum/showthread.php?t=1514
     
Loading...