Question

It is many years since I did anything with FoxPro, but I have a legacy system that needs work. Okay, I can call a COM-based application such as MapPoint or Excel from FoxPro. I've done that before. However, how do I pass a function or object method as an event callback? Is it even possible? (I can't find anything online or the FoxPro books I've managed to track down)

The following is a VB6 example of what I mean, taken from the MapPoint documentation. As it happens OnConnection() is itself a callback; but the call to moaApp.AddCommand() passes a reference to a callback function ( SayHello() ) to MapPoint (moApp), as a menu callback. Not that it matters for the question, but I'm probably going to need to trap the Save, Quit, and Menu callback events.

Dim moaApp As MapPoint.Application
Public Sub SayHello()
MsgBox "Hello"
End Sub

Private Sub AddinInstance_OnConnection(ByVal Application As Object, ByVal ConnectMode As
AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst As Object, custom() As Variant)
On Error GoTo error_handler

Set moaApp = Application

'Add this command to the menu (HOW DO I DO THIS IN FOXPRO?)
moaApp.AddCommand "Saying Hello", "SayHello", Me

Exit Sub

error_handler:

MsgBox Err.Description

End Sub
Was it helpful?

Solution

Thanks to the lead from @Alan B, I've managed to get it working...

Events are caught by creating a COM class that implements the required event interface. All events in the interface have to be implemented, although they can be empty implementations.

E.g.

&& Create an event handler
oHandler = CREATEOBJECT("MapPointEventHandler") 

&& Connect our _ApplicationEvents implementation
EVENTHANDLER( oMyMapPointApp, oHandler)


&& Here is our event handler

DEFINE CLASS MapPointEventHHandler AS Session OLEPUBLIC 
IMPLEMENTS _ApplicationEvents IN "MapPoint.Application"

 && Call back when MapPoint Quits

   PROCEDURE _ApplicationEvents_Quit()  
      MESSAGEBOX("QuitHandler called")
   ENDPROC

   && Event indicates MapPoint is about to close
   PROCEDURE _ApplicationEvents_BeforeClose( bcancel as logical) AS VOID
      MESSAGEBOX("before close called")
   ENDPROC

   && These events are not used here, but must be defined for COM/class compatibility
   PROCEDURE _ApplicationEvents_BeforeSave( SaveAsUI AS logical @, bcancel as logical) AS VOID
      *? PROGRAM()
   ENDPROC
   PROCEDURE _ApplicationEvents_New() AS VOID
      *? PROGRAM()
   ENDPROC
   PROCEDURE _ApplicationEvents_Open() AS VOID
      *? PROGRAM()
   ENDPROC    

ENDDEFINE

Methods can also be passed (eg. for menu items), but these cannot be to the same class. You need to implement one class for each event handler interface you wish to implement, and a separate class to handle the menu callbacks.

Here is an example with a menu item:

&& Create a menu handler
oMyMenu = CREATEOBJECT("MapPointMenuHandler") 

&& Add our Tools menu entries and hook them up
oMyMapPointApp.AddCommand("Custom Menu Item", "MyMenuCallBack", oMyMenu)


&& This class implements the Tools menu callbacks
&& *** NOTE: MessageBox will appear UNDER MapPoint

DEFINE CLASS MapPointMenuHandler AS Session OLEPUBLIC 

   PROCEDURE MyMenuCallback()
      MESSAGEBOX("Main Menu callback")
   ENDPROC  

ENDDEFINE  
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top