Level Extreme .NET Magazine April 2008 issue

Universal Thread Magazine March 2007 issue

2006
2005
2004

2007
2006
2005
2004

2007
2006
2005
2004
2003

2007
2006
2005
2004
2003
2002

2007
2006
2005
2004
2003

2007
2006
2005
2004
2003

2004
2003
2002
2001
2000
1998
1997
1996
1993

2003
2002

2003
2001

2003
2002
2001

2003
2001

Visual FoxPro 2001
Visual FoxPro 2000
Visual Studio 2000

West Wind 2002
Double Impact 2001
FoxTeach 2001
Jam sessions
Technical Guidelines

Universal Thread documentation

About
Acronyms
Contact information
Troubleshooting
Time zones
Web Service
Terms & Conditions
Copyright

Manage your account for the messages area options, your subscription information, your invoicing, youir banners and your pictures Subscribe to the Universal Thread and get all the benefits related to the messages area A corporate subscription is needed for companies that have more than one developer Access the Universal Thread store to purchase your subscription, corporate subscriptions and banners The Universal Thread is covering several conferences per year. On site, reporters cover the technical aspect of the conference as well as making interviews, taking pictures and videos and other related content. Get all the reports from our coverages site. Universal Thread home page Level Extreme .NET Magazine, a newly published online magazine by Level Extreme about Microsoft .NET technology and its community Universal Thread Magazine, a magazine dedicated to the Visual FoxPro community Southwest Fox 2004

The newest developer conference dedicated to Visual FoxPro! We want to provide practical techniques and best practices for all skill levels that can be applied to the problems and challenges in developing applications today. Sessions will give a better understanding of OOP; upgrading existing VFP skills; address the latest changes and innovations in VFP; knowledge of additional tools such as SQL Server, API’s and .NET; business advice; taking your application to market; and “nuts and bolts” sessions that you can use today. You will also have the opportunity to mix, blend, come together, mingle, join, unite, socialize, circulate, associate and altogether rub elbows with the top speakers and recognized vendors in our industry. Please join us for what we are certain will be a valuable and entertaining conference.

Date: 
Location: 

Friday, October 22

by Dave Bernard

First-time reporter Dave Bernard here; Patrick and I are excited about being able to bring you a blow-by-blow account of the events and people of the inaugural (or initial instantiation, for you OO fans) of the Southwest Fox Conference. Many thanks to Bob Kocher and Jeff Johnson for putting this together.

Getting here today was not easy; I had to brave Friday afternoon Atlanta traffic, gate changes and misdirections, an hour waiting on the tarmac and a long, bumpy flight sans food (too rough for the flight attendants to "attend"). Kissing the ground upon disembarking seemed a natural response to finally landing. The hotel provided a free shuttle from the airport (nice) which was only ten minutes away (nice, too).

What a great time to be in Phoenix: mild, sunny days and cool dry nights. The hotel at which I'm staying, the Twin Palms, is across the street from Arizona State University, which is providing the space for the conference. So it's just a five minute walk from hotel to conference, which is a shorter distance than some conferences where I've stayed in the hotel that hosted it.

Friday night was registration and a meet-the-speakers reception. Due to the tardiness of my flight, I missed most of the reception, but managed to get registered (received a nice conference shirt, nicely bound conference materials, name tag with schedule and even a handful of hard candy!) and then went and mingled for a while. Many of the usual suspects were present (David Stevenson, Toni Feltman, Craig Berntson, Andy Kramek, Cathy Pountey and others), and it was nice to see a dapper Les Pinter roaming around. There are about 120 attendees, which surpassed the goal set by the organizers. Not bad at all for a first time!

A group of nine of us finished with the reception and headed to IHOP for a bit of a meal; Andy Rice turned menu decision-making into entertainment. Rich Simpson, Carl Karsten, Stein Goering, Andy Rice, Patrick Bibro, David Stevenson, and Lou Harris. We discussed everything from voice recognition to natural language processing and Fox on the web. Most interesting and entertaining was Rich regaling us with stories from his flight simulator days at Mcdonnell Douglas. I think Rich needs a bumper sticker that says "I'd rather be flying".

We'll get some pictures for you tomorrow; stay tuned.

Saturday, October 23

by Dave Bernard

We're going to start this day with a couple of completely unnecessary diversionary items. First, the water tastes "funny", not unlike the effect you might get from sprinkling a bit of dirt in your drink. Like anything else, I'm sure it's an acquired taste for the locals. With the desert-like environs, there's no telling from where, how far or through what this water has travelled on it's journey to the tap.

Second, the shower head is at the opposite end of the shower from the tub drain. This proved to be very disconcerting, and caused significant lost time while acclimatizing myself to this new take on tub and shower architecture. It's akin to getting into your car to go to work and finding yourself in the passenger side instead of behind the wheel. I got the same feeling when I first used the open source GIMP graphics program on Windows for the first time; they decided to replace your northwest-facing mouse arrow with a northeastward one. More lost time there. Or maybe this is just my own special sort of insanity at play here.

David Stevenson and I took the short walk from the hotel to the conference; we noticed some attendees taking in breakfast at the IHOP next door. It was a treat to finally meet Cindy Winegarden, author, MCSD and VFP MVP, whose many user group posts I've benefitted from over the years. Patrick and I met to divvy up the sessions amongst ourselves; unfortunately, we won't be able to cover all of them but we've selected a good mix for you.

I for one felt that the first day of the conference went very smoothly. There were a few small glitches here and there, but I've been to conferences celebrating their tenth anniversary that were much less well run than this one. The session rooms are close together, the ballroom remained well-stocked with sodas and cookies and the A/V equipment worked perfectly (unless you were Les Pinter). All in all, it looked more like a third or fourth year offering rather than the very first day. I'm already looking forward to next year!

Once last note before we dive into sessions: it's fall and we're on a major college campus and that means (American) football. Throughout the afternoon, we heard big, muffled explosions that turned out to be fireworks set off whenever ASU, hosting UCLA, scored a touchdown. And, on an afternoon where neither defensive squads showed up, ASU pulled off a 48-42 win and burned a lot of black powder.

Now, on to the sessions.

Re-Architecting FoxPro Applications - Encapsulating Old Code
David Stevenson

This well-attended session (I counted 30 people, fully one quarter of all attendees) consisted mainly of "old timer" Fox developers who had been using FoxPro for at least 10 years; nearly everyone owned up to having "old" code around to maintain. About a third of the audience were at their first Fox conference (a nice surprise) and there was an even split between those who work for a single company and those who service multiple clients. About half had downloaded and checked out the VFP 9 beta.

David's session dealt head-on with a common problem in small and medium-sized businesses. It's no secret that many businesses out there still run "legacy" Fox applications (say, version 2.6 and before), and quite successfully. Increasingly, information systems strain to keep up with business growth, customer service demands and competitive pressures. Businesses that ran on a single LAN in a single location have now expanded to multiple locations, and customers are clamoring to access information over the Internet. The original application was never designed for this kind of scalability; the business, not technology, demands change to survive and grow.

Full rewrites using the same development tools are risky and expensive. The risk is even higher if you are contemplating changing technology horses entirely (it may very well require new technologists unfamiliar with your business). In many cases a complete re-analysis is required due to lack of technical documentation. And you've got to accomplish this with little or no business interruption. Reality dictates that you will still make changes to the existing system while creating the new one (keeping the plates spinning while rearranging the furniture). For many businesses, a safer and more predictable approach is to repurpose the existing application in a way that satisfies the business requirements.

David's theme was encapsulation (simply said: putting a box around something). Encapsulation promotes the reuse of existing code (lower risk), enabling code use in other parts of the application, allowing code to move to scalable COM objects callable from multiple places and reducing expensive rewriting and debugging of new code. The path to attaining encapsulation starts with an assessment: strip away the UI and navigation code; what's left (core business logic and data access code) are candidates for encapsulation. Next, consider encapsulating heavy data manipulation and maintenance routines (data scrubbing, e. g.) with little or no UI, along with complex calculations involved in querying data. Old-style hand-coded reports are another good target. Once identified, the goal is to turn these pieces into one or more isolated, self-contained units. It follows the nTier goal of the separation of code into loosely-coupled logical layers.

David pointed out several barriers to pulling this off. The task is considerably harder if the original code depends heavily on environment settings and a lot of public variables (login credentials and paths, for instance). The visibility of variables inside and outside any given data context needs to be carefully considered. There may also be dependencies on other programs and class libraries that needs to be accounted for.

In packaging this together, David advocated the use of multi-threaded DLL (MTDLL) classes built on the Session class (which delivers an automatic private data session). Your old public variables are passed as parameters to the new COM method, instantiated via NEWOBJECT or CREATEOBJECT. Place any SET commands in the INIT method (VFP 7 and later set TALK, EXCLUSIVE, SAFETY to OFF). If you create a class called "CustCalc" and build your MTDLL from a project called "Calculations" (containing the CustCalc class), then executing the class is a snap:

oCalc = CREATEOBJECT("Calculations.CustCalc")
llSuccess = oCalc.DoACalc()
oCalc=.NULL.
David pointed out a few important aspects of working with an MTDLL. First, multi-threading helps smooth out handling multiple requests of the DLL by different callers. Also, remember that the default folder for a DLL instantiated outside the Fox environment may not be what you think; it is a good habit to explicitly perform a SET PATH in the INIT method that points to your expected startup location.

Running an MTDLL outside of Component Services introduces some interesting side effects, as David demonstrated with some interesting test code. Multiple instances of the same object run on the same process and thread ID's, causing public variables to be shared between the two threads. MTDLLs are apartment-model threaded: each thread gets it's own "apartment" for global data. Because they're both running on the same thread, they will share global variables. This is not the case with Component Services. David highly recommends installing the DLL under Component Services to avoid conflicts, improve scalability and ease security concerns.

Neutralize Your Data Source with Cursor Adapters
Mark McCasland

Mark led an clear, thorough and compelling look at using the Cursor Adapter object in VFP to build a data access foundation that makes it astonishingly simple to change your backend data source with very little code change. This speaks directly to the current trend of moving larger, growing data stores from FoxPro DBF's into SQL Server, mySQL, Oracle, DB2 and others. His techniques truly let you design with the future in mind.

According to Mark, a well-planned design results in having only to change a single property when switching backend data sources. He also showcased his own public domain CursorAdapter VCX Builder, which is designed to connect to a non-Fox backend data store, retrieve all tables in that database, and create a Cursor Adapter subclass for each table. This enables VFP to auto-generate the Insert, Update and Delete SQL or to allow you to programmatically handle these functions. It greatly simplifies the process of setting up the proper Cursor Adapter code for the various backends you want to support.

Mark outlined a few items to be aware of. In general, some data types don't map properly (or don't exist at all) among the various backends to which you might connect. For example, Oracle doesn't really support a logical data type; a good idea is to store .T./.F. values as 1/0 in an integer column. Text and BLOB fields map pretty well by default. The new VARCHAR data type in VFP 9 is a real help in migration situations; use it as soon as you can. Take care that you avoid using reserved words as primary key, column or table names; this can be especially confusing and problematic to the target backend. Avoid having embedded spaces in these entity names, too.

Mark is a strong advocate of using only integers for primary keys and to name it the same for all tables (AUTOINCREMENT in FoxPro and IDENTITY in SQL Server). In the case of distributed databases, a GUID is a better primary key value because it guarantees uniqueness even across machine boundaries, easing the merging of disparate data sets.

Mark followed this discussion with an in-depth demonstration of conflict resolution techniques using the TIMESTAMP data type when multiple users are attempting to update the same record. CursorAdapter properties InsertCmdRefreshCmd, InsertCmdRefreshFieldList and InsertCmdRefreshKeyFieldList are new to VFP 9 and are important in controlling TableUpdate behavior. Conflicts can be detected via the ConflictCheckCmd property and when the TIMESTAMP data type is used. There's a lot of new capability and simplification in the coordination of key updates in a master/detail data schema. Also, Mark touched on delayed memo fetching, data type conversions for logicals and the ability to specify code pages.

Mark brought his fire hose and made us drink from it!

Using SQL Server with Visual FoxPro
Les Pinter

Les is one of the icons of the FoxPro community. He's an overachiever in many ways (speaks a thousand different languages, is a prolific writer, speaker, traveller, VFP and .NET MVP, et al) and an underachiever in some ways (selling 23-year-old Bill Gates the foundation for the first version of Microsoft Word for $30,000 and a grilled cheese sandwich). In this session, however, he outdueled the demo gods (who disabled both his projector AND his laptop) to deliver an entertaining, informative and important presentation on using SQL Server with VFP. Truly a yeoman's effort while having to work without a net.

Les is a great advocate for VFP as a development tool; he told the audience that "FoxPro's the best thing that ever happened to me". But SQL Server solves the problems inherent with larger FoxPro tables: backups requiring exclusive use of the tables, index corruption, slow updates and lack of client-server efficiencies. In short: SQL Server is much better and faster for larger data sets.

A couple of remarks Les made got the audience's attention. He quoted a senior Microsoft official as saying that "every VFP license sold represents a loss of about $10,000 in SQL Server license fees"; give that a moment or two of thought. And he provided us with a great one-liner regarding the Internet: "The Internet provides us the ability to deliver any type of data of any complexity at any time anywhere in the world for free; it is probably the greatest thing that's happened to our industry." Food for thought: if you're not on the Internet Superhighway, it's time you found the on-ramp.

Les quickly outlined the various methods for connecting a VFP application to a SQL Server data store. SQL pass-through (SPT) uses the SQLEXEC/SQLCONNECT/SQLDISCONNECT command set, Remote Views (stored in the DBC) are easy and efficient, the CursorAdapter is great for preparing the ground for upsizing FoxPro and XML Web Services for integrating in a more loosely-coupled manner.

Les cautioned his rapt listeners to use the upsizing wizard with care; he advised that either using SQL Server DTS (Data Transformation Services) or rolling your own methodology might be a better course due to data type conversion issues, especially with nulls and dates. Remote Views are a good way to get started if you're new to SQL Server; the Cursor Adapter is newer, slightly better and more complex for the novice. Parameterized remote views allow the developer to specify a simply "?" to represent a parameter when storing the view in DBC; subsequent use of the view prompts the user for the value to use in the view construction. XML Web Services provide a good pathway to getting your data onto the Internet. DiffGrams, often seen in Web Services, are supported by the XML Adapter. A final method for connecting a VFP application to SQL Server is to take advantage of IIS support for XML data delivery using SQL Server (FOR XML AUTO); it returns XML much like a Web Service would.

For working with SQL Server itself, make sure you understand the difference among the different SQL Server "editions". Spend time learning Query Analyzer, because that's where you'll live as a developer.

Great session by Les.

Lunch and Keynote
Bob Kocher, Jeff Johnson and Ken Levy

We're halfway through the first day of the first ever Southwest Fox conference; it's been a pretty fast-paced morning, lots of good material and ideas to ponder.

And we've worked up an appetite.

Lunch was provided in the form of a simple buffet of salad (green and fruit) and sandwiches (make your own, which I personally prefer). Cookies and sodas are plentiful. There's some time to chat with your neighbor at the table, try out the Wi-Fi arrangement (a little problematic for me, but I'll try again tomorrow) and scan the vendor booths (the usual suspects). I like the idea of centralizing vendors and eating in the same large room, a thought shared by the vendors, I'm sure.

Jeff and Bob opened up the keynote proceedings to a big round of applause; they acknowledged Whil Hentzen's work as their primary model for organizing the conference, and thanked the Vision Data Solutions folks, Ed Leafe of ProFox, and Drew Speedie for their encouragement, prodding and support. The FoxPro community may be getting smaller, but it's a persevering, close-knit group of believers.

Ken was introduced and began his presentation with the theme "20 years of the Fox: The Road to Microsoft Visual FoxPro..." It took me a moment to digest that it had really been two decades since the first Fox release (FoxBase), and about half the room had started with that version. Ken, an ASU alum, informed the audience that he knew exactly where he had been 20 years ago to the day: downstairs in the student center having lunch!

Next, we were warned about what was not going to be in the keynote:

  • Andy and Marcia singing and dancing
  • Drew Speedie in slow motion
  • Doug Henning in a swimming suit
  • Craig blogging in underwear
  • Jeff Johnson doing dBase demos
  • DAO, RDO, ADO, Jet or MSMQ demos (applause)
A show of hands proved that most of the audience still has FoxPro/DOS loaded on their machine! And, at the same time, most of the room had checked out the VFP 9 beta.

Ken took us back in time with a couple of items. First, he related how Susan Graham, one of the original Fox Software employees, ran into Dr. Dave Fulton himself while on vacation in Antarctica (with photos to prove it). Recently, Susan interviewed Dr. Dave on camera, part of which was shown. He is aggressively pursuing his hobbies (playing and collecting violins, photography), tries to keep up with technology, doesn't do too much programming anymore and loves Visio. He felt Rushmore was the greatest single contribution that FoxPro made to Microsoft. He reminisced about FoxPro winning the 1991 COMDEX Outstanding Technical Excellence award largely because of Rushmore. He thinks it's "utterly astonishing" that VFP is "still alive", that is has "nine lives".

Ken quickly ran through the themes for VFP 9 and provided a few good sound bites (bytes?) in the process. The first, "Over half of FoxPro development involves SQL Server", was something I had not heard before. A good summary of the enhancements to VFP in version 9: according to Doug Henning "we blew the lid off extensibility with VFP 9." Well said.

Demos were short and to the point and just scratched the surface of what's changed since version 8. The common theme here is: No More Limits! Most enhancements involved removing restrictions on functionality that are now only limited by available memory (arrays, procedure size, etc.) There are a lot of neat GUI improvements (anchors, wrapping labels, GDI+). Hovering over a memo field puts the contents in a tool tip (very cool and useful). TabletPC events have been incorporated, too. The SQL syntax improvements and Reporting engine overhaul are worth the price of admission, in the humble opinion of yours truly. Many more interesting things; just get the beta, read the help and go for it!

Ken said that VFP 9 will have the same pricing structure as VFP 8. Look for a slew of great white papers and a December, 2004 release date.

A random thought: It's good having shows in geographically dispersed areas. Each conference's attendees are region-centric, so you get to meet different people at each conference. Just thought I'd share that with my kind readers.

Using the Windows Event Log
Craig Berntson

At first, I felt a little sorry (for Craig) seeing the sparse showing for this session. After getting under weigh, it was the audience I was feeling sorry for!

To those who didn't see it: cowards! Craig has attacked and subdued a very complex undertaking and made the result available to the Fox community. What he accomplished was not just a way to work with the Event Log from within VFP, but also demonstrated how to deal with some real issues when dealing with Win32API calls in general and VFP's lack of support for common OS-level information structures. This is the kind of session you can really sink your teeth into on multiple levels.

To say that working with the Event Log is a complex endeavor is to make a supreme understatement. I would have given up long before Craig did. Fortunately for us, Craig had outside pressures that necessitated a working solution, so he had little choice but to finish.

Why would you want to do this, anyway? Aren't there many other options available to log events? Well, for one thing, those other methods (XML, tables, etc.) are proprietary, have wildly different formats, different UI's and are hard to merge together. The Event Log is standardized, centralized and supports a unified UI. For our example we are going to focus on the Application Log component of the Event Log (note that Windows 2000 and later support user-defined logs, too). Event logs are stored in EVT files in the System2\Config folder and are meant to store information for things like problem diagnosis, users logging on, opening a database, starting a file transfer, etc. It is not a tracing tool, because there are real limitations on practical physical size.

You access Event Log functions programmatically through Win32API calls. But first you have to do some weird, geeky things to set up the access. Craig has encapsulated the complex setup process via a batch file and some rather simple guidelines, all figured out the hard way. What follows is the short version of what needs to happen.

First, you have to create Message Files, INI-like (sorta, kinda) collections of name-value pairs in a couple of "sections". To simplify, you can put the three types of message files into a single physical file, which is advisable. The "collections" can get quite convoluted if you let them get out of hand, but Craig has outlined some steps to keep it simple. Since messages can be shared by multiple event sources, it's best to set up the message file parameters to accept the entire message as a parameter passed by the calling application so that the DLL (see next paragraph) can remain unchanged once built. Got that?

Once you built the message file, you need to "compile" it into a DLL, which is not really a DLL in the sense that FoxPro developers may think, but really just a repository of message attributes, because the actual messages aren't stored in EVT files (only pointers to messages in the DLL). Get it? Just making the DLL itself is a multi-step process: once you make the message file, you then compile it with the message compiler, compile THAT result with the Resource compiler then link it. NOW you have a DLL. Fortunately, Craig has provided a "make" script that encapsulates all the trouble.

So we're ready to go at it with our FoxPro application, right? Wrong! Next you have to do some rather obtuse registry changes, THEN you're ready to have at it!

The real fun (and education) begins now. To post an event to the event log, you basically DECLARE a certain Win32API function, call it and check for errors. But calling it is no simple task because the function requires parameter data types that VFP doesn't support! These include structures, null-terminated arrays of strings and C++ object pointers. Craig has figured out how to convince VFP that it CAN handle those things. Makes you very glad you're not a C++ developer!

Reading the event log is much simpler. You can get the number of events, read the oldest event or read them sequentially. You can do maintenance tasks on the event log such as backing it up and clearing it (careful!).

Event log limitations are very important to understand. The real practical size limit for an event log is about 300MB, even though the theoretical limit is 4GB. This limit further degrades due to memory limitations imposed by other services using the log. Once the event log fills up, it starts overwriting the oldest entries.

Because the event log format is an OS-level piece, it is an easier sell for something like HIPAA compliance because it looks a lot less proprietary than a custom log approach. But that's just my opinion, I could be wrong. In all seriousness, extending the Event Log's usefulness as a problem resolution device to our VFP applications allows us to leverage existing tools that leverage the Event Log itself. It bears serious consideration as an addition to your development toolbox.

Working with Events in Visual FoxPro
Drew Speedie

Drew is one of the most popular speakers on the circuit, and it's easy to concur when you see him in person. His preparedness and direct presentation style work well with tough topics like BindEvents. His rapid fire delivery (darn, I've already used that fire hose metaphor!) is great for getting through a lot of material in a short amount of time, and he backs up his sessions with prolific examples and written explanation.

This session focused on using BindEvents to manage Windows message notifications, a capability newly added in VFP 9. We first got our bearings with a nifty demonstration that clearly showed BindEvents responding to a slew of VFP and screen events (writing a fired message to the screen). This is what's available in VFP 8 (see Mike Helland's "Using Event Binding in VFP" session). In VFP 9, we can bind events to Windows events, too. In VFP, you create a delegate object that can respond to bound events. To support Windows events, a new first parameter in BindEvent specifies the hwnd pointer to a FoxPro form. When the Windows event fires, it passes the same four return values to the specified event handler. Drew has plenty of real code examples in his session notes. Necessary constant values are defined in WinUser.H; it's a good place to go noodling for Windows events to which you can bind delegate functions.

Drew showed a useful example: binding the Windows event that fires when your Fox application loses and gains focus via clicking or Alt-Tab. He warned against putting any UI or even dialog box in your delegate code in response to an event being raised; you could find yourself in hot water if you're trapping for a Got/Lost Focus and, when the event fires and it throws up a dialog box, that causes the form to lose focus again, which throws the events, which puts up the dialog box, which...

Another relevant example demonstrated how you could trap a change to the Windows desktop screen resolution and then have code fire to resize your application screen appropriately (not a rare situation in the real world). After that, Drew addressed a real problem with applications doing important batch work on a laptop. You can bind code to the Windows event (WM_POWERBROADCAST) that fires when the power state of your laptop changes (hibernate, standby, etc.) If you have a long-running process that needs to finish or not run at all, an unexpected power outage could render unacceptable results. Disk events are fired by Windows Explorer when files/folders are added, deleted, renamed, etc. You could bind code to these events that could replace "old-style" file-exists polling logic with a simpler and more efficient event-driven approach. The great thing is that you can use SendMessage to simulate a Windows event firing in order to test your delegate code, without having to actually wait for your laptop to run out of juice!

Re-Architecting FoxPro Applications - Converting Business Objects
David Stevenson

In his earlier session ("Re-Architecting FoxPro Applications - Encapsulating Old Code"), David provided us with practical methodology that leveraged encapsulation to repurpose applications for the Web. In this session, he reinforces and extends that methodology to the creation of a specific business object layer from existing, "legacy" code.

A main benefit to this approach is the flexibility you gain in choosing your data stores because you have separated your UI layer from your data access layer. You are also making this code available to other programs and processes by centralizing common tasks into object-oriented classes, maximizing code reuse. The end result is an application that better adheres to object oriented design guidelines.

David explained that there is no particular "right way" to building a business object layer in an nTier design; hybrid and special-purpose designs are fine as long as they are appropriate to the situation and solve the problem at hand. It's OK to break the rules (you heard it from David!) Many developers assume a physical separation between layers; that can certainly be valid in many cases, but it's better to conceptualize nTier design as a logical separation between layers. A logical separation can be compiled into a single application, if that's what you need.

David outlined a typical business object class structure, based on the Session class:

  • GetList: get a recordset
  • GetByPK or Get or LoadData: get an individual record
  • New: populate a new data structure with defaults
  • Add: add a new record
  • Save: update an existing record
  • Validate: make sure data can be saved
You can optionally add hooks (BeforeSave, AfterSave, e.g.) to these methods to add further runtime flexibility. David encouraged the use of the CursorAdapter to abstract the moving of data to and from cursors and ODBC data sources. The XMLAdapter is good at abstracting the handling of XML from SQL Server, .NET DataSets and DiffGrams (see also Mark McCasland's public domain CursorAdapter VCX Builder). A good resource for business class objects is Rick Strahl's wwBusiness class.

Thanks for a good series, David.

by Patrick Bibro

I decided to start my day at the Southwest Fox Conference with a healthy dose of VFP 9 report writer overload. Cathy Pountney had back-to-back sessions on the Report writer beginning first thing in the morning. Even thought she covered tremendous ground in the two well-attended sessions, she still had to refer the audience to her white papers on MSDN (here and here) for more detail and depth.

What's New in the VFP Report Writer
Cathy Pountney

Cathy's session focused on the User Interface changes in the new VFP Report Writes. She covered the the myriad ways that you can now extend the functionality, too.

Old Engine = GDI, New Engine = GDI+ for rendering reports.

SET Reportbehavior 80|90 – The default is set to 80 and GDI+ may require adjusting current reports. If you have numeric fields with a "99999999" mask, it may be too small for the way the GDI+ engine renders results, leaving a display of "********" where GDI rendering would allow the same value to fit.

Cathy demonstrated how the appearance at 300% zoom was very choppy when using VFP8's GDI preview and very crisp when using VFP9 GDI+ preview. Very impressive.

The Data Environment piece has several enhancements; you can now copy a DE from an existing report's DE. You can also save the report's DE as a class and use that for several reports. You can USE a DE Class – Link in report properties – to add code using BindEvents. Will run fine if you change the DE class but the DE in the Report designer may not update the visual cues to match changes.

Reports can now be "protected" when using MODIFY REPORT at runtime. "Protection" properties can be used to allow allow users to modify only the parts of the report we choose. For each report object you can specify that it can/can't be moved/resized, Not Edited, Not Deleted, Not Selected, and/or not even visible in the designer.

Design Time Caption – instead of long function that only a developer would understand you can display an English friendly wording – double-clicking will show code behind. You can also select which fields tabs of the report properties dialog will be available to users at runtime.

Misc User Interface Enhancements: Better right-click menus and new toolbar options (Page Setup and Font Dialog). The Expression Builder: fields list are the tables open now, prior version it was tables in the DE. This is nice for people like me who never use the DE for reports. You can now zoom up to 500%, down to 10% from toolbar. Multiple Selection Dialog: you can now apply Protection and set the “print only when expression is true” property in bulk.

Layout object enhancements:
Template character - Format Expression – Overlay vs Interweave
99999-9999 Overlay 55113-123
99999-9999 interweave 55113-1234

New Trim mode options are available:

  • To nearest Character
  • To nearest Word
  • To nearest Character with Ellipse
  • To nearest Word with Ellipse
The question “Is there a global setting for trim mode?” came up and the answer was "No". Trim mode is can not be done in multiple selection dialog either.

Printing Enhancements: Sys(1037) – Pick printer dialog – Prior to VFP9 there was no useful return value; now it returns 0 for cancel and 1 if a printer was picked.

Requirements for multiple detail bands: the parent table should be selected at time report is run. You need to set relations for report to work. Add additional detail bands using Optional Bands on the report properties Dialog. Each Detail Band can have Associated Header/Footer bands. Report Variables: “Reset on”; can reset on any of the detail bands.

The VFP Report Writer in Action
Cathy Pountney

In this session Cathy presented the ReportListener Base Class, the FFC subclasses, and some of her own subclasses. The FFC listeners have functionality for generating XML, HTML, and Chaining together multiple outputs. Cathy's subclasses addressed a variety of tasks all made possible by the ReportListener class.

Using the Listeners:

ox = CREATEOBJECT(“ReportListener”)
ox.PrintJobName = “My PJ”
ox.Quietmode = .T.  && does not print page x of y dialog

REPORT FORM repname OJECT ox

Cathy's Listeners: She uses the Report FRX's USER field and adds a trigger to tell her listener object to do something. REDNEGATIVE, SQUEEZETEXT, ROTATE TEXT.

Directive Class (custom base class), subclasses for each behavior. Report Listener Methods/Events that are commonly used: Render, AdjustObjectsize, EvaluateContents

Change Color:

Object.PenRed = 255
Object.Reload =.T.  &&& Needs to make change happen

Pagination Listener: to keep an entire data group together. By using the rectangle shape and adjusting its height this can force VFP to go to a new page if the group will not completely fit on the current.

TIFF Listener: Can do multi-page or single-page TIFF's. At page 20 multi-page TIFF performance may take a nose dive and get worse for each additional page; beware. X-Up Forms Listener: uses shapes to fudge the height to keep everything in the same place independent of number of detail rows. Bar Chart Listener: adjust heights of the bars at runtime.

Cathy wrapped up the session by talking briefly about Chaining Reports and adding a Table of Contents or Index.

Whats New in VFP9 or Potpourri for $1000, Alex
Mark McCasland

Note: No prizes, cash or otherwise were awarded. By the end of the session nearly all the board had been covered and Mark had shown many examples of the new changes of VFP9, mostly nice new features, but there were also some behavior changes that could break code.

Change or Set a grid's RecordSource: trick of setting to blank and then restoring later no longer works – structures are lost – use of methods.

  • MapVarChar property for CursorAdapter Class
  • SQL Clause: (Buffering = .T.) and SET SQLBUFFERING ON
  • Collections can be used for ListBox or ComboBox RowSource
  • Native mapping of Bit Type to Logical
  • IN is optimized: if you put the most likely values at the beginning you will see better performance
  • SET TABLEPROMPT OFF: does not prompt user for table
  • SET COVERAGE TO LOG at Runtime
  • Drag and Drop SQL Stored procedure to Fox code window from the Data Explorer
  • ALINES(): able to break on more than just the end of line
  • SELECT DISTINCT: now requires ORDER BY to work
SQL can now rollback changes if disconnected in the middle of transactions – difficult to demo on single machine:
FOR EACH ... AS TYPE cClassType
 	.    &&  Intellisense now works
ENDFOR
The fourth parameter for the SQLEXEC to capture how many records have been effected by DELETE/UPDATE/SELECT/INSERT: not in the CursorAdapter Class.

Test for type is an array with a second parameter to the Type() function. TYPE(cVar,1) returns 'A' if an array but returns 'U' if not. Confused by the result; the crowd felt an ISARRAY() function may have been a better option.

Extending the VFP 9 Reporting System part I: Design-Time
Doug Henning

Doug started the session with a demo to give everyone a taste of what could be done with the design time extensibility. After typing “Create Report x” in the command window, a dialog appeared with a list of templates to use to create his report. He choose the first report template from which a report was created He then added a field object to the report and this brought up a custom dialog for that allowed selection of fields based on his metadata that displayed descriptive field titles and that would automatically size the field object to match the length of the field. After adding a couple fields that self-sized and added header captions for themselves, he went into print Preview which then automatically queried a cursor from SQL Server.

From there, Doug covered how VFP9's open architecture for the reporting system makes all this possible: Report Builder Events that allow for hooks into the building process. There is a standard framework for handling report events by registering your custom handlers. The ability to add new handler records enabled Doug to bring up his custom dialogs when certain events occurred. Only one Handler is used for a particular type of Event. It will only use first record found so you need to delete or disable other existing records to make sure your handler is the one called.

He went through each of his handlers that made his initial demo work. The first being the New Report Handler that checks if the report is a new report and if so offers a list of templates. If the user chooses one the handler takes the newly created FRX and issues a ZAP to remove anything added to it, append the records from the template report and loads the FRX changes into the designer. Next he covered his Add New Field Handler. This handler fires when a new field is created. It runs the builder to select fields from the metadata and determines the needed space for that field based on the field length, font name, font size, and font style. It then must tell VFP not to do the default behavior and to reload the modified FRX in the designer.

Last he covered the Preview Handler. It generates a SQL Select statement based on what fields are referenced in any of report records such as in a field expression, a print when expression, a variable, in the on entry, or in the on exit. It will select all the fields used and will query from SQL Server.

Extending the VFP 9 Reporting System part II: RunTime
Doug Henning

The focus for this session is on extending the report system for when you run reports, not when you design reports. Again Doug started with the teaser of what you can do followed by how it is done.

He showed a demo conditional Red/Bold fonts evaluated at runtime, Rotated Header Labels, and a Watermark.

His slides showed the VFP9 report architecture:

  • Report Engine handles (Data, Object position)
  • ReportListener Class handles (Rendering, Printing, Previewing)
  • Subclasses (New Outputs, Other Functionality)
“Page at a time” mode: renders the page and sends to them printer one at a time. “All pages at once” mode: renders all pages to memory, Display/Output page by request.

New Reporting Syntax

loListener = CREATEOBJECT(“myListener”)
REPORT FORM myReport OBJECT loListener
or
REPORT FORM myReport Type 1 
Common Types: 0=Print, 1=Preview, 4=XML
You do not have to change existing report command, VFP will use type 0 if “to printer” or TYPE 1 for “preview“.

Doug went over the new ReportListeners base class and its most useful Events/Methods. He showed how you can chain multiple ReportListener subclasses together to get multiple effects on one report.

oListener.Successor.Successor.Successor...  

Doug used the USER field of the FRX to store the directives he wanted the ReportListener to address for each report object.

Doug's syntax, to identify tasks for his ReportListener:

*:LISTENER FORECOLOR = IIF(....)

In the EvaluateContents event he parses out the desired behavior. For performance, this is best done only once for each record of the FRX not for each detail item in a record set. His class keeps track of whether it has checked for directives for each FRX record and other reads the USER field once per FRX record. He uses another class to then make the changes to the report item that have been identified by examining the contents of USER field for directives.

He went over the ways to generate some of the additional output types: JPG, TIFF. Other ideas he listed but did not cover:

  • Alternating colors for details band lines
  • Chain reports together
  • Pie Charts, bar charts
VFP to VB.NET: What Do You Have to Know?
Les Pinter

This session was one of the most useful .NET sessions I have attended over the years. Even though the session got a little off task from time to time, it still covered quite a bit of information. Not a lot of time was spend on the virtues of .NET, in fact Les stated that he thinks FoxPro is better. .NET can do things like web services and Pocket PC very easily. If you need a thin client application, VB.NET may be your best bet.

The session looked at VB.NET wth regard to how VFP works, which I found very useful. Other sessions I've attended that have attempted to do the same often focused primarily on syntax differences, while this session spend minimal time on syntax and got down to real tasks like how to replicate a MAIN program, the USE command, the browse command, data binding, how menus work, how to skip, and other common VFP tasks.

He went over the references, the Global Assembly Cache, Namespaces, Imports, Menus, variables, objects, fields vs. properties, reflection, parameters, and threw in a nice side story about Bill Gates and grilled cheese sandwiches.

Sunday, October 24

by Dave Bernard

A new day dawns and we gather once again to imbibe at the technical trough. For some, the previous night's activities weigh heavily, but that is not the case for sleeping "beauty" here. More likely, his failed attempts at fountain gymnastics have sapped what energy remained, for this fellow is both a provider and an imbiber.

We're going to crank up the randomness a bit today; I'm going to do things in no particular order because that's they way they seemed to happen.

I can say with all confidence (sustained by conversations overheard) that the conference is already a resounding success, with folks already anticipating a 2005 version. Bob and Jeff fielded a pretty constant stream of requests from both prospective speakers and attendees for the Second Annual Southwest Fox Conference, and they later confirmed same to the lunch crowd: an expanded (day and evening) version will begin with pre-conference workshops on Tuesday, October 11, 2005, followed by the conference starting Thursday the 13th through the following Sunday. A post-conference workshop will wrap things up on Monday, October 17. The intrepid attendees of the 2004 edition will receive a $50 discount, too!

Just before the lunch session and keynote, the conference speakers gathered near the outside fountains for a planned photo shoot. Herding these cats proved to be a rather complex and lengthy task, providing the aforementioned Mike Helland opportunity to demonstrate his utter lack of balance on the edge of the water. Only the wind direction prevented immersion (and a much more compelling photo opportunity). The judges were not kind.

So much time elapsed, in fact, that I was forced to snap this shot of a large floating object, thinking that it looked nice in front of the palms and against the blue sky. Boredom can have strange results.

After the photo shoot, we scuttled back inside to a packed ballroom with lunch in full swing. Before long, Jeff stepped onto the stage (I considered "mounted" for a second there) and kicked off the proceedings. He announced that session white papers and source would be available to attendees in a few days via the web. Next, user group leaders stood up and announced their names and locations; Tampa, Atlanta, Dallas, Phoenix, Los Angeles, Salt Lake City, Madison, Chicago, Detroit, Asheville and Grand Rapids were all represented. Bill Anderson leads a consortium of Southern California and Arizona user groups that coordinate their activities and share speakers; it looks like there's quite a strong following there with some great leadership.

Next, we writers from the Universal Thread were recognized, after which Jeff moved to thank Ed Leafe for his efforts with the ProFox site and email list. Ed has extended his enthusiasm to Linux and Python as well; a source of great insight on open source technology from a longtime FoxPro developer.

Jeff turned it over to Drew Speedie, our announced key note speaker. Drew began by highlighting more examples of extensibility in VFP 9. The Fox Team has extended VFP itself by opening up the architecture to give developers more of the power of customization; if it doesn't work the way you want it to work, then do it yourself.

As an example, Drew demonstrated how you can modify system menu behaviors by hooking MENUHIT via Intellisense. You can cause custom code to fire on any VFP system menu option, and that logic can either augment or even completely override the default (or, irritating) native VFP behavior. For example, certain dialog box behavior (defaults, size, etc.) can be modified on the fly to behave in a more acceptable manner. This is great stuff!

Another good example involved a situation where you might want to completely suppress some native VFP behavior. If you go to File, Open then pick a CHM file, the default behavior assumes that you want to open a PRJ. It's not sensitive to the type of file you chose to open (DBF, FPT, PRG, etc.) Drew replaced the default dialog box with one that default to All Files, so that clicking on a CHM or HTM file opens the right associated program to run it. There's many ways, using just this one capability, to streamline your development process. Think about the little things that irritate you about IDE behavior and go attack them!

At one point, an audience member heckled Drew with a comment that didn't hear.
Drew: "You want to come up here and do this?"
Heckler: "Yeah"
Another audience member: "Didn't you mean to say 'No'?"
Drew: "OK"

The heckler walked up to the stage, and Drew was abruptly and unceremoniously removed (a staged removal?) by one Thomas Bond, who turned in a pretty funny standup routine. Some of his better lines: "Summer in Phoenix is so hot that if you tell someone to go to hell, they'll tell you that they wish they could", "I have a car old enough that it's applying for it's own driver's license" and "I can remember when TV was an escape FROM reality." An nice unexpected break from conference routine.

Many companies contributed door prizes, which were handed out next. Among the goodies distributed:

  • Rich Simpson's Minds Eye Reporting Engine
  • Les Pinter's book "Visual FoxPro to VB.NET"
  • HackVCX and ViewEditor bundle from Rick Schummer's White Light Computing (two copies)
  • Doug Henning's Stonefield Query
  • Visual MaxFrame Pro by Vision Data and Drew Speedie (two copies)
  • FoxFire 8.0+ Developer Edition
  • Release copy of VFP 9
Jeff and Bob received a spontaneous and well-deserved standing ovation for their efforts.

by Patrick Bibro

Best Practices for the VFP Developer
Art Bergquist

This session was a fun, laid-back variety show of tips and techniques that can be utilized to make a VFP developer more productive. Art stressed the importance consistency in the maintainability of an application. Many of the suggestions put into practice go a long way toward making a developer more productive and write code that is less error prone and easier to maintain.

Many of the suggestions were simple things such as using copy and paste instead of retyping in order to avoid generating new typos. Others techniques were more complex, such as using methods in dynamic grid properties, allowing easier debugging and richer comments. Some of the tips were keyboard shortcuts for use in the command window, like CTRL+SHIFT+RIGHT/LEFT to highlight and delete, CTRL+ENTER to add a blank line between a multi-line command. These are the kind of things that we all need to be reminded of every so often.

One eye-opener tip is SQL SELECT...TO SCREEN NOCONSOLE: to get a record tally without any input or creating an array or a cursor. I will certainly look into how this could help clean up some of my code. Using TEXT/ENDTEXT allows for clean, readable code but it was pointed out that when working with long SQL statements in TEXT/ENDTEXT you can copy directly into SQL Query Analyzer without the ";" character you would likely have if your statement was outside the Text block.

The session was very interactive, with the audience offering tips and thoughts that built on the presented material. The crowd of experienced developers was not shy in pointing out some potential problems with some of best practices.

Intellisense for Applications
Toni Feltman

This session demonstrated Intellisense features at runtime as well as the new AutoComplete function of the textbox. The session did not focus on the details of the Intellisense engine but instead offered a methodology for using some of the existing functions in VFP's native Intellisense (FOXCODE table) as a model for developing custom function for runtime usage.

Some configuration items to be aware of: _VFP.Editoroptions: “LQKT” is the default value in IDE; this property controls whether certain Intellisense behaviors are automatic or manual. _FOXCODE variable: You most likely would want to create your own but make use of the structure of the supplied FOXCODE table. This variable lets you specify a table to use.

The first record with version information is required from the original FOXCODE table for Intellisense to work.

_CODESENSE = [FOXCODE.APP]  && maybe needed for some scripting

The first demo was typing in “TF” and having FoxPro expand out to her full name within a memo window. She modeled this behavior on the MC/Modify Command behavior in the default FOXCODE table.

Next we covered a drop down list, which can be modeled after “SET“ command expansion. We saw a template created based on the Intellisense “DC” expansion. Her template was created with the <<>> TextMerge delimiters for variable data. This is powerful tool; sadly this part of the session ended on a major limit of the the runtime Intellisense feature: it is not available in the EditBox, my preferred control for memo data.

Toni went over the new properties for the AutoComplete within TextBoxes. AutoComplete is a nice addition to quickly add functionality to your applications, but keep in mind it's not designed for validation. No events occur, it is standalone, rather rigid system.

Tricks are for Grids
Art Bergquist

At the second to last session of the conference, you can tell people are winding down. The session went quickly as the dozen or so attendees had few questions and absorbed what they could. This section focused on three main topics involving grids: Dynamic ControlSource for Columns, Dynamic ToolTips, and Date entry validation.

Art framed his usage of a Dynamic ControlSource using a scenario he encountered where he needed to incorporate a “junior administrator” user level. Where they would be able to grant user privileges up to the level of privileges they had been granted. For his grid, depending on the access level, a DropDown ComboBox list of options maybe appropriate. If the security level does not allow for when we may not want the ComboBox to even show. Using multiple controls for each column and setting the ControlSource at the controls level the grid could display different controls dynamically based a security level.

The second topic, Dynamic ToolTip, demonstrated the limitations of VFP's native ToolTip behavior for the grid. He showed his custom improvement that uses the MouseEnter event and the AMOUSEOBJ() to show a dynamic ToolTip for anywhere on the grid, regardless of focus. The full details of how it was done are covered in the whitepaper.

Final Concept: Grid with Date Entry Checking. This focused on validating date ranges entered into a grid. First we looked at making sure Start date <= Enddate, then onto looking at multiple date ranges for more advanced constraint. Do we allow gaps between date ranges? Do we allow the overlap of dates?

His grid was able to check the constraints make sure they were valid date ranges and again details can be found in the whitepaper.

Event Handling in VFP
Mike Helland

Luckily Mike woke up in time for the last session of the conference.

Mike started by contrasting how you would do the task in VFP 7 and what is possible in VFP 8 with BindEvents. Although the functionality has been around for a while, the initial confusion of the audience made it clear that many of us still have much to learn.

His VFP 7 code created two objects, with object1 calling a method of Object2. The VFP 8 code accomplished the same task without Object1 needing to know anything about Object2, including its existence. Two objects are created and instead of asking Object1 to call a method on Object2.

He used BINDEVENT(Object1,”Obj1Event()”,Object2,”Obj2Method()”)

In Object1 he had a method that used the RAISEEVENT function to trigger the Obj1Event of Object1. Since the Obj1Event is bound to Object2's Obj2Method method, the communication from Object1 to Object2 is completed without either object knowing anything about the other.

From there we moved to thinking about this in terms of real world situations. The next set examples used three classes: a WareHouse Application Class, an OrderProcessor Class and a Boss Class.

Our Boss wants to know when order has been processed. If we make OrderProcessor Class notify Boss, it needs to know about the Boss and its methods. We used BINDEVENT/RAISEEVENT to accomplish this. The Warehouse Application Class knows about the other business objects and issues the BINDEVENT but the OrderProcessor does not need to do more than its core task of processing an order.

Mike went on to expand the example to show how we can use RAISEEVENT to pass a parameters and by passing an object we are able to get return values.

I have a feeling if RAISEEVENT() was named FIREEVENT(). I would have understood the concept before now. I now understand RAISEEVENT to be telling the class that an event should now fire. BINDEVENT is hanging out waiting for that event to fire and when it does it has some other things it needs to do.

We looked at the fifth parameter of BINDEVENT() and how it determines if the bound event code is run first or delegate code is run first.

Other related topics covered:

  • AEVENTS(): Array of all events that have been set with BINDEVENT()
  • UNBINDEVENT() can be called or is done when object is released
  • BINDEVENT to property: Useful for Empty class that cannot have access/assign methods
Then it was back to some samples that made a stronger case for usage of this methodology of coding for more than academic purposes.

One sample involved taking a SCAN/ENDSCAN block of code and reworking the process using BINDEVENT() to scan but easily changed if you are no longer needing to scan a Fox table but instead do something like process files in a directory.

Another showed a GUI that eliminated any references to the data layer. He showed a form that was responsible for only two thing presenting information and collecting information. Where the data goes or where it comes from is left to the business objects.

And how about performance? There is additional overhead for calling 2 functions instead of one but worth it for the vast majority of applications.

Post-Conference Chat with Bob Kocher and Jeff Johnson
Dave Bernard

At the end of the conference, Jeff indulged himself by throwing shirts to the audience; his Nolan Ryan delivery caused more of a duck-and-cover reaction and not a few injuries. Soon after, I had a chance to sit down with Bob and Jeff, newly-certified conference organizers, to chat for a few minutes about the past, present and future of the conference.

"We came at this from a unique perspective; we're both self-employed FoxPro developers who have never been to a DevCon. It's a budget-buster. Our goal was to hold down the price", said Bob. Jeff added that they wanted to "stress practicality and education over theory; we wanted everyone to go home with something new that they could use tomorrow and, at the same time, have a good time. It all needed to be worth the price of admission." I overheard several conversations about how this conference was a great value for the money.

"WhilFest was our primary model", said Jeff. "Drew Speedie really mentored, inspired and encouraged us. He helped troubleshoot various issues along the way and pushed us to showcase VFP 9." Bob: "The comic routine at Sunday lunch was Drew's idea; Bob and I didn't have any idea how they had scripted it, so we were just as surprised as anyone; we go a lot of positive feedback on it."

Both Bob and Jeff agree that the conference far exceeded their expectations. "This year we went to a conference that we wanted to see", said Jeff. "Next year will be more of a community effort. We're serious about gathering feedback through the evaluation forms to make improvements and grow the conference. We're going to maintain a communications channel throughout the year with the FoxPro community." Said Bob: "A good conference is a kick in the pants; you're supposed to have fun, get motivated and enjoy it."

"Ken Levy was sincerely stoked and enthusiastic about the conference and the Fox community, and was impressed at the show of strength this conference represented.", said Jeff. "We emphasized community in our planning", said Bob. Jeff added: "The introductions made of user group leaders, press, email list, recognizing community leaders, etc., reflected our desire to unite the Fox community, rather than push it in one direction or another. It was a great feeling."

"We're decompressing now", said Bob. "But we want to thank the whole FoxPro community, which is what it's all about. We were successful because of the strength of that community."

Bravo!

 
David Bernard, The Intellection Group, Inc. 
Dave is co-founder and Vice President at The Intellection Group, Inc., which builds web-based business solutions for many different industries. He has been a software developer, manager and executive for over 25 years. He has worked in FoxPro continuously from version 1.02 through VFP 9, is Vice President of the Atlanta FoxPro Users Group and holds MCSD and MCDBA certifications. He currently specializes in Internet-based extranet development using VFP and SQL Server and has recently been immersed in voice recognition, text-to-speech, natural language and RFID projects.

 
Patrick Bibro 
Patrick Bibro is a developer and consultant based out of Minneapolis, MN. He is Microsoft Certified Professional specializing in building solutions for the Insurance and Financial Services industries using Visual Pro 5-9 and Visual Studio .NET with MS SQL Server and IBM DB2 databases.



Copyright © 1993-2008, Level Extreme Inc., All Rights Reserved
62 Rue Doucet, Petit-Rocher, New Brunswick, E8J 1L3
Telephone: 1-506-783-9007 Email: mfournier@levelextreme.com