Wiki Home

BINDEVENT


Namespace: SoftwareEng
BINDEVENT() is a function in VFP 8.0 that allows you to delegate functionality between components. You can bind to Properties and Methods as well as Events.
This function, when used with RAISEEVENT(), makes up the powerful Native Event Binding scheme demonstrated in Event Binding Sample. BINDEVENT was enhanced in VFP9 to allow VFP applications to bind to Windows Messages.

One usage guideline I have is that I never BINDEVENT() to a native VFP method. Instead, any native method to which you want to bind, should be over-ridden with a new event raised. For example, lets say you want to bind to the ADDOBJECT() of a class. What you really want to do is write your own ADDOBJECT() for the class that has the following line:

RaiseEvent(this, "ObjectAdded", newObjectReference)

and create an ObjectAdded event (ie, create an ObjectAdded method) for the class that accepts one parameter. Then you can BINDEVENT() to this new ObjectAdded event and you'll be good to go. The reason for this guiding line is binding to native events (like a Click() event of a command button or an ADDOBJECT()) often gives squirrely behavior, and the design just isn't as clean.

Using BINDEVENT() with only developer defined events raised using RAISEEVENT() will give you the most solid behaivor with the most decipherable class design.

According to the FoxPro 9 help topic, "Language Enhancements" within "What's New in Visual FoxPro", we now have "Windows Message Event Handling". One of the events this topic lists is "Interception of screen saver queries to stop the screen saver from activating."

Has anyone figured out how to actually implement that?

I thought I could utilize the sample provided in that help topic for detecting a Theme change and modify it for stopping a screen saver, but I cannot find enough useful information at the MSDN site or elsewhere. And, even if I discovered the nMessage number for this, I still don't know how to actually stop the screen saver activation!

I have a VFP 8 application (currently being ported to VFP 9) with a long-running process. One of two events occurs when a screen saver activates, and the user has configured the screen saver to require a password to get back to work:

For the first case, since the long-running process involves a loop that checks for an Escape keypress, I can only guess that somehow it is getting such a keypress when the screen saver is deactivated, even though I don't actually press the Escape key. (That guess is probably a long shot, but I don't know how to avoid the interruption in any case.)

If I can intercept and cancel the activation of a screen saver during my loop, I am hoping that that will solve my problem.

Any ideas?

-- Robert Chaffe

Notes on Simple Method Call

Calling bindevent with nFlags=2 states that: "Do not trigger event (call delegate code) by simple method call." in the help file.

This means if you bind an event to a button click, the delegate code will not get triggered if you call the button click event directly by thisform.command1.click(). However it will still be triggered if (1) you click the button, or (2) you call raiseevent(thisform.command1, "click").

Perhaps a better name of this is Direct Method Call.

-- David Fung



How can I determine the object that raised the event when in the Delegate method? eg. I have a grid on a form and I want to implement a sort on column header click.

... code to initialize the grid and assign values to the header tag ...

FOR EACH oColumn IN thisform.Grid1.Columns
bindevent(oColumn.Header,"Click",thisform,"OnHeaderClick")
ENDFOR


PROCEDURE OnHeaderClick
oHeader = ???? && Which column header was clicked?

SET ORDER to tag (oHeader.Tag) IN (thisform.Grid1.RecordSource)
ENDPROC


I know there are alternatives like
- Have a seperate Delegate for each Column.Header.Click()
But this is not scalable - I have to predefine each Delegate

- Subclass the Header
This means I can't use a standard VFP grid control


Is this possible?


-- Kevin Goh

You can do this in your OnHeaderClick method to determine the event's source object:
local arrEvents[1]
local oHeader as header
dimension arrEvents[1]
aevents(arrEvents, 0)
oHeader = arrEvents[1]



Thanks!


.Value propery is bindable . That's how i implement Control Source in custom controls. Pass the Control Source to a textbox that acts as proxy, then bind to that textbox's Value property to know when its value was changed. The ProgrammaticChange doesn't trigger when textbox's value gets changed via Control Source.

Protected or Hidden methods can be used as delegates (probably as sources too) as long as the BINDEVENT() function executes in a scope where the methods aren't hidden (like in class's init method). I hide the delegate methods since they act only on the internals of the class.

-- edyshor


Note that this is the proper name for what has been referred to elsewhere around this site as BindEvents [sic].

Contributors: Mike Helland, Stuart Dunkeld
( Topic last updated: 2010.04.08 10:52:52 AM )