Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

callback function raising an event

Posted on 2003-03-21
23
Medium Priority
?
410 Views
Last Modified: 2010-04-07
What is the best way to have a callback function raise an event located in a class module?

Scenario:
I have a timer class that is bound to a callback function.  The callback function get's called within a timer interval specified.  As you all know the callback function has to be in a standard module and not a class module.

I want that callback function to raise an event inside the same timer class, how can I do this?

I don't want to use any forms, so that solution is not an option.
0
Comment
Question by:aeklund
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 6
  • 6
  • +1
23 Comments
 
LVL 28

Expert Comment

by:AzraSound
ID: 8184083
Well, as you know, you can not raise events from a standard module, so you are left with either having your module just "know" a function in your class it can call, or you can be more "technically correct" and have your class implement a particular interface that the standard module can then call a method of.
0
 
LVL 10

Author Comment

by:aeklund
ID: 8184170
I have Class "A" that references my Timer class.  It sets a timer with an interval of 60 seconds...  Now when 60 seconds it reached, it called a callback function in a standard module.  Now how can I get that callback function to reference the instance of Class "A" that set the timer?

I don't want to hard code any function names inside the timer class or the callback function.  This way I can use this timer class for multiple projects.
0
 
LVL 3

Expert Comment

by:emadat
ID: 8184264
Refer to the article:
http://archive.devx.com/upload/free/features/vbpj/2000/02feb00/mc0200/mc0200.asp

If you can call the callback function with the AddressOf(your class specific function), then I think using the technique discussed in this article will help you.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8200071
Setting your call back function you ue the AddressOf against an object.

Sub SetCallback(CallBack as Object)
CallbackAddress=AddressOf(CallBack)
...
End Sub

That way, you merely:

SetCallback Me.Thisfunction
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 8203002
Unless you are using some API that expects a function pointer, the AddressOf suggestion probably won't do you any good because pointers to VB functions can't be passed within VB.

>>I don't want to hard code any function names inside the timer class or the callback function.  This way I can use this timer class for multiple projects.

Regardless, it sounds as if the timer class and the standard module work together.  The standard module needs to be able to reference your timer class in some way.  To allow this to work with any other class, provide an interface that any other class must implement, e.g.,


'class ITimerFriend

Public Sub OnTimerInterval()
End Sub



From within Class "A" (ClassA):

Implements ITimerFriend

Private Sub ITimerFriend_OnTimerInterval()
    'code for class A to execute on timer interval
End Sub





From within Timer Class (ClassTimer):

Private m_objTimerFriend As ITimerFriend

Public Property Set TimerFriend(NewTimerFriend As ITimerFriend)
    Set m_objTimerFriend = NewTimerFriend
End Property

Public Sub DoSomething()
    'something that calls callback function in std. module
End Sub



The timer class calls the callback function in your standard module, passing in as a parameter, this reference to the TimerFriend object.  Then in your callback, you an do:


Public Function MyCallback(TF As TimerFriend)
    'do stuff

    Call TF.OnTimerInterval
End Function




An example of how this may be implemented from a client interface:


Dim objA  As New ClassA
Dim objTimer As New ClassTimer


Set objTimer.TimerFriend = objA
Call objTimer.DoSomething
0
 
LVL 10

Author Comment

by:aeklund
ID: 8203557
Thanks for all you input... but perhaps I was a little unclear.  The callback function I'm using is a standard callback function, so I cannot specify any parameters...

Let me layout the battlefield to you guys and see if you can re-arrange my troops so that they work together:

'Class "Timer" (All the timer code)
Option Explicit

Private Declare Function SetTimer Lib "user32" _
  (ByVal hwnd As Long, _
   ByVal nIDEvent As Long, _
   ByVal uElapse As Long, _
   ByVal lpTimerFunc As Long) As Long

Private Declare Function KillTimer Lib "user32" _
  (ByVal hwnd As Long, _
   ByVal nIDEvent As Long) As Long

Private m_iTimer As ITimer
Private cTimers As New Collection
Public bTimerActive As Boolean

Public Function StartTimer(ByVal Milliseconds As Long) As Long
  Dim lTimer As Long
  lTimer = SetTimer(0, 0, Milliseconds, AddressOf TimerProc)
 
  cTimers.Add lTimer, CStr(lTimer)
 
  StartTimer = lTimer
  bTimerActive = True
End Function

Public Sub StopTimer(ByVal lTimer As Long)
  KillTimer 0, lTimer
  cTimers.Remove CStr(lTimer)
End Sub

'Module "basTimer" (The callback function)
Option Explicit

Private Sub TimerProc(ByVal hwnd As Long, _
                      ByVal uMsg As Long, _
                      ByVal idEvent As Long, _
                      ByVal dwTime As Long)
 
  Debug.Print hwnd, uMsg, idEvent, dwTime
End Sub


Now how from within this callback function can I reference the same instance of the class that called it?  I may want to use this code from within a user interface (form) or within another class, I am trying to write re-usable code.

In the callback function hwnd is always 0, umsg is always WM_TIMER, idevent is the actual timer that was created and is unique, this is how I can identify which timer is firing, and dwtime is just a what it is, the time of the timer.

I have increased the points since this is dragging on, and I am basically working on many projects and don't want to beat my head on this one...
0
 
LVL 28

Accepted Solution

by:
AzraSound earned 600 total points
ID: 8203820
I assumed you would be doing something to that effect.  There really is no way around it as the class module is dependent upon the call in the standard module.  You can still use interfaces as I indicated to make it appear somewhat seamless, but you must provide a way for the standard module to reference, at the very least, your timer class.  This may be well suited to compile as a DLL (your timer class and standard module).
0
 
LVL 10

Author Comment

by:aeklund
ID: 8204082
Hmm... I think I found a way...  here is what I'm thinking:

Declare a public variable in my module as a timer class

then in the timer class initialize event, set that variable to itself.. set variable = me

Now I have reference to the same class from within my module where the callback function is....

Now in my class event I create a friend sub to trigger a public event... and this event could not reside in my user interface, or another class module..

Does that sound like a feasable solution?
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 8204113
Exactly, but the main point being, your standard module MUST know about your timer class...there is no way around that.  Using a public variable to hold the particular instance is a method I have used myself.
0
 
LVL 10

Author Comment

by:aeklund
ID: 8204280
I'm not too familiar with Implementing classes and using polymorphism in VB.  I have not run into a situation where it is needed, or rather do not have enough knowledge on when best to use polymorphism.

Thanks for all you reply's, and the points go to you AzraSound for helping out and your solution was the closest thus far, and helped me work out the problem.

PS - When is it best to use implements and polymorphism?
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 8204328
>>When is it best to use implements and polymorphism?

It is best when you want to support many different entities that all share some common characteristics.  For example, perhaps you are creating some data gathering tool that can gather data from different devices.  Each device will have its own unique requirements, but they will probably share some common properties and functions.  These common links can be implemented in an Interface class.  Interfaces are good because you can create a common interface, and additional classes may be developed in the future that fit seamlessly into an application that works against that particular interface.  It is not used very often in development in VB that I have seen, but there are occassions when it is very beneficial (in the development of plugins for example).
0
 
LVL 10

Author Comment

by:aeklund
ID: 8204340
Gotcha... thanks.
0
 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8204349
The class module and standard module (that has the TimerProc which SHOULD be public or atleast Friend for the AddressOf to work) could be made to raise an event, passing off the 4 values from the timers (and perhaps filter some too).  Or perhaps use messages and watch the form's window for a specific message (from the timer), since you can make the Timer Start function require a valid hwnd and when that timer fires, send off a message to the window that set it.  Doing it with messages or events, compile (as AzraSound said) into a DLL and perhaps make the class Friend to the module and use the module as the DLL front end.
0
 
LVL 10

Author Comment

by:aeklund
ID: 8204463
Funky-

Yes, I realize the TimerProc should be public, when I pasted the code I forgot to make it public, because orginally I had the entire timer functions in one module and not split up into a class/module.  But how can it be used to trigger an event from the 4 values or a filter?

The way I solved it is to put a public variable inside the module that holds the TimerProc function that is set during the timer class initialization function and released on the termination function.

Also, to make this as generic as possible, I do not want to use the hwnd property, in case I want to incorporate this dll/timer class into another dll that does not have forms, so I would not have any hwnd to use therefore can not subclass it like you suggest to watch for window message.

If anyone is interested in my final solution, I would be more than happy to post it.
0
 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8216046
Funny thing is, we're both working on the same thing (I too am working on a DLL to handle input, but from more areas, keyboard, mouse and voice).  Mainly because I hate the keyboard software that came with my Internet keyboard (it's someone's idea of a joke, I know someone's laughed at it, I have a lot).  So, I'm working on the "guts" for now and then plan to make the front end.  Just a few quirks to figure out with respect to the wheels on the mouse (yes, wheelS).  Not found any journal ready code on finding their movement (and direction).  I know when they DO move, but not that.  So whats your keyboard dll for?
0
 
LVL 10

Author Comment

by:aeklund
ID: 8220742
Funky-
I'm not working on a keyboard dll, this is a timer dll, so I can create true timer and events without a form.

In a more wider description, this timer dll is going into a project I'm creating for monitoring directorys/folders for changes.  When a change is made an event is triggered.

I'm just about finished with the project, and so far everything is working out great...
0
 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8220920
Wouldn't hooking into the system file io (like virus checkers do) to monitor file changes be better than a timer?  (And I'm responding to too much lately it seems, all these hooking and dll questions flying about, I'm getting dizzy.)
0
 
LVL 10

Author Comment

by:aeklund
ID: 8220972
Yes, I could hook the file i/o, but this will be used for unc paths on other servers, and I don't know of any way to hook into a remove file i/o.. <g>
0
 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8225589
Would the servers be able to run an app?  Reason being, is hook them there and do a "broadcast" message to your "snooper-receiver" to tell it a change happened and where (less network traffic).
0
 
LVL 10

Author Comment

by:aeklund
ID: 8226349
Hmm... that is a good idea...  It would reduce traffic and would only trigger in the event something changed.. I like it... Thanks for the idea.
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 8226559
0
 
LVL 10

Author Comment

by:aeklund
ID: 8226641
Thanks, but that does not do everyting I want... something like this is more like it:

http://www.mvps.org/vbnet/code/shell/shchangenotify.htm

Which I have already played with awhile back.
0
 
LVL 1

Expert Comment

by:FunkyMeister
ID: 8228144
No problem aeklund.  I admin a local lan here and I hate it when activity happens without a "noticable" reason.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
This article describes how to use a set of graphical playing cards to create a Draw Poker game in Excel or VB6.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question