Accessing ContainerControl / EmbeddedWindowControl Type

  1. 3 years ago

    I have created a container control called myCustomCC with a couple of controls in it and placed it in a window.

    I then iterate through all the window controls using "Window.ControlCount" loop and identify the control using "IsA EmbeddedWindowControl" but what I can't figure out is how to find out whether this particular EmbeddedWindowControl is myCustomCC because its name is a complex "wrapper" verison of the actual control name on the window (not the original container control name) and I can't use "IsA myCustomCC" because this does not work.

    I need to know it is specifically a myCustomCC (and not some other custom container control type on the same window) so I can call a custom method on it etc.

    Any ideas?

  2. Greg O

    18 Mar 2017 Xojo Inc scout.galaxy.barn

    It's not enough to use IsA, you have to then cast it.

    if ctl IsA myCustomCc then
        MyCustomCC(ctl).methodName()
    End If 
  3. Even though I have identified the control IsA EmbeddedWindowControl Xojo is not then allowing me to cast it to a specific type (myCustomCC) and gives me an illegal cast exception. And I don't know how to find out the type either since there could be two types of container controls on a window.

  4. Michel B

    18 Mar 2017 Pre-Release Testers, Xojo Pro
    Edited 3 years ago

    The name is probably _wrapper_ myCustomCC. What I would do is to verify the name with

    if instr(control(i).name, "myCustomCC") > 0 then 

    As Greg said, when you are sure it is myCustomCC, you must cast it to access its methods.

  5. Thanks, Michel, yes I am using Instr to access the name value right now but that's not ideal and as mentioned, I cannot cast it due to IllegalCastException. Instead I have to refer to the control by its actual name in order to access the cc methods.

    This is also not ideal since I have ten controls like that so have to manually call the same method one by one using If and then etc rather than casting and calling it once.

  6. Tim H

    18 Mar 2017 Pre-Release Testers Portland, OR USA

    You cannot cast an EmbeddedWindowControl to anything. There is no direct way to access the containercontrol from the Control() method. It's best to maintain your own array of containers. Barring that, you can iterate over all the objects in Runtime and find the one that matches your embeddedwindowcontrol. I recommend maintaining your own list of them.

  7. Norman P

    18 Mar 2017 Xojo Inc, Pre-Release Testers, Xojo Pro Seeking work. npalardy@great-w...

    your best off NOT to reach inside a container at any rate

    put methods on the container that you can call that does whatever work is needed
    then even if the guts of the cc changes (you change controls names etc you can just change the code in the exposed method and things continue working)
    treat them like black boxes - you know nothing about their innards & have to use the API they provide (which of course you also get to write)
    it will make your life simpler in the long run

  8. @Norman P your best off NOT to reach inside a container at any rate

    put methods on the container that you can call that does whatever work is needed
    then even if the guts of the cc changes (you change controls names etc you can just change the code in the exposed method and things continue working)
    treat them like black boxes - you know nothing about their innards & have to use the API they provide (which of course you also get to write)
    it will make your life simpler in the long run

    I have created methods on the container control to access but what I'm trying to say is that when I loop through the windows controls and identify an EmbeddedWindowControl how can I identify what type of container control it is (other than Instr name method) in order to call a method on it and even then I still have to manually call the actual control and method since it can't be cast to anything...right?

    So let's say I have five container controls in a window and I loop through and want to call the same method on all five of them, right now I have to use ccname1.execute(), ccname2.execute() and so on. Is there an easier way rather than hard-coding each control call?

  9. Jean-Yves P

    19 Mar 2017 Pre-Release Testers, Xojo Pro Europe (France, Besançon)

    this method will give you all the containercontrols inside a given window:

    Public Function ContainerControls(extends w as Window) as ContainerControl()
      'get a list of all the container controls in a window
      
      dim theList() as ContainerControl
      dim o as Runtime.ObjectIterator = Runtime.IterateObjects
      
      while o.MoveNext
        if o.Current isA ContainerControl and ContainerControl(o.Current).Window is w  then
          theList.Append ContainerControl(o.Current)
        end if
      wend
      return theList
      
    End Function

    but it is not very efficient as it loops throught all the objects at runtime, this can be quite long on a heavy project.
    a better way is to use the notification interface (look about it in the dev center)
    at the open event of the window, register all your containercontrols inside an array of the window, then you can call them from a window's method.

  10. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Dim ccs As New Dictionary()
    	
    Dim iterator As Runtime.ObjectIterator = Runtime.IterateObjects()
    Do Until Not iterator.MoveNext()
      If iterator.Current IsA ContainerControl Then
        Dim cc As ContainerControl = ContainerControl(iterator.Current)
        ccs.Value(cc.Handle) = cc
      End
    Loop
    
    For i As Integer = 0 To ControlCount - 1
      If Control(i) IsA EmbeddedWindowControl Then
        Dim handle As Integer = Control(i).Handle
        Dim cc As ContainerControl = ccs.Lookup(handle, Nil)
        If cc <> Nil Then
          // Do something with cc...
        End
      End
    Next
  11. Michel B

    19 Mar 2017 Pre-Release Testers, Xojo Pro
    Edited 3 years ago

    There is a simpler way : store references to the CC when they are instantiated. In their Open event for instance. Can be done in a dictionary or an array.

    Then you cycle through the dictionary or the array, not the window.

  12. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Edited 3 years ago

    It would be great if EmbeddedWindowControl had a (read-only) property AsContainerControl to return the ContainerControl instance.

  13. Okay but even with a dictionary or array of all container controls in a window how can you identify the "type" and how can you call a specific method based on that specific type? So do ccType1.Execute() and ccType2.Flush() whereby Execute is a method specific to type 1 cc and Flush is a method specific to type 2 cc. I'm guessing you can't because you can't cast a type like ccType1(cc).Execute and ccType2(cc).Flush is probably not possible so you still have to go by individual control names and method calls for each one by name.

  14. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Edited 3 years ago

    Once you have the container control instance you can cast it to ccType1 or ccType2.

  15. Norman P

    19 Mar 2017 Xojo Inc, Pre-Release Testers, Xojo Pro Seeking work. npalardy@great-w...
    Edited 3 years ago

    IsA

    if cc isA CC1 then
    elseif cc isa CC2 then
    end if
  16. Michel B

    19 Mar 2017 Pre-Release Testers, Xojo Pro

    @Denise A Okay but even with a dictionary or array of all container controls in a window how can you identify the "type" and how can you call a specific method based on that specific type?

    How many kinds of CC do you have ? You could have a dictionary or array for each type, or do what Norman shows above.

  17. @Eli Ott Once you have the container control instance you can cast it to ccType1 or ccType2.

    @Norman P IsA
    if cc isA CC1 then elseif cc isa CC2 then end if

    Ahh, I see. I will try all that out. Thanks.

  18. 2 years ago

    Thomas T

    10 Feb 2018 Pre-Release Testers, Xojo Pro Europe (Germany, Munich)
    Edited 2 years ago

    @Michel B There is a simpler way : store references to the CC when they are instantiated.

    The problem with this is that I cannot write generic functions accessing all controls in a Window this way, though, if the window contains ContainerControls.

    E.g, I want to write a general function that finds all editable controls in a Window and sets their Enabled property to false - it won't be able to find controls inside CCs unless I explicitly pass those CCs to the function as well. Not very clean, IMO.

    I agree with Eli that EmbeddedWindowControl should provide an accessor to the ContainerControl or provide access to the Controls inside.

  19. 2 weeks ago

    James S

    Mar 21 Pre-Release Testers, Xojo Pro

    Not to resurrect an old topic ;) But I’m going to resurrect an old topic.

    Has anyone found a way around this in the meantime? I am trying to write a generic window extension that will let me do some changing of the tab order of things as I am creating much of the interface dynamically and cannot trust the information used for that to be in the proper tab order. I wish to walk every control on the window, including ones embedded on container controls but that seems to be impossible as the EmbeddedWindowControl object is undocumented, opaque and has no .controls method or obvious other way to walk it’s control array. It cannot be cast back to a ContainerControl or anything else as far as I can tell.

    I’m going to have to write specific methods for all the affected windows that use local container control references and know what they should be which is a pain as it really should be possible to find all the controls that are currently on a window even if some of them are inside a container control.

    Walking the entire object list for the entire program is not an option in this case as it’s a large program and there are millions of objects at runtime.

  20. Newer ›

or Sign Up to reply!