Event definition for dummies (me)

I have a container control with three different textfields inside.
I would like to have an event for this container that will fire when a property was changed and do some calculations with these textfields.

An event “property xy has changed” would be enormous helpful to do the job. But the manual keeps as a secret how to define an Event - or I was to blind to find it.

Using the “Add to”-command I am able to add a Event Handler, but I can’t put any defining stuff into it.

Please! Show me a way!

Go past ‘Event Handler’ and select ‘Event Definition’. Then you can name, set it’s parameters and return type. It’s always marked private so you can only call it from within the object it’s defined in. Call it like a method or use RaiseEvent in front.

You didn’t add an “Event Handler”, you defined an “Event Definition”.

As an example in your container control class you add an “Event Definition” like that:

Sub MyPropertyHasChanged()

In the code in your container control class when the property changes, put this code:

RaiseEvent MyPropertyHasChanged()

The you drag the container control class onto a window. Click on the instance of the container control in the window. Then via the menu add an “Event Handler”. Choose MyPropertyHasChanged. There you can put your code:

Event MyPropertyHasChanged() MsgBox("MyProperty has changed") End

1 Like

It took a while to understand. When I gave it a try it made me understand. Thanks a lot for helping!

My this are not working?

New Class
ToolbarHover as Toolbar
Event Definition
Event MouseMove(X as Integer, Y as Integer)
Event MouseEnter()
Mothods
Public Sub MouseEnter()
RaiseEvent MouseEnter
End Sub
Public Sub MouseMove()
X = system.MouseX
Y = system.MouseY
RaiseEvent MouseMove(X,Y)
End Sub
Properties
X as Integer
Y as Integer

In a Window
on ToolbarHover1

Sub MouseEnter() Handles MouseEnter
Label1.Value = “Mouse in Toolbar”
End Sub
Function MouseMove(X as Integer, Y as Integer) Handles MouseMove as Integer
Label1.Value = “X:” + X.ToText + " Y:" + Y.ToText
End Sub

[quote=466116:@Horst Jehle]Public Sub MouseEnter()
RaiseEvent MouseEnter
End Sub
[/quote]
Is that a Method or an Event Handler? Ie., did you add the event to the ToolbarHover class? Or did you add it as a method?

These are my definitions:

The code belongs in the events, not in methods with the same name.

[quote=466116:@Horst Jehle]My this are not working?
[/quote]

Typically when you create Event Definitions, you call the RaiseEvent <MyEventDefinition> from within a corresponding actual Event, as @Tim Hare pointed out.

But in your case Horst, the Toolbar control does not have any mouse related events. In the linked page it says “Although Toolbar inherits from RectControl, it has no mouse-related events. This is due to limitations of the operating system”.

I was hoping to do something similar a little while ago, and ran into the same problem.

Technically speaking, you can call RaiseEvent from within a Method, but you need something to call the Method in the first place - so that sort of limits what kind of events you can wire-up that way.

I hope that helps.

[quote=466116:@Horst Jehle]My this are not working?

Event MouseMove(X as Integer, Y as Integer)
Event MouseEnter()
[/quote]

Since essentially the ToolBar is an overgrown window bar, I believe you cannot use the window MouseMove, since it will not work over the toolbar (untested).

But you could implement a general MouseMove monitor with a timer which gets the position of the mouse with System.MouseX and system.MouseY.

It will work over the toolbar, as over the entire screen. You could use a 20 ms period when the mouse is anywhere but in the toolbar (1/50 second), and shorten it when the mouse is over the toolbar, to get a higher resolution, as a normal MouseMove would. Something like 10 ms will give you a 1/100 second, which should suffice. The Mac will provide such a short interval. Under Windows, if I am not mistaken the build in timer cannot go faster than 60ms, but you can use MBS plugins timer which provides much shorter intervals.

Use a static variable retaining the last X and Y position to detect when the mouse enters or leaves the toolbar, so you can execute the ad hoc corresponding myMouseEnter and myMouseExit methods.

That’s an interesting suggestion Michel, I’ll have to check into that myself, when I have time.

Thank you.

It is Sunday, I like a programming challenge, and programming is better than crossword puzzles…

Here is a toolbar with MouseMove, MouseEnter, and MouseExit, based on the principles I outlined above.

I finally did not accelerate the timer when inside the toolbar. A 1/50th second is sufficient for most applications. You can always modify the period in the class’ Open event.

To use, drag in the left pane of the IDE, and then drag over the window. Add the extra events like you would with any other control.

I intentionally created it in 2017R2.1, so it should be compatible with all versions.

Enjoy :slight_smile:

ToolbarWithMouseMove.xojo_binary_code.zip

1 Like

[quote=466522:@Michel Bujardet]It is Sunday, I like a programming challenge, and programming is better than crossword puzzles…

Here is a toolbar with MouseMove, MouseEnter, and MouseExit, based on the principles I outlined above.

I finally did not accelerate the timer when inside the toolbar. A 1/50th second is sufficient for most applications. You can always modify the period in the class’ Open event.

To use, drag in the left pane of the IDE, and then drag over the window. Add the extra events like you would with any other control.

I intentionally created it in 2017R2.1, so it should be compatible with all versions.

Enjoy :slight_smile:

ToolbarWithMouseMove.xojo_binary_code.zip[/quote]

Thank you Michel, this was very generous of you to put this together for us.

Now that it’s Sunday, looks like I get to play with a new shiny widget :slight_smile:

All the best and thanks again!

Thank you again @Michel Bujardet. I recently spent some time implementing your ideas from the code you wrote into a project.

In the end, because I still wanted to be able to use the Toolbar designer in the IDE, as opposed to dynamically assigning the buttons at runtime to the Object/Super class you defined. I just added the Timer to the Open Event of the Window containing the Toolbar (the logic has to track the whole area of the Window anyway).

// add to Open Event of Window with an assigned Toolbar // use this method to have the Toolbar button hover text displayed in a custom Statusbar Canvas Self.TimerMouseMove = New Timer AddHandler Self.TimerMouseMove.Action, AddressOf Self.TimerMouseMove_Action Self.TimerMouseMove.Period = 200 Self.TimerMouseMove.RunMode = Timer.RunModes.Multiple
The following is the Timer logic, which calls a Method (MainToolbarHoverTextShow) that locates my particular buttons.

[code]Private Sub TimerMouseMove_Action(sender As Timer)
If Self.mainToolbar.Visible Then
#If TargetWindows
Var titleBottom As Int32 = 51 // fixed height of Windows Titlebar + MenuBar
Var toolbarBottom As Int32 = Self.TrueWindow.Top - Self.TrueWindow.bounds.Top
Var x As Int32 = System.MouseX - Self.TrueWindow.Left
Var y As Int32 = System.MouseY - Self.TrueWindow.Bounds.Top
#Else
Var titleBottom As Int32
Var toolbarBottom As Int32
Var x As Int32 = System.MouseX - Self.TrueWindow.Left
Var y As Int32
If Self.FullScreen Then
// in macOS Fullscreen mode, the Toolbar positioning behaves differently
titleBottom = 0
toolbarBottom = 63
y = System.MouseY
Else
// regular Window mode
titleBottom = 25 // fixed height of macOS Titlebar
toolbarBottom = Self.TrueWindow.Top - Self.TrueWindow.bounds.Top
y = System.MouseY - Self.TrueWindow.Bounds.Top
End If
#EndIf
Static previousX As Int32
Static previousY As Int32

If (x <> previousX Or y <> previousY) Then
  // only call Method to show text when mouse is in the Toolbar area above the main Window area
  If x >= 0 And x <= Self.TrueWindow.Width And y >= titleBottom And y <= toolbarBottom Then
    // following is a custom method that tracks location of my Toolbar buttons
    // and sends the appropriate text to the custom statusbar to show
    // note: only the "x" parameter is used in the following method, but
    // "y" was helpful debugging the vertical constraints of the Toolbar
    Self.MainToolbarHoverTextShow(x, y)
  Else
    // remove text from Statusbar or revert to previously shown static message
    Self.mainStatusBar.ResetToPrevious
  End If
End If

previousX = x
previousY = y

Else
sender.RunMode = Timer.RunModes.Off
End If
End Sub
[/code]
Inside MainToolbarHoverTextShow, the hover text (not the Tooltip property) associated with each of those buttons is then sent to my statusbar.
In the end, this gave me the ability to show extended information in my statusbar while hovering over specific buttons.

Hopefully this macOS/Windows Timer logic is also helpful to others. Thanks.

@anon93744516 & @Michel_Bujardet : I played around with the Toolbar, and actually there is a way to subclass the Toolbar and be able to use the editor, and keeping everything contained.

  1. Add a Toolbar to your Window
  2. Right-click the Toolbar and select “New Subclass”
  3. You can edit the super class with the Editor (and it will show up in the subclass), and you can customise the subclass to your hearts content.