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
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.
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.
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
or may be it will be in API 2.0 ?