Enhancing ContainerControl
· Dec 26, 01:28 PMThe Canvas and ContainerControl classes provide no hook to implement behavior when they are hidden. For Mac OS composited windows in particular, this makes it more difficult to implement custom controls. But with a bit of work, it is possible to add your own hooks.
The hooks I would like are events VisibilityChanging and VisibilityChanged. For ContainerControl, this is almost straightforward; it has methods Show and Hide, inherited from Window. So we define a subclass BetterContainerControl of ContainerControl; note that this should be something created with ‘New Class’, not ‘New ContainerControl’.
Next, we add event definitions
Sub VisibilityChanging()
and
Sub VisibilityChanged()
to BetterContainerControl.
Then we override Show and Hide to call the event handlers.
Sub Show()
if me.Visible then
return
end if
VisibilityChanging
super.Show
VisibilityChanged
End Sub
Sub Hide()
if not me.Visible then
return
end if
VisibilityChanging
super.Hide
VisibilityChanged
End Sub
Unfortunately, a feedback prevents this code from compiling.
A workaround is to cast the reference me to Window, and call Show/Hide on it. Here is the code for Show.
Sub Show()
if me.Visible then
return
end if
VisibilityChanging
Window(me).Show
VisibilityChanged
End Sub
Perhaps you’re wondering why this does not result in a StackOverflowException; I can only suppose that it is a consequence of the problem that causes us to resort to this trick. For now, it works.
And now, a quick test; add a new ContainerControl, named ContainerControl1, to a project, and set its superclass to BetterContainerControl. Drop one into a window, add some beeps to the VisibilityChanging and VisibilityChanged event handlers.
Add a PushButton to the window, and implement its Action event handler.
Sub Action()
if ContainerControl11.Visible then
ContainerControl11.Hide
else
ContainerControl11.Show
end if
End Sub
A quick test run shows that this all works. Now I replace the code above with
Sub Action()
ContainerControl11.Visible = not ContainerControl11.Visible
End Sub
and test again — no beeps. There is a faint smell of code duplication coming from the Rb framework; perhaps Hide, Show and Visible.Set are not calling the same code.
Unfortunately, we cannot override ContainerControl.Visible because it is a computed property. What we can do, however, is shadow it.
Property Visible As Boolean
Get
return ContainerControl(me).Visible
End Get
Set
if value = me.Visible then
return
end if
if value then
me.Show
else
me.hide
end if
End Set
The result is a ContainerControl with events to be implemented when its visibility is changed.
We can do the same for Canvas: write a subclass, add the event definitions, and add a computed property Visible that shadows Canvas.Visible.
Property Visible As Boolean
Get
return Canvas(me).Visible
End Get
Set
if value = me.Visible then
return
end if
VisibilityChanging
Canvas(me).Visible = value
VisibilityChanged
End Set
With this, you can now get custom controls on windows to be hidden when they should be.
Comment
Commenting is closed for this article.
External functions cannot use objects as parameters Retrieve the Reply Error From an Apple Event
Thanks for writing this. I’ve often needed this.
BTW, I doubt that it’s the feedback that’s causing the first attempt not to compile – it’s rather the bug that’s responsible for it :o)
— Thomas Tempelmann · Dec 26, 04:59 PM · #