Design Time References (Monitor Designer Changes)

Version: 0.00.01 - last update: Sunday, September 27, 2009, 14:45:00

Previous EntryTips & Tricks HomeNext Entry 


All you have to know about how to monitor your top-level VFP designer session.

Intro

Many VFP-developers who are going to code some cool tools that work with a Form- or a Class-Designer session are faced with a common problem: How to monitor the existence of that designer session? Well, the first thing we have to do in such a case is to get a reference to the designer session in question. I wrote another article about this issue, you can read here.

The Problem

After having retrieved a reference to the object we have to deal with, wouldn’t it be nice to be noticed whenever another designer session gets activated (comes on top)? This can be done using Win-Event binding, but is only necessary/useful if we want to create a behaviour like VFP’s property window, which always shows the property set of the current active designer session (on top of VFP’s windows stack). In all other scenarios it is sufficient to be noticed when someone closes our designer session, that is, when we loose the reference to our target object within the designer host form.

I’ve seen a lot of older solutions (before Win-Event binding was introduced) using a timer that checks the existence of the captured object reference. Let me tell you, using a timer in VFP’s development environment we should try to avoid by all means! On the other hand, using Win-Event binding isn’t fiddling at all. Fortunately, there is a much simpler solution!

_ASSIGN() Comes to Our Rescue

When closing any VFP-Designer session, FoxPro does its best to release all references to the inner objects. This is the “event” we can hook on! All we have to do is to store the object reference of our target inside the designer window to a property of our tool class instance. Next, we have to create an _ASSIGN() method for that property. You might guess, what comes next…

At the moment, VFP shuts down the designer window, all inner objects get released by VFP, storing NULL values to any variable or property that holds a reference in addition. The only thing we have to do within our _Assign() method is to check the incoming value.

The Solution

DEFINE CLASS MyMonitor AS Custom

	PROTECTED oReference AS Object
	oReference = NULL

	PROTECTED FUNCTION INIT
		LPARAMETERS toRef AS Object
		LOCAL ARRAY la[3]
		IF NOT VARTYPE(toRef, .F.) == "O"
			IF ASELOBJ(la,3) > 0
				toRef = la[1]
			ELSE
				toRef = NULL
			ENDIF
		ENDIF
		THIS.oReference = m.toRef
	ENDFUNC

	PROTECTED PROCEDURE oReference_assign
		LPARAMETERS toObject AS Object
		LOCAL IsObject AS Boolean
		*\\ check if we've stored an obj.-ref.
		IsObject = VARTYPE(THIS.oReference) == "O"
		*\\ do the assignment
		THIS.oObject = toObject
		*\\ in case we are really releasing an obj.-ref.
		IF ISNULL(m.toObject) AND m.IsObject
			= RAISEEVENT(THIS, "EvtTargetReleased")
		ENDIF	
	ENDPROC
	
	PROCEDURE EvtTargetReleased
		*\\ This is an event you can bind to
		*\\ or fill with code in your subclass
	ENDPROC
	
ENDDEFINE

Utilizing an ASELOBJ() within the object’s INIT() isn’t the optimal solution. I’ve done it here to have an additional “fall-back behaviour”. You may want to keep the obj.-ref. retrieval code outside of the class – that’s absolutely okay! Utilizing the class within a larger context could be done like so:

loMySuperCoolTool = CREATEOBJECT("MySuperCoolToolClass")
WITH m.loMySuperCoolTool
   IF VARTYPE(m.loTarget) == "O"
      .AddObject("oMonitor", "MyMonitor", m.loTarget)
   ELSE
      .AddObject("oMonitor", "MyMonitor")
   ENDIF
   = BINDEVENT(.oMonitor, "EvtTargetReleased",;
	loMySuperCoolTool, "OnEvtTargetReleased",2)
ENDWITH

Previous EntryTips & Tricks HomeNext Entry