Advisor Discovery. Use BindEvent() to keep things in synch. BindEvent() Refresher. June, By Tamar E. Granor, technical editor

Similar documents
Taking Advantage of Idle Cycles. Make Your Application Work When the User Isn't. The Idea. The Strategy. December, 2003

Give users a control that makes entering dates as easy as it is in Intuit Quicken.

Advisor Answers. January, Visual FoxPro 3.0 and 5.0

Role-Based Security, Part III Doug Hennig

This tool lets you specify a new name for each control on a form or class and fixes all code that uses it.

Windows Event Binding Made Easy Doug Hennig

A New IDE Add-on: FoxTabs Doug Hennig

Combos and Lists - The Forgotten Controls

Q: I've been playing with the Microsoft Internet Transfer Control (inetctls.inet.1) and it would be great if only it worked.

The Mother of All TreeViews, Part 2 Doug Hennig

I Got Rendered Where? Part II Doug Hennig

The Ultimate Grid. Visual FoxPro 6 DORON FARBER. Structure of the Solution. Design Issues

Taking Control Doug Hennig

Understanding Business Objects, Part 1

Let's start by taking a look at the object generated by LIST OBJECTS. I used the following code to put a few objects in memory for testing:

Making the Most of the Toolbox

Splitting Up is Hard to Do Doug Hennig

Advanced Uses for Dynamic Form

Try Thor s Terrific Tools, Part 2

Give Thor Tools Options

IntelliSense at Runtime Doug Hennig

Custom UI Controls: Splitter

Cool Tools by Craig Boyd, Part II Doug Hennig

Manage Your Applications Doug Hennig

Put Event Binding to Work, Part 2

What's the Slope of a Line?

and I want the subsets with three members, the result would be:

It Might Be Valid, But It's Still Wrong Paul Maskens and Andy Kramek

Speed in Object Creation and. Destruction. March 2016 Number 49. Tamar E. Granor, Ph.D.

Top 10 (or more) Reasons to Use the Toolbox

A File Open Dialog Box Doug Hennig

Extending the VFP 9 IDE Doug Hennig

Azon Master Class. By Ryan Stevenson Guidebook #5 WordPress Usage

About this tutorial. The Lianja App Development process

Integrating Word's Spellcheck with Your VFP Application

Advisor Answers. Create Cross-tabs. July, Visual FoxPro 9/8/7

Try Thor s Terrific Tools

Working with the Registry. The Registry class makes it easy. The Registry Structure. January, By Tamar E. Granor

DATABASE AUTOMATION USING VBA (ADVANCED MICROSOFT ACCESS, X405.6)

Handling crosstabs and other wide data in VFP reports

05: A Gentle Introduction to Virtools

Frequently Asked Questions. Micro Filter

Azon Master Class. By Ryan Stevenson Guidebook #4 WordPress Installation & Setup

Manually Windows Update Vista Not Work In

Understanding Business Objects, Part 3

The Happy Project Hooker Doug Hennig

Manage Music Iphone 5

uilding Your Own Builders with BuilderB Doug Hennig and Yuanitta Morhart

Sharing the Calendar

mk-convert Contents 1 Converting to minikanren, quasimatically. 08 July 2014

Advisor Answers. Match multiple items in a query. December, 2005 VFP 9/8/7

Frame Editor 2 Manual

Manual Itunes Iphone 5 Not Working Ios 7 >>>CLICK HERE<<<

! Emacs Howto Tutorial!

MITOCW watch?v=rvrkt-jxvko

You can make certain sections of the text clickable by creating hyperlinks. Once clicked, these links navigate users to different

A New Beginning Doug Hennig

BBC Learning English Face up to Phrasals Mark's Mistake

More Flexible Reporting With XFRX Doug Hennig

Linked Lists. What is a Linked List?

How to Improve Your Campaign Conversion Rates

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting

jquery UI Widget Factory

The Crypt Keeper Cemetery Software Online Version Tutorials To print this information, right-click on the contents and choose the 'Print' option.

DoNotCall.gov: Do Not Call it up With Firefox

Windows 7 Disable Changing Proxy Settings Registry

CATCH Me if You Can Doug Hennig

PROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between

Basic Fiction Formatting for Smashwords in OpenOffice L. Leona Davis. Copyright 2012 L. Leona Davis All Rights Reserved

A File Open Dialog Doug Hennig

mid=81#15143

Google Apps Sync Installation Failed Outlook 2010

Lesson 1. Importing and Organizing Footage using Premiere Pro CS3- CS5

Manually Repair Windows 7 Update Service Not

/* Copyright 2012 Robert C. Ilardi

Customizing Access Parameter Queries

Getting Around the Member Pages

10 Strategies for Effective Marketing Campaigns

Troubleshooting Maple Worksheets: Common Problems

Azon Master Class. By Ryan Stevenson Guidebook #7 Site Construction 2/3

Pattern: Model-View-Controller (MVC) Beat Generator Example. Model-View-Controller. Model-View-Controller

Using IPv6. Daniel Hagerty

T Mobile Manual Contract Sim Only Business

Chrome if I want to. What that should do, is have my specifications run against four different instances of Chrome, in parallel.

Base Classes Revisited Doug Hennig

VFP: Ideal for Tools, Part 3

Java Programming Constructs Java Programming 2 Lesson 1

Zip it, Zip it Good Doug Hennig

Hard Reset Apple Tv 2 Without Remote

Out for Shopping-Understanding Linear Data Structures English

Can't Add Songs To Iphone From Itunes 11 >>>CLICK HERE<<<

FrontPage Help Center. Topic: FrontPage Basics


Advisor Answers. Clean up a Project. May, Visual FoxPro 9/8/7

MITOCW watch?v=flgjisf3l78

Computer graphic -- Programming with OpenGL I

Session V-STON Stonefield Query: The Next Generation of Reporting

Web Page Components Doug Hennig

SNS Locator Quick Start Tutorial

Digital Marketing Manager, Marketing Manager, Agency Owner. Bachelors in Marketing, Advertising, Communications, or equivalent experience

Transcription:

June, 2006 Advisor Discovery Use BindEvent() to keep things in synch By Tamar E. Granor, technical editor I've been experimenting with BindEvent() since it was added in VFP 8; I've even written about it (see the July, 2005 issue). But I recently found a use for the function that helped me see how it could be an integral part of an application and not just a way to add functionality after the fact. I wanted buttons on a form to be properly enabled and disabled as soon as a user acts. It's easy to reset the Enable property when the user moves off a control, but I wanted a way to change the property with the first keystroke, so that for example, the Save button is enabled only when the user has actually changed the record, not just because he asked for a new record. My first attempt set the KeyPreview property of my data entry form class to.t. and then checked in the form's KeyPress for keystrokes that indicated a change of data. It required a complete list of navigation keystrokes, so that pressing those wouldn't change the button status. I got this version working, but it didn't handle using the mouse for data entry or situations like using an ellipsis button to choose a file. The more I looked at getting it totally right, the uglier the problem got. At this point, I discussed the problem with Doug Hennig, who pointed me at the solution. Before I show the details, let's take a look at event binding in VFP. BindEvent() Refresher BindEvent() lets you hook a method to an event. You can specify that when a certain event fires, another method besides the event method should be called. The example most people use to demonstrate the technique looks something like this: PUBLIC ohandler ohandler = NEWOBJECT("Handler") BINDEVENT(_SCREEN, "Resize", ohandler, "HandleResize") DEFINE CLASS Handler AS Custom

PROCEDURE HandleResize WAIT WINDOW "Resizing main window" NOWAIT RETURN ENDPROC ENDDEFINE In this code, the Resize event of _SCREEN is bound to the HandleResize event of the ohandler object, which is based on the custom Handler class. After you run this code, when you resize the main VFP window, the WAIT WINDOW appears. (Issuing CLEAR ALL or RELEASE ohandler to turn this behavior off.) This example is included on this month's Professional Resource CD as BindResize.PRG. Like many simple examples, this code isn't terribly useful, but it demoes well. With a little more work, you can use the same idea to keep an image centered on the main VFP window (or a form) as it's resized. BindEvent() has four required parameters and one optional parameter. Here's the syntax: BINDEVENT( oeventsource, cevent, oeventhandler, chandlermethod [, nflags]) The first two parameters specify the bound event; you supply a reference to the object and the name of the event. The next two parameters specify the event handler (or "delegate"); again, you provide a reference to the object and the name of the method. You can read the function call as a sentence: When the cevent method of oeventsource fires, call the chandlermethod of oeventhandler as well. The nflags parameter deals with a couple of variations. It's an additive value that lets you specify several things with a single parameter. The first issue is whether the bound event or the handler runs first. By default, the handler code runs first. Add 1 to nflags to run the bound event's method first and then the event handler's method. The second issue is a little trickier to understand. VFP lets you call an event method directly with code like ThisForm.cmdSave.Click() (though such calls are bad form). You can determine whether code bound to such an event fires on a programmatic call or not. By default, such a call does also run the event handler method; add 2 to nflags to prevent such calls from executing the event handler method.

The reason for the distinction is that direct calls to an event method like Click don't actually fire the event. They run the code contained in the event method, but not the built-in VFP code associated with the event. For example, when you call a button's Click method, the code there runs, but the button doesn't go down and back up visually. One final point about BindEvent(), though it's not relevant to this particular problem. You can actually bind to properties as well as events. That is, the cevent parameter can actually be the name of a property. When you bind to a property, the event handler method fires every time that property's value changes. This is similar to having an Assign method for the property, but without the need to subclass. In addition to providing another way to respond to VFP's events, the event binding mechanism also provides a way to create and fire custom events. The RaiseEvent() function lets you indicate that an event is firing, even if it's a custom method of a custom object. The syntax is: RAISEEVENT( oeventsource, cevent [, uparameters ]) Events fired by RaiseEvent() call any handler code regardless of the nflags setting used in BindEvents(). You can also use RaiseEvent() on native events; as with custom methods, handler code is always called. However, even RaiseEvent() doesn't fire built-in VFP code for the native event. Back to the problem To solve the problem of properly enabling and disabling buttons, I made a few changes. First, I eliminated the KeyPress-related code entirely. I added a custom AnyChange method to every control class with a ControlSource property and put this code in Both InteractiveChange and ProgrammaticChange: RaiseEvent(This, "AnyChange") Since there might be controls that aren't involved in the record itself and thus shouldn't determine the status of the buttons, I also added a custom property, lnotechange, to each of the control classes with AnyChange methods.

Next, I added an AnyChange method to the base form class. Then I added a method called BindControlEvents and put the following code in it: LOCAL ocontrol FOR EACH ocontrol IN This.Objects IF PEMSTATUS(oControl, "lnotechange", 5) AND ; ocontrol.lnotechange BINDEVENT(oControl, "AnyChange", This, "AnyChange") ENDIF ENDFOR So the AnyChange method of every control on the form that has lnotechange set to.t. fires the form's AnyChange method. The Init method calls BindControlEvents. With this code in place, any time there's a change to a control on the form, the form's AnyChange method fires. This is essentially a generalization of the mechanism that KeyPreview provides for KeyPress. In my situation, I put a method call in AnyChange to the form's custom UpdateEnabled method that evaluates the current situation and enables and disables controls. This month's Professional Resource CD contains a class library (Base.VCX) containing the necessary code for this technique, as well as an example form (Customers.SCX) that demonstrates it. The form is a simple editing form, but the buttons enable and disable based on the current state, as soon as you start typing. Figure 1 shows the form after clicking the New button; Figure 2 shows it after something has been typed.

Figure 1. New record After clicking New, the new record is ready to edit, but there's nothing worth saving, so Save and Revert are disabled. Figure 2. Changed record Once there's some data to save, the Save and Revert buttons come alive. In your applications, you might chose to be more picky about what's enough to enable the Save button. Lots of ideas Since this experience, I'm seeing more uses for BindEvent(). For example, in a project I'm currently working on, I'm binding the Activate and Deactivate methods of the base form class to a couple of

application object methods, so I can maintain an application-level property pointing to the active form. Then I can bind to changes in this property to handle application-level tasks when the user moves from one form to another. Among the things I'm currently working out is keeping toolbar buttons properly enabled and disabled, based on the active form and its status.