Is there an elegant way to stop controls firing when clicking to bring a window to the front? For example, I click on an inactive window and my canvas based button records a mousedown event and starts doing something that may not have been expected.
I can only think of starting a timer on window.activate and ignoring events shortly after.
[quote=233293:@Stephen Dodd]Is there an elegant way to stop controls firing when clicking to bring a window to the front? For example, I click on an inactive window and my canvas based button records a mousedown event and starts doing something that may not have been expected.
I can only think of starting a timer on window.activate and ignoring events shortly after.[/quote]
I believe setting enable = False for all controls by looping through Window.Control() would do the trick.
On Mac it’s standard behavior that clicking down on a button on a window that’s behind does start the button press, as well as bring the window forward. Not sure what Windows and Linux do.
Maybe the problem is you’re firing the Action from MouseDown. If so you should do it from MouseUp and it’ll act like standard buttons (at least on Mac). Something like this for a Canvas subclass…
[code]Private Property isDown As boolean
Event Action()
Function MouseDown(X As Integer, Y As Integer) As Boolean
isDown = true
Invalidate
return true
End Function
Sub MouseDrag(X As Integer, Y As Integer)
if isDown <> inside(X, Y) then
isDown = not isDown
Invalidate
end
End Sub
Sub MouseUp(X As Integer, Y As Integer)
isDown = false
Invalidate
if inside(X, Y) then RaiseEvent Action
End Sub
Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if isDown then g.ForeColor = &c00FF00 else g.ForeColor = &c808080
g.FillRect 0, 0, g.Width, g.Height
End Sub
Private Function inside(x As integer, y As integer) As boolean
return x>0 and x0 and y<height
End Function[/code]
[quote]
What if you subclass your controls and windows.
Add the following to the subclassed window:
Boolean property: Active
Eventhandler: Activate
Eventhandler: Deactivate[/quote]
The question is, does the activate event fire consistently on Mac and PC before the mousedown event?
Yes, true. And I probably should allow the click. It’s just that I have controls that appear only on mouseover near the area and the mouseover doesn’t function when the window is inactive so… you click on a blank area and the control suddenly appears out of nowhere and gets clicked - surprise!
[quote=233710:@Stephen Dodd]
Yes, true. And I probably should allow the click. It’s just that I have controls that appear only on mouseover near the area and the mouseover doesn’t function when the window is inactive so… you click on a blank area and the control suddenly appears out of nowhere and gets clicked - surprise![/quote]
The ultimate solution : Place your controls inside a PagePanel or on top of a Canvas or inside a ContainerControl so you can make them all invisible.
In the Deactivate event, DrawInto the window in the window Backdrop.
Make the controls invisible (change Page, make the containing control invisible).
Upon Activate, or in a small period timer, nil the window backdrop and reinstate the controls visible.
So when the window is in the back, all it shows is a picture.
Ha, I read this and looked over to my movie playing app with buttons like this and they work the way you want. Opening the project the button class is pretty much what I posted above except there’s MouseEnter and MouseExit events which control an isShowing property for the hover.
[code]Sub MouseEnter()
if not System.MouseDown then
isShowing = true
Invalidate
end
End Sub
Sub MouseExit()
if not System.MouseDown then
isShowing = false
Invalidate
end
End Sub[/code]
Basically there’s a property that says when to show the widget, but it’s only flipped in MouseEnter/Exit when the mouse is up (if it’s down then the MouseDown/Drag/Up sequence handles it).
The thing is, when the window is behind and the button clicked, MouseDown comes first, then MouseEnter. This means isShowing will be false in MouseDown, so discriminate on that…
Function MouseDown(X As Integer, Y As Integer) As Boolean
if isShowing then
isDown = true
Invalidate
return true
end
End Function
You should check that MouseEnter comes after MouseDown on Windows OS.