Monday, December 28, 2020

Microsoft Office 365-like Ribbon Control

Merry Christmas! Every year between Christmas and New Year's, I like to work on a fun project, such as learning a new technique or writing some cool utility. Last year, I worked on the open source version of Hacker's Guide to Visual FoxPro. This year, I created an open source Microsoft Office 365-like ribbon control for VFP forms.

Here's a sample form containing the ribbon control that resembles Microsoft Outlook. It has two tabs: Home and Send / Receive. Clicking a tab displays the toolbar for that tab.

Here's the Send / Receive tab:

So far, I've included two themes: Colorful (above) and Dark Grey (below):

Themes are defined as RGB colors in an XML file so it's a simple matter to add another theme.

The ribbon control is 100% VFP code. Please try it out and let me know of any enhancements you'd like by creating issues in the GitHub repository for the project.

Wednesday, December 23, 2020

Help us plan the next Virtual Fox Fest

We have 11 quick questions to help us plan future Virtual Fox Fest conferences. We would really appreciate your input:

Happy Holidays and wishes for a healthy and prosperous 2021 to all.

Friday, November 06, 2020

Virtual Fox Fest 2020 Follow-up

Here are some follow-up notes about Virtual Fox Fest 2020, the first but likely not the last online event hosted by Geek Gatherings:

  • Videos for all presentations are now available on YouTube for free to everyone, as our contribution to the VFP community. Be sure to subscribe to our channel.
  • If you didn't attend Virtual Fox Fest and want materials (white papers and sample code) for the presentations, go to and "register" for the conference. You're not really registering since it's over, but in the Registration Fees section of the registration page, you'll see "Virtual Fox Fest 2020 Session Materials (download)". The cost of the materials is $49. There's also an opportunity to sponsor Virtual Fox Fest, which means your name will be listed on our Sponsors page.
  • We're planning on doing a survey soon. It'll be sent to all attendees but if you want to participate so you can help shape future events, email and ask to be included.
  • We have tentative dates for an in-person Southwest Fox conference next year: October 14-17, 2021, at the same location as previous years: the SanTan Conference Center in Gilbert, Arizona. At this point, we don't know whether we'll be able to have an in-person event, but hope springs eternal!
  • If you didn't attend Virtual Fox Fest, check out our Facebook page and see what you missed, then plan to attend a future one so you can join in the fun.

Friday, October 30, 2020

Default Git Message as a Pre-Commit Reminder

If you want a reminder when you commit in Git that you need to do something before committing, such as generating the text equivalents of binary files (something I occasionally forget to do if I working on something that doesn't use Project Explorer, which automatically does that for me), do the following:

  • Create a text file anywhere you wish (named, for example, commit.txt) with the default message you want used in Git commits, such as “Remember to DO WHATEVER YOU NEED TO DO".
  • Open a command window in the project folder (the one that has .git as a subdirectory).
  • Type in a command window: git config commit.template “path\commit.txt”, where path is the full path for the text file you created.

Now, whenever you commit, the commit message defaults to “Remember to DO WHATEVER YOU NEED TO DO” (or whatever your message was), which of course you will then overwrite with the real commit message after you do what the reminder tells you to do.

Application Configuration using JSON

After watching Andrew MacNeill's Quasar and JSON: A Full Stack Experience for the DB Developer presentation at Virtual Fox Fest 2020, I was inspired to look at nfJSON, a VFX project by Marco Plaza. This cool project adds JSON support to VFP applications. The thing that tweaked my interest was the ability to convert a JSON string to a VFP object and vice versa with one line of code.

My first thought was using this for configuration settings. Just about every application needs configuration settings: it's better to read settings such as database connection information, file locations, email settings, etc. from a configuration source rather than hard-coding them into the app. I've used the Windows Registry, DBF files, INI, and XML files at various times but all of those require manually coding the reading and writing between the source and the VFP object(s) containing the settings. With nfJSON, it's one line of code.

I created a wrapper class called SFConfiguration. It only has three methods:

  • Load returns an object with properties matching the name/value pairs in the JSON contained in the specified settings file. If the file doesn't exist or is empty (such as the first time the application is run), it calls GetDefaultSettings (described below) to get default settings.
  • Save saves the properties of the specified settings object to the file specified in either the passed file name or the cSettingsFile property if a file name isn't passed.
  • GetDefaultSettings returns JSON for default settings. You can use this one of two ways: subclass SFConfiguration and override GetDefaultSettings to return the desired JSON, or set the oSettings property to a settings object containing the default settings.

Here's an example of using this class to get email settings:

loConfig = createobject('SFConfiguration')
loConfig.cSettingsFile = 'email.json'
loConfig.oSettings     = createobject('EmailSettings')
loSettings = loConfig.Load()
* loSettings contains the email settings for the user;
* if email.json doesn't exist, the settings in the
* EmailSettings class below are used as defaults.
* After the user enters the desired settings in some dialog,
* save them using:

define class EmailSettings as Custom
    Email      = ''
    MailServer = ''
    Port       = 25
    UseSSL     = .F.
    UserName   = 'dhennig'
    Password   = 'mypw'

Here's what the settings object looks like:

Here's what the saved JSON looks like:

Here's another example, this time using a subclass of SFConfiguration for the same thing:

loConfig = createobject('SFEmailConfiguration')
loConfig.cSettingsFile = 'email.json'
loSettings = loConfig.Load()
* loSettings contains the email settings for the user;
* if email.json doesn't exist, the settings in the
SFEmailConfiguration class below are used as defaults.

define class SFEmailConfiguration as SFConfiguration
    function GetDefaultSettings
        text to lcSettings noshow
            return lcSettings

Here's the code for SFConfiguration. It requires nfJSONRead.prg and nfJSONCreate.prg, which you can get from the nfJSON GitHub repository:

define class SFConfiguration as Custom
  cSettingsFile = ''
        && the name and path for the settings file
    cErrorMessage = ''
        && the text of any error that occurs
    oSettings     = ''
        && a settings object

* Load the settings from the file specified in the parameter
* or in This.cSettingsFile and return a settings object. If
* the file doesn't exist
 (such as the first time we're called),
* a settings object containing default
 settings is returned.

    function Load(tcSettingsFile)
        local lcSettingsFile, ;
            lcSettings, ;
            loSettings, ;
            loException as Exception
            lcSettingsFile = evl(tcSettingsFile, This.cSettingsFile)
            if not empty(lcSettingsFile) and file(lcSettingsFile)
                lcSettings = filetostr(lcSettingsFile)
            endif not empty(lcSettingsFile) ...
            if empty(lcSettings)
                lcSettings = This.GetDefaultSettings()
            endif empty(lcSettings)
            loSettings = nfJSONRead(lcSettings)
            This.cErrorMessage = ''
        catch to loException
            This.cErrorMessage = loException.Message
            loSettings = NULL
        This.oSettings = loSettings
        return loSettings

* Save the settings in the specified object to the file
* specified in
 the parameter or This.cSettingsFile.

    function Save(toSettings, tcSettingsFile)
        local lcSettingsFile, ;
            lcSettings, ;
            loException as Exception
        lcSettingsFile = evl(tcSettingsFile, This.cSettingsFile)
        if not empty(lcSettingsFile)
                lcSettings = nfJSONCreate(toSettings, .T.)
                strtofile(lcSettings, lcSettingsFile)
                This.cErrorMessage = ''
            catch to loException
                This.cErrorMessage = loException.Message
            This.cErrorMessage = 'Settings file not specified.'
        endif not empty(lcSettingsFile)
        return empty(This.cErrorMessage)

* Gets the default set of settings as a JSON string; override
* this in a
 subclass if necessary.

    function GetDefaultSettings
        local lcSettings
        if vartype(This.oSettings) = 'O'
            lcSettings = nfJSONCreate(This.oSettings, .T.)
            lcSettings = '{"text":"some text"}'
        endif vartype(This.oSettings) = 'O'
        return lcSettings

Monday, October 26, 2020

Sending Email from VFP Applications: Supporting Newer SMTP Protocols

There are many libraries you can use to send emails from VFP applications. I created my own several years ago: a C# wrapper class using the .NET SMTPClient class, which I call using Rick Strahl's wwDotNetBridge. However, as discussed here, Microsoft no longer recommends using this class because it doesn't support modern protocols (which I can attest to, thanks to several support tickets from customers). As suggested in the article, I've rewritten my wrapper class to use the open source MailKit project.

Here's some code that shows how to use this wrapper class:

local loMail, ;
loMail = newobject('SFMail', 'SFMail.prg')
with loMail
   .cServer      = ''
   .cUser        = 'MyUserName'
   .cPassword    = 'MyPassword'
   .nSMTPPort    = 25
   .cSenderEmail = .cUser
   .cSenderName  = 'My Name'
   .cRecipients  = ''
   .cSubject     = 'Test email'
   .cBody        = 'This is a test message. ' + ;
      '<strong>This is bold text</strong>. ' + ;
      '<font color="red">This is red text</font>'
   .cAttachments = 'koko.jpg'
   llReturn      = .SendMail()
   if llReturn
      messagebox('Message sent')
      messagebox('Message not sent: ' + .cErrorMessage)
   endif llReturn

Here's what the received email looks like. Notice the attached image and the formatted text.

The class supports the following:

  • Text or HTML body: simply include HTML tags in the cBody property and SFMail automatically handles it
  • Attachments: cAttachments is a comma-separated list of file names
  • Normal, CC (the cCCRecipients property), and BCC recipients (the cBCCRecipients property): separate multiple email addresses with commas or semi-colons
  • SMTP or MAPI (using Craig Boyd's VFPExMAPI.fll): set lUseMAPI to .T. to use MAPI or .F. (the default) to use SMTP
  • Adjustable timeout (the nTimeout property, which is in seconds)
  • Adjustable security settings (the nSecurityOptions property; see the MailKit documentation for the values). I find the default setting of 1 (Auto) works best for most servers.
  • Diagnostic logging: set cLogFile to the name and pass of a log file; it will contain the dialog between MailKit and the mail server so you can debug any problems.

You can download SFMail and the supporting files from the Technical Papers page of my web site or directly from here.

Tuesday, October 20, 2020

Regretting not registering for Virtual Fox Fest?


Virtual Fox Fest continues this week and next on October 21 and 27, 2020!

The posts on social media about the first day of Virtual Fox Fest are very uplifting, the sessions were informative and inspiring, and the camaraderie during the social time after the sessions was a lot of fun.

Does this make you wish you were part of the fun and learning? No worries, you can still register before our next conference day on October 21st, and have access to all the conference materials and to videos of the sessions you missed. Head over to our Registration site.

Friday, October 09, 2020

The Fox Show: Virtual FoxFest 2020

Listen to Rick, Tamar, and I discuss Virtual Fox Fest 2020 with Andrew MacNeill on The FoxShow.

Virtual Fox Fest starts next week. If you haven't registered, there's still time: Want to know who else is attending? See

Wednesday, October 07, 2020

Virtual Fox Fest 2020--still time to register

Our thanks to all those who responded to our plea not to wait for the last minute. Here's a reminder in case you got busy and forgot...

Virtual Fox Fest starts next week and is held October 15, 21, and 27, 2020! Get registered today!

Get Your Geekwear

Order your Virtual Fox Fest gear from Choose from the options shown or create your own unique Virtual Fox Fest-wear. 

To choose your favorite color instead of ours, click the item you want and on that item's page, click Customize This Product. On the page that opens, click Product & Color and choose the color you want. 

To create custom items, click any item. On the page that appears, click Customize This Product. On the page that appears, click Product & Color and then click Change Product. You can select from all items offered by Logo Sportswear. If you want the VFF logo printed, be sure to start with one of the t-shirts. If you want the logo embroidered, start with anything other than one of the t-shirts. 

Once your VFF gear arrives, post your pictures on social media with the hashtag #VirtualFoxFest, so we can see them.

Only 8 days until we gather virtually via the Internet! We look forward to seeing everyone soon.

Wednesday, September 30, 2020

Time to register for Virtual Fox Fest

Thanks to all who have already registered for Virtual Fox Fest; we appreciate your support and our speakers are excited to share all their sessions with you all soon.

That said, we know there are procrastinators who have not registered and have good intentions to do so before the conference starts. Please, please, please do so sooner than later. Our hard working registration staff of one is also a presenter who is practicing and refining his session, and an organizer, and has more than a full-time job working on customer projects. If you all wait until the week of the conference to register, let’s just say you might not get the credentials in time to see the first session on October 15th. It literally takes minutes to register.

We don’t want you to miss all the details about the conference we are sharing over the next couple of weeks. We want you to have a chance to read white papers and download the examples once we release them before the conference starts. We’d hate to see you miss the opportunity to get a head start on all the goodies. Go get registered! Now, really, don’t waste another minute. Here is the link:

Virtual Fox Fest is October 15, 21, and 27, 2020!

Friday, September 04, 2020

Virtual Fox Fest 2020: GeekWear and Speaker Changes

We're pleased to announce GeekWear by Geek Gatherings. Order your Virtual Fox Fest gear from the options shown or create your own unique VFFwear.

Unfortunately, because of family matters, Cathy Pountney had to withdraw from presenting this year. Fortunately, John Ryan offered to present "Visual FoxPro Advanced and VFP C++ Compiler: a New Lease of Life for VFP".

Wednesday, July 15, 2020

Virtual Fox Fest 2020: Speakers, Sessions, and Registration

Speakers and sessions for Virtual Fox Fest 2020 have been announced, and registration is open. Virtual Fox Fest is October 15, 21, and 27, 2020.

Friday, May 29, 2020

Virtual Fox Fest 2020 Speaker Deadline

Just a reminder that the deadline to submit session proposals for Virtual Fox Fest is next Monday, June 1st. You'll find details on our Call for Speakers page. We look forward to your ideas and session proposals.

Virtual Fox Fest is October 15, 21, and 27, 2020!

Wednesday, May 13, 2020

Virtual Fox Fest 2020: All new virtual Fox conference in October

We're disappointed to announce that due to COVID-19, the annual Southwest Fox Conference is on hiatus in 2020. However, we’re excited to offer you Virtual Fox Fest, an online conference presenting the latest in Microsoft Visual FoxPro development techniques and interoperability with other technologies. This conference provides a venue for VFP experts to come together virtually to learn more about how our fellow programmers are using and extending VFP. For details about Virtual Fox Fest, please see

We've issued the Call for Speakers for Virtual Fox Fest. If you are interested in presenting, please read the document referenced in that page and consider submitting sessions. If you previously submitted sessions for Southwest Fox 2020, you don’t need to resubmit for Virtual Fox Fest (but feel free to delete or revise your prior submissions or submit new sessions).

Friday, March 27, 2020

Southwest Fox 2020 Call for Speakers Deadline Extended

We understand you're probably not thinking much beyond the next few weeks or months, but we're still planning Southwest Fox 2020 on the assumption that the current crisis will be over by November. In light of that, we're extending the speaker submission deadline to Monday, April 13. If you have something to share with our developer community, read the Call for Speakers document ( and then use the Submission site ( to send us your session proposals. We look forward to your ideas.

Friday, February 28, 2020

Southwest Fox 2020 Call for Speakers

We've issued the Call for Speakers for Southwest Fox 2020. If you're interested in presenting, please read the document referenced in that page and consider submitting sessions via the Geek Gatherings Submission Web site.

Wednesday, January 15, 2020

Hacker’s Guide to Visual FoxPro is now Open Source

I am pleased to announce on behalf of the authors of “Hacker’s Guide to Visual FoxPro” (Tamar Granor, Ted Roche, Della Martin, and me, with contributions from Steven Black) that the book is now open source:

Most people consider HackFox to be the “bible” for VFP developers because it goes far beyond the VFP help and tells you how VFP really works. It advises which commands and functions to use, which to avoid, and the best way to accomplish certain tasks.

HackFox has gotten a little long in the tooth since it wasn’t updated after VFP 7. Hopefully making it open source will allow it to flourish as people in our community update existing topics and add new topics for VFP 8 and 9. Also, the online content currently closely matches that of the book but that may change over time so it can become a better online resource.

Monday, January 13, 2020

Stonefield Database Toolkit is now Open Source

Inspired by Steve Black open sourcing INTL, I’ve decided to open source Stonefield Database Toolkit (SDT).

SDT was originally created in 1995 and Stonefield Software sold a ton of copies of it over the years, making it one of the most popular add-ons for Visual FoxPro ever. However, nearly 25 years later, my baby has grown up and it’s time to open it up and share it freely with the VFP community that has supported us all this time.

You can find the open source version of SDT at It includes all source code, documentation (as a CHM file, including West Wind HTML Help Builder source; I didn’t convert it to Markdown), and tutorial files. Enjoy!