I have a DesktopContainer, an instance of which I put on a window in the IDE. This container has a few properties and that’s all (for now), I also added a vertical scrollbar control to the window. The intention is that instances of another DesktopContainer will be created at runtime and Embedded-Within the first container and located one below the next with the scrollbar used to scroll up and down to look and one and then another. This all works.
Now I want to use the MouseWheel event for the scrolling, and if I implement that on the first, main, container, then it scrolls nicely. But only if the mouse is over a part of that first container which is not covered by my runtime instances of the second container.
So I thought to use AddHandler to add a MouseWheel event to each instance of teh second container that is embedded within the first. Code looks like this:
while (reg.AfterLastRow=False)
mv = new MailView
MailViewer.mvs.Add (mv)
mv.EmbedWithin (MailViewer)
mv.absid = reg.Column("absid").IntegerValue
mv.mboxid = mboxid
mv.Left = 10
mv.Width = MailViewer.Width - 40
mv.Top = 10 + (MailViewer.mvs.LastIndex * (10+mv.Height))
AddHandler mv.MouseWheel, AddressOf MainWindow.ScrollHandler
reg.MoveToNextRow ()
wend
However scrolling while the mouse is over one of the embedded containers has no effect. Putting a break at the first line of ScrollHandler (a method on MainWindow) shows that it is not called. Why is this? Or should I be approaching this in a different way?
Hmm. How this should work is you would leave all the MouseWheel handlers blank in the embedded controls, which propogates the event down to the control behind the current control. Eventually, if this is true for all the controls on the embedded control, as well as the embedded control itself, the containing control will receive the event, which is what you’re looking for.
My hunch is that the very last step isn’t happening for ContainerControl reasons. They sometimes act like windows, and my guess is that it is eating the event instead of passing it downwards.
Try this: place a Canvas over the containing control - importantly, it must not be a child of the containing control, it just needs to be on top of it. Have the Canvas intercept the MouseWheel event and pass it on to the containing control using the ScrollHandler method you created. That should work.
OK. Checking further I found an issue with the MailView container, which in this test has two controls within it - a Canvas, and an HTMLViewer. Of course I’d forgotten to remove a MouseWheel event handler from the canvas. Removing that allowed wheel scrolling when the mouse is over the canvas. So far so good.
The HTMLViewer is more problematic, as it doesn’t implement the MouseWheel event. Unless there’s another way, I may have to inject some javascript into the HTMLViewer to call back to the Xojo side to do the scrolling. I don’t know how performant this will be. It may look clunky on all platforms. But I can move the event handler onto the container I’m embedding and not use AddHandler. Or I can try your overlay canvas suggestion.
The takeaway is that I should have checked I didn’t have spurious events handlers kicking around.
Edit: I tried the overlay and it worked first time so thanks.
Awesome! Keep that technique in your back pocket - you’ll need it again some day.