Me or self from Button Class to Timer on Window

I know this is a dumb one, but I just can’t find the answer.

Working with a custom tooltip code. Not specifically needing this tooltip, but the concept of how it works is what I am learning from for other ideas.

I have a window with a BevelButton.

Window also has a timer ( TooltipTimer1 ).

MouseEnter sets some global variables ( in the properties of a module ) and then sets off the timer:

  TTipXPos = me.left + self.left + me.width
  TTipYPos = me.top + self.top
  TTipMessage = "123" + chr(13) + "with two lines of text"
  TTipDisplayed = True
  TooltipTimer1.Period = ToolTipDelay
  TooltipTimer1.Mode = Timer.ModeSingle

Now I want to customise the BevelButton, so that I can add some other properties, methods, etc.

So I create a Class called AppMenuButton, Super = BevelButton
In the Class I then add Event Handlers > MouseEnter

and then change the Super of the BevelButton on the Window to AppMenuButton

The above code will not compile.

Error :

This item does not exist
TooltipTimer1.Period = ToolTipDelay

So I try :

me.TooltipTimer1.Period = ToolTipDelay
error :
Type "AppMenuButton" has no member named "TooltipTimer1"

and then try :
self.TooltipTimer1.Period = ToolTipDelay
error :
Type "AppMenuButton" has no member named "TooltipTimer1"

self.Window.TooltipTimer1.Period = ToolTipDelay
error :
Type "Window" has no member named "TooltipTimer1"

So what am I missing, or is not just not possible for an instance of a button to set the properties of a timer on the window where the instance exists ?

Your BevelButton subclass doesn’t know anything about the window it lives on. In the constructor you need to add a parameter for the window. Then a property for the window.

Now you can write:

TTipXPos = self.left + theWindow.left + self.width TTipYPos = self.top + thewindow.top TTipMessage = "123" + chr(13) + "with two lines of text" TTipDisplayed = True

Now the timer is a bit more complicated. Hunt something down that is called “Delegating Timer”. This should be mentioned here on the forum a couple of times. Add this to your project. Now you can instantiate your timer in code and add the functionality for it.

If you have any problems then make an example and post it.

Thank You for the reply.

So are you saying that I should :

  1. add a property to the button subclass, let’s call it ‘OwnerHandle’
  2. when adding the instance of the button to the window, set the instances OwnerHandle property as the Windows handle.
  3. use OwnerHandle.TooltipTimer1 to activate the timer.

Alternatively, if I knew the name of the timer, would it be possible to :

  1. loop through all the open windows
  2. loop each control on the window
  3. if the control name = the timer name I am looking for, use the window name or handle to activate the timer ?

[quote=186561:@Dave OBrien]Thank You for the reply.

So are you saying that I should :

  1. add a property to the button subclass, let’s call it ‘OwnerHandle’
  2. when adding the instance of the button to the window, set the instances OwnerHandle property as the Windows handle.
  3. use OwnerHandle.TooltipTimer1 to activate the timer.[/quote]

Is the code in the class, or in the instance ? The class won’t be able to see the timer on the window.

What you may want to do, if you want to use a timer from the CustomBevelButton class, is to add a Timer property to the class, let us call it ToolTipTimer, then

  • Add a method called ToolTipTimerAction :

Sub ToolTipTimerAction(Sender as Timer) msgbox "Picaboo" // Whatever you need done Sender.enabled = False End Sub

  • In the class Open :

Sub Open() ToolTipTimer = New Timer AddHandler ToolTipTimer.Action, AddressOf ToolTipTimerAction End Sub

  • In MouseEnter :

Sub MouseEnter() dim ToolTipDelay as integer = 1000 TooltipTimer.Period = ToolTipDelay TooltipTimer.Mode = Timer.ModeSingle ToolTipTimer.enabled = True End Sub

  • In Close :

Sub Close() RemoveHandler ToolTipTimer.Action, AddressOf ToolTipTimerAction End Sub

OK. So it looks like coding in subclasses of controls, like a button, is basically limited to interacting with itself only, and for receiving properties from the window that creates the instance.

There is no real simple way of passing info / data / results / setting properties back to the ‘owner’ window from the instance of the button ( meaning from code in the subclass of the button before an instance is created ).

So if I want to have a subclass of a button that changes backcolor when the mouse moves over it, it is coded in the subclass before the instance.

But if I want to interact with the other components of the window that created the instance of the button ( like the timer ), it is best done in the code of the created instance that is on the window.

Does that sound about correct ?

Now I am starting to think that the subclass code for the instance of the button could change a global variable, and the timer could be checking that global variable to do the required actions. So the timer runs every second, but does not do anything until the button has ‘populated’ the activation variable.

[quote=186566:@Dave OBrien]OK. So it looks like coding in subclasses of controls, like a button, is basically limited to interacting with itself only, and for receiving properties from the window that creates the instance.

There is no real simple way of passing info / data / results / setting properties back to the ‘owner’ window from the instance of the button ( meaning from code in the subclass of the button before an instance is created ).

So if I want to have a subclass of a button that changes backcolor when the mouse moves over it, it is coded in the subclass before the instance.

But if I want to interact with the other components of the window that created the instance of the button ( like the timer ), it is best done in the code of the created instance that is on the window.

Does that sound about correct ?[/quote]

The class (CustomBevelButton) basically does not have any reference to the window. In fact, it is in limbo and does not get into existence until an instance materializes it.

Changing backcolor is as simple as me.backcolor = &cFF0000

But if you want to interact with other controls on the window, it should be done in the instance event handler.

If you want to use the MouseEnter event in both the class and the instance, add a MouseEnter event definition to the class, and in its MouseEnter Event, place :

RaiseEvent MouseEnter

If every occurrence of your subclassed button will end up on the same window and you know which window, you can call items of that window from the event handlers defined in your button.

Window1.Timer1.Mode = Timer.ModeSingle

Use the Window property of the BevelButton and cast it to the window class you have created the timer:

Window1(Self.Window).Timer1.Enabled = False

[quote=186575:@Eli Ott]Use the Window property of the BevelButton and cast it to the window class you have created the timer:

Window1(Self.Window).Timer…[/quote]

Thank You Eli

This worked perfectly in the code in the subclass of the button.

When the instance is created on the Window, it activates the timer exactly as required. So it does only need coding once in the subclass, and works in all instances … only restriction seems to be that coder must know then name of the window ( Window1 ) that the timer and button instances exist on - in this case I do, so it is a perfect solution.

Thanks again and also Thanks to everyone for their input. I have learnt loads again :slight_smile:

Well, this is not really a restriction as you need to somehow check if the window has a timer. There are several possibilities:
Wrap everything in your BevelButton subclass related to the timer in If … Then tests:

If Self.Window IsA Window1 Then Window1(Self.Window).Timer1.Enabled = False ... End
Or you could loop over all controls of the window to check if one is a timer. This will only work if the timer has been added to the window in the window editor (so it was added as a control). Note that this is independent of the kind of window, it works with any window, not only Window1:

For i As Integer = 0 To Self.Window.ControlCount - 1 If Self.Window.Control(i) IsA Timer Then Dim t As Timer = Timer(Self.Window.Control(i)) t.Enabled = False ... Exit For i End Next
Or you could use introspection to access the timer, for example should the timer be a property and not a control on the window.