C&L Nicholls - Spacefold     Lisa's Page     >L<'s Fox Stuff     FoxSpoken Volume Index

   FoxSpoken Volume 3

articles on this page retired Apr.98

Before you use this material, please be sure you have read and understand the various provisos *3 with which I provide it for your use.

Contents of this page:

  1. The Future of FoxPro: a few more thoughts, and a plea
  2. GetNextVersion(), another futuristic epic
  3. Tales from the Framework: Edit options feature not continued
  4. So You Wanna Learn about the Active Messaging API...
  5. The Whipped Tip Dept: Unknown datasessions won't bite you
  6. CLASSDOC update

Special DevCon Non-Issue Issue

This volume of FoxSpoken is somewhat short on technical content, and it's appearing bit later than I expected to write it. This is mostly because been exhausting myself trotting around to Fox conferences, presenting Fox information in-the-flesh rather than over-the-net, for a change.

At conferences, one has a chance to think about the product with a business perspective. Talking to peers, clients, and the MS staff, is a different ballgame from the technical focus one maintains when one is coding, back-to-the-wall, fingers-to-the-grindstone, nose-to-the-screen, at the home.

Consequently my thoughts at this time are about why we use the product VFP, and perhaps how it uses us, more than about how we use Fox.

DevCon attendees: the special DevCon page is now available to you. Check out the additional technical details there. It's not like I've been doing NO coding!

The Future of FoxPro again

The most earthshaking revelation at the San Diego International VFP DevCon, for me, came in the opening session.

Yes, I know it was stultifyingly boring. Let's ignore the tepid presentation for a moment.

If you were there, do you remember being asked how many people were new to Fox, and new to DevCon, at this year's meeting? The people who stood up to be counted for that question had to be about 25% of the group. This is truly astounding.

No less remarkable was the tiny fraction that was still left standing when the roll was called for people who'd attended the first and second DevCons in Toledo. Many of the developers, both inside the developer team and on the front lines using the product, who helped make this product great with their creativity, their humour, their intelligence, their independence, and their fearless exploration... are no longer with us.

Some of our brightest stars -- Tom Kemm, Glenn Hart, Tom Rettig -- have sadly passed away. Others have burned out. Still others seem to blaze in and out of our lives (if you read this, Dr. X, say hi! Chuck Werner, are you still doing Fox? Ham Ahlo, what are you writing in these days?)...

The product continues. It's amazing that we're still debating about it. For heaven's sake, the first article I published with the words "The Future of Fox" in the title was by Jordon Powell, in FoxTalk -- I believe this was early 1992! Apparently FoxPro has progressed more than we have, in that time!

Let's just get on with it, shall we?

No crystal balls here, no matter what logo they use at DevCon

One final word, or perhaps a plea: Folks, please stop e-mailing me your CVs and descriptions of your applications, with requests for advice on how to manage your careers or which development environment you should use next year. Only you can answer these questions.

I have no inside information, and if I did it wouldn't help you here. I've said all I can say on this subject in the last FoxSpoken issue.

If you choose to write applications in FoxPro, any version, it is my professional responsibility to help you write the best FoxPro applications you can possibly write. If your applications should not be written in FoxPro, or if you shouldn't be writing in FoxPro, and you are my client, I will not shirk from my professional responsibility to advise you of these facts as I see them.

But I have to make these judgements on technical grounds, as a developers' consultant, okay? Clearly, technical issues are only a part of the picture you have to face. You need to take responsibility for the whole picture.

GetNextVersion(), a whole 'nuther ballgame from Service Packs

If you weren't at DevCon, and somehow missed Fox making front page news (!) in InfoWorld for a change, Tahoe, the next version of VFP, looks like a winner.

What sexy is

InfoWorld and presumably MS likes Tahoe because of its cozy relationship to Transaction Server. If you have no idea what that means, or are not sure whether it's relevant to your development work, or your life, or even your galaxy, here's a list of some of the other new features MS divulged at DevCon:

MS marketing wouldn't let them tell us everything, so we can figure this isn't a complete list. On the other hand, they were fairly clear that we weren't getting a new Report Writer. (Anybody else up for study sessions on Crystal Reports?)

RIP, VFP for Macintosh

MS also told us that there will not be a new Mac version of VFP. Although it's hard to see how this could be considered a feature, we can respect them for letting us know... my personal opinion is that this was probably a painful decision to make, but a reasonable one.

Apparently nobody is out there

Last time I gave you some tips on using menu functions when the menu is not available. I then said that there are some more pieces of the puzzle you have to think about if you're using top forms with this functionality. I was prepared to continue this discussion, if anybody was interested.

Well, apparently nobody is. I got no feedback on that section, even though you guys usually give me feedback on everything! Either you haven't encountered the problems yet (hint: they only show up in runtime), you've all solved these problems or you just plain don't care. Any of these reasons is possible...

I admit I am obsessed with top forms, because they present so many obstacles on the path to Fox application development nirvana, but you don't have to be! So, OK, end of subject. This time I'm gonna ask before I write:

Is there anybody interested in finding out how to use listboxes with a rowsourcetype of 6 (fields) and a rowsource that includes fields from multiple related tables in the list?

You can, and you don't need a view. Perhaps everybody already knows the answer to this one -- or perhaps this is another subject you don't need an answer to. Either way, drop me an e-mail. If there's curiosity, I'll discuss this topic in the next FoxSpoken issue; if not, let me know what else you'd like solved and you think would make a reasonable topic here...

Where oh where is the documentation on Active Messaging?

Here's something that apparently half the Fox programmers on the planet are struggling with: how do you address the Active Messaging API? And how do you find out more about it?

The first thing you have to realize: this is a moving target. When I first started to write about this subject, gee, all the way back in September 1996, it was called "OLE Messaging". This was later changed to "Active Messaging", and now is about to be called "Collaboration Data Objects" (CDO). I think this is actually Version 1.2 of the same library, no matter what it is called.

I doubt you'll find very much documentation under the last name, at this writing. However, in this guise, (CDO), the Messaging API is about to become very useful with Active Server Pages on the web.

Your best bet for finding up-to-date information on this subject is to search the MSDN OnLine section of the Microsoft site using this string

"Active Messaging" OR "Collaboration Data Objects" 

If you were fortunate enough to get your hands on the May TechNet CD, it was an "Exchange Special Edition" which contained the first published version I saw for the OLE Messaging API. This was later released on the Exchange DK (Technical Resource) CD.

If you have the October 97 MSDN Library, take a look in the Platform SDK section under "Database and Messaging". You'll probably find the CDO Library Guide and Reference is exactly what you are looking for, at least assuming you can write to the latest version of the API. (If not, either the Library Archive or one of the older editions listed above will have what you need.)

The challenge, of course, is to translate this idealized object model into working VFP code!

Check out the HowTo articles in the KnowledgeBase for help. For example, Q171425 is "HOWTO: Writing an Active Messaging Inbox Agent in Visual Basic" -- it's not great, but at least it's sample code. Q169031 is "HOWTO: Embedding a Document in a Message using Active Messaging", ditto. Whether you're looking in the HowTo or Info sections of the KB, the area you want is called (at least right now) "Messaging Application Programmers Interface".

And, yes, all the useful examples I've seen are written from a VB programmer's perspective. Stay away from the C and C++ examples, unless you plan to add C components to your VFP applications that you'll write yourself. The C/C++ syntax will only confuse you with syntax that you won't actually be able to implement, in fact whole APIs that you won't be able to get your hot little VFP hands on, mirages in the desert.

With these examples in hand, it's time to boogie. Start trying out the syntax from Fox! Just as important, create the kinds of messages you have in mind, interactively, in your messaging client application (Exchange Server client, Outlook, Windows Messaging). Get a reference to these messages from VFP and examine their properties. This will give you a good idea of the items you have to fill out programmatically, to achieve the same results.

Think cross-platform and least-common-denominator while working on this task . Yeah, all the "platforms" we're talking about are "Windows", and all the messaging clients we're talking to are MAPI-compliant... so how different can they get? The answer is: plenty different.

Although the Outlook object model, for example, can look entrancing, and is certainly more full-featured than the bare-bones Messaging API, resist the temptation to write to that object model unless you are certain that all your users are willing to make Outlook their preferred messaging client. Otherwise, considering how much work it takes to learn the syntax and twists of Messaging, you're going to waste your time learning two idiosyncratic interfaces -- and the Outlook object model may not be very long for this world, whereas it looks like the Messaging/CDO API is going to stick around, presumably improved. What's more, various people have been telling me that Automating Outlook is not going to give you great performance.

The Whipped Tip Dept:
Unknown Datasessions are not your enemy

This particular heading covers information I've seen published or available to Fox developers that either needs amplification to be useful or is Just Plain Wrong. Warning: I will not always be good tempered in this section, or perhaps not even on the rest of the page. Sometimes I wonder why I gave up carrying a whip <g>.

This one really ticks me off, because it's basically an issue manufactured by the FoxPro press looking for something to write about, IMHO.

Here's a quote from "Ask Advisor", in the May 1997 issue of FoxPro Advisor -- Tamar and Ted have introduced the idea of a modal form or a report form sharing a datasession with an existing form:

The problem with this approach is subtle. It's best seen by opening the Data Session window (know as the View window in VFP 3.0) while testing. The private data session of the original form is known by the name of that form. After calling and returning from the modal form, that data session now indicates that it's "Unknown". It appears to work correctly and closes when it should, but the change in identify to "Unknown" is a cause for concern.

I don't wish to pick on Tamar and Ted here -- I've just chosen this excerpt because, together with the additional sections I'm about to quote, it represents a very complete example of the issue, but in fact I've seen this alarmist attitude countless times in the FoxPro press.

Why, exactly, is this "cause for concern"? The datasession operates correctly because, in fact, nothing is wrong. The View/Datasession window, like the status bar, is not perfect in its understanding of the environment and does not always refresh dynamically exactly when we would like. But the Datasession window is a programmer's tool, not a reflection of any "higher reality".

Having a form or REPORT FORM share a datasession with an existing form is a standard technique (this is exactly why it is a choice on the Reports menu popup). It allows a form or a report to see current/buffered/dirty data, which is sometimes the appropriate thing for that second form or report to see. (Not always -- that's why we get the other choice.)

During the run of the report, and in absence of an explicit SET DATASESSION statement or the creation of a new DE object, the Datasession window can't use its usual cue (WONTOP()) to figure out a name for the current session. All this means is that the Datasession window is confused; FoxPro isn't. The same thing sometimes happens during a modal window brought up into a current session (it depends on when you invoke the Datasession window).

The story thus far: we're talking about a datasession that is behaving completely normally, except that the Datasession window has a problem figuring out what to name it.

The problem can actually get more important, and more complex, than the above example. In fact it is possible to create datasessions that live beyond their appointed life span. We'll get to those in a moment. But first it's vital that you realize this: sharing datasessions between forms (or between forms and reports) is necessary, and good, and perfectly okay. It is actually quite a bit safer than using the explicit SET DATASESSION TO statement that Tamar and Ted appear to be recommending as an alternative. (I'll get to that in a moment, too.)

The DED reference

Sometimes, you can get a Diabolical Everlasting Datasession -- this one won't release when you think it should, which is when the form that "owned" it releases.

Here's an easy way to see one in the flesh (I promise you, I'll hold your hand if you get scared!):

  1. Open the Datasession window. This isn't required to get a DED reference, but otherwise you won't be able to see it.
  2. Create a form or form class with a private session, and open a table in the session. Nothing fancy is required.
  3. Use the Datasession window or the SET DATASESSION command in the Command window to move into the private datasession of your form. Issue a BROWSE statement, or use the Browse button in the Datasession window.
  4. Close the form.
  5. DED at twenty paces. Your datasession is Unknown, and It's Alive.

What's happened? Your datasession object can't disappear, even though you think it should, because you have a table open in that session, which the form didn't know enough to close when it it disappeared. The datasession is called "Unknown" because it no longer has an "owner form" from the Datasession window's point of view (duh!), and it still exists because it is still needed as an "owner" of that open table.

Guess how you get rid of it? Close the BROWSE, and watch the Datasession window revert to the Default session. The DED will be completely gone.

This simple trick is not the only way you can get DEDs. For example, use the SCATTER... NAME syntax to get an object reference to the fields in a table in a private datasession. Hand a reference to that object to an application property or a variable scoped outside the form or formset that owns the session. Now, if you close the form or formset, the datasession remains because there's an outstanding reference to the tables in it (which, when you think about it, is all the BROWSE really was!). Similarly, a reference to a cursor or relation object stored in a property or variable scoped outside the form or formset can stop a datasession from disappearing.

How do you get rid of it? The same way you'd get rid of any object that refused to die: you'd look for the outstanding object reference, and get rid of that. It's purely a matter of being responsible about your garbage collection.

Tamar and Ted went on to say that "Contributing Editor Drew Speedie ran into memory problems when testing this technique [sharing data sessions] (although several other people indicate they're sharing data sessions this way in their applications without problems". Well, sure. If you don't get rid of unknown data sessions properly, eventually they will pile up and eat memory. But it's perfectly legitimate to keep a datasession around longer than a form because you actually need that reference, briefly, perhaps because you've passed information back to your app object using the SCATTER'd object reference I postulated above.

FoxPro isn't Voodoo

Scare tactics have no place in VFP education. The product is complicated enough without adding mystery where it doesn't belong. With this in mind, let's return to the rest of Ask Advisor's comments on this subject:

The alternative approach is to use the SET DATASESSION command to change the data session of the modal form. The problem here is that you can only do so safely if none of the controls on the modal form are bound. Watch for a future article for details on making this approach work.

This is rubbish. You can certainly bind controls safely on a modal form that changes datasession (should you really feel it necessary to use this technique, which takes far more work than simply sharing a datasession the way God and Fox intended!). All you have to do is bind the controls after you switch datasessions to the one containing the data you want, and un-bind them before switching out of that datasession again. If you pay attention to how Fox is thinking about these things, it's perfectly clear, and there's no need for superstitious mumbling or sacrifices on the GPF altar; the behavior is quite predictable.

There may be a design problem here (does switching datasessions violate encapsulation? is switching datasessions ever justified -- I think it is, but not here --?). But all the design problems in the world should only prove that Fox writers should never have to stoop to made-up issues for their material.

plus a few development principles you can live by

Pertinent files: CLASSDOC.ZIP updated Nov.97, ~13k. A text file from this .ZIP, CLASSDOC.TXT ~11k, is also available for viewing before download if you wish. In this update, I've fixed a small bug in the treeview control DblClick handling (this would affect the VisualDocForm subclass of ClassDoc and its descendent VisualClassMemberDocForm).

If you haven't learned about this utility earlier, please check out the information in the relevant past FoxSpoken article.

Uploading an updated version of this utility gives me an excuse to bring it to your attention. Although the Class Browser has been much improved in 5.0 and undoubtedly will be further improved in future versions of VFP, there is still no "natural" way to document descending classes, rather than ancestor classes, provided in the product. CLASSDOC fills this need. When you're spelunking around in your class hierarchy, making an architectural design change mid-stream, you'd be wise to consider its repercussions on all possible descendent classes in your toolkit -- and those of your fellow team members -- before proceeding.

CLASSDOC also demonstrates another important principle, one that you can't always live by in VFP but which you should take into consideration whenever possible: Don't use ActiveX controls without giving yourself a "back door" in Fox code to serve when the ActiveX control is not available, unregistered, the wrong version, et cetera. Although I've used a Treeview control in two of the classes in the CLASSDOC hierarchy, you're not required to use those particular subclasses to get CLASSDOC's main purpose accomplished.

CLASSDOC also uses the common file dialog control, and this one is required in the entire class tree. However, you'll notice that if an OCX error occurs, CLASSDOC switches smoothly over to using GETFILE() instead. If you know that you are running VFP on a minimal installation, such as a laptop, or if you've been having troubles with the common file dialog control version on your machine, you may want to switch the #DEFINE DOC_OMIT_TRYING_OCXS and recompile -- if this #DEFINE is .F., CLASSDOC won't even wait for an OCX error before using GETFILE() instead.


Lisa Slater Nicholls