Casting classes based on ContainerControl

I have a class called MICRLineBox based on ContainerControl, which contains a couple TextFields and one integer property I need access to in order to print its content when it is part of a page.

I use Window.Control() to access each control, and cast each according to its name.

So when I get an embeddedWindowControl named _wrapper_MICRLineBox1, I do

dim MLB as MICRLineBox = MICRLineBox(W.Control(i))

And I get an illegal cast exception …

Of course I could set global variables all around, or a global dictionary, but that feels terribly wrong.

Is there really no way to cast a control instance to a class based on ContainerControl ?

containercontrols are not controls …
you must use something like this :

Function ControlOrContainerControl(Extends win As Window, index As Integer) As Object If index > win.ControlCount - 1 Then Return Nil Else Dim c As Control = win.Control(index) If c IsA EmbeddedWindowControl Then Dim iterator As Runtime.ObjectIterator = Runtime.IterateObjects() Do Until Not iterator.MoveNext() If iterator.Current IsA ContainerControl Then If ContainerControl(iterator.Current).Graphics = EmbeddedWindowControl(c).Graphics Then Return ContainerControl(iterator.Current) End End Loop Else Return c End End End Function

or like this :

[code]Function ContainerControls(extends w as Window) As ContainerControl()

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

[/code]

Thank you so much Jean-Yves :slight_smile:

[code]Module ExtensionsModule

Private Property ContainerControls As Dictionary
Get
Static dct As New Dictionary()
Return dct
End
End

Sub Register(Extends cc As ContainerControl)
Dim g As Graphics = cc.Graphics
#if TargetCocoa
ContainerControls.Value(g.Handle(Graphics.HandleTypeCGContextRef)) = New WeakRef(cc)
#else
… handle Windows, Linux, etc.
#endif
End

Function ContainerControl(ewc As Control) As ContainerControl
If Not ewc IsA EmbeddedWindowControl Then
Raise New IllegalCastException()
End
Dim ref As WeakRef
Dim g As Graphics = EmbeddedWindowControl(ewc).Graphics
#if TargetCocoa
ref = ContainerControls.Value(g.Handle(Graphics.HandleTypeCGContextRef))
#else
… handle Windows, Linux, etc.
#endif
If ref.Value Is Nil Then
Return Nil
Else
Return ContainerControl(ref.Value)
End
End

End Module[/code]
Each container control will need to register in its open event:

Event Open() Self.Register() End
And then you can do this:

For i As Integer = 0 To ControlCount - 1 If Control(i) IsA EmbeddedWindowControl Then Dim cc As ContainerControl = ContainerControl(Control(i)) // handle container controls Else // handle all other controls End Next

This solution is much faster than iterating over all runtime objects in large projects (and I should know as ControlOrContainerControl posted above by Jean-Yves was a solution I introduced to the forum years ago).

Then thank you Eli for the first code, which satisfies my needs so far : I have only 4 or 5 such classes and 10 objects on the window, it works just fine, and the extra time needed to iterate is not an issue.

For big numbers of CC, though, it can make a lot of difference. I know some projects can carry hundreds of them.

Would seem to me that grabbing the graphics reference of an object outside the paint event is suspect

My applications hold all data in memory (amateur-ORM-like). This means that for every container control the iteration over all runtime objects (including this ORM-data of several 100k record objects) can literally take seconds.

Only the handle of the graphics object is read. Should this ever be a problem (currently it isn’t), the registering could be moved to the first call of the container control’s paint event.

I don’t understand why Feedback case 23030 posted by Christian Schmitz has not yet been implemented. A simple property on EmbeddedWindowControl returning the ContainerControl instance is in “Reviewed” state" for almost four years. Really Xojo? This is an important thing – and a rather small thing – to implement. Please please please…

If Xojo is not implementing that functionality until November 8, I’m gonna vote for Trump! Oh, I’m not a US citizen, so I cannot vote. So if Xojo is not implementing that functionality, I’m going to build a wall between Europe and the US – and Mexico is going to pay for it.

Why not use cc.Handle instead of cc.Graphics.Handle?

And shouldn’t there be a mechanism to remove nil WeakRefs?

[quote=273813:@Jean-Yves Pochez]containercontrols are not controls …
you must use something like this : …
[/quote]

Thank you so much, Jean-Yves, from me, too. Finally I understood what’s going on with my containerControls! :slight_smile:

glad you liked it.
sadly, there is still no xojo implementation to get easy access of the container list in a window.
please Xojo ? it should not be that difficult to implement ? easier than API 2.0 :wink:
or may be it will be in API 2.0 ?