“SKIP” keyword in FoxPro examples.

A helpful note from a Chilkat customer:

I wanted to update you on the problem for future reference.
SKIP is a reserved word in Visual Foxpro, I should have caught it, but didn’t
until 2 days of screwing with it.  I knew it had to be something simple, because
everything of yours worked perfect, fast, without a hitch except when I compiled
then VFP kicked out a syntax error and nothing else to lead me to a HINT.
I checked and rechecked everything over and over….then I realized it !
I hope this helps you with future VFP questions. Also,
Thanks for responding so quick….Happy 4th of July !!!

Thanks again for great programming tools!   I luv Chilkat Components!

The following callBack procedures used the word SKIP in online examples or blog posts:

**************************** FTP General CallBack Procs **********************
* VerifyDeleteDir
PROCEDURE _IChilkatFtp2Events_VerifyDeleteDir(dirPath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method VerifyDeleteDir”
ENDPROC
* VerifyDeleteFile
PROCEDURE _IChilkatFtp2Events_VerifyDeleteFile(FilePath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method VerifyDeleteFile”
ENDPROC
**************************** FTP Upload CallBack Procs **********************
* BeginUploadFile
PROCEDURE _IChilkatFtp2Events_BeginUploadFile(FilePath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method BeginUploadFile”
pnThermFtpCnt=1
*  ? ‘BeginUploadFile’
ENDPROC
* VerifyUploadDir
PROCEDURE _IChilkatFtp2Events_VerifyUploadDir(dirPath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method VerifyUploadDir”
ENDPROC
**************************** FTP Download CallBack Procs **********************
* BeginDownloadFile
PROCEDURE _IChilkatFtp2Events_BeginDownloadFile(FilePath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method BeginDownloadFile”
pnThermFtpCnt=1
*  ? ‘BeginDownloadFile’
ENDPROC

* VerifyDownloadDir
PROCEDURE _IChilkatFtp2Events_VerifyDownloadDir(dirPath AS STRING, SKIP AS NUMBER) AS VOID;
HELPSTRING “method VerifyDownloadDir”
ENDPROC

Register an ActiveX DLL from within FoxPro

A Chilkat customer provided this bit of Foxpro code:

DECLARE LONG DllRegisterServer IN <yourfile.dll>
IF DllRegisterServer() = 0
   * OK
ELSE
  * Not OK
ENDIF

It provides an alternative way to distribute an ActiveX DLL with a FoxPro application. Typically, one would create an installer, such as a .msi or something from an install software package (InstallShield perhaps), such that the installer registers any ActiveX DLL’s included in the setup/deployment project when installing. However, using the idea above, it should be possible to simply include the ActiveX DLL in the same directory as the EXE and potentially distribute as a simple .zip. When the app is first run, it could automatically register the ActiveX DLL.

Windows Application User-Interface Freezes?

Question:

I recently purchased the Chilkat HTTP component and am using it with a Visual FoxPro application. However, each time I run it the form freezes and I get the Not Responding message in the title bar. I have an animated GIF that I am using as a quasi-progress meter but that freezes as well. As soon as the HTTP Download finished, the form gets the focus back and the download is successful.

I need the animated GIF to keep working and to avoid the freeze and Not Responding message. Happens every time. Plus the mouse cursor pointer disappears from the VFP form.

Answer:

To answer this question, I must first describe the basic architecture of all interactive Windows-based applications w/ user-interfaces. This applies to all programming languages: FoxPro, VB6, MFC (C++), C#, VB.NET, etc.

Microsoft Windows programs are event-based. They act upon messages that the operating system posts to the main application thread. These messages are received from the message queue by the application by repeatedly calling the GetMessage (or PeekMessage) function in a section of code called the “event loop.” (See this Wikipedia article: Message Loop in Microsoft Windows)

In higher-level programming languages such as FoxPro, VB6, etc., the actual code for the app’s message loop is hidden from you. The application programmer interactively designs a user-interface and provides code (handlers) for user-interface events. For example, when “Button A” is pressed, call this subroutine (or function). Typically, the code in your button handler finishes quickly and returns control back to the caller. It happens so fast that you never notice that technically the user-interface was “frozen” for the short amount of time spent in your button-handler code.

It becomes apparent that user-interface events are not being handled when your application code takes longer to complete before returning control back to the app’s main event loop (i.e. before returning control to the FoxPro, VB6, C#, etc. runtime). It may also help to think of it this way: Since the application is single-threaded, it can only be doing one thing at a time. While the application thread is executing the application code, it can’t possibly be doing something else, such as executing code to update the user-interface.

The solution is that within your application code you must periodically handle any accumulated user-interface events. In Visual Basic 6.0, C#, and VB.NET, this is accomplished by calling the DoEvents function:

(from the Microsoft online documentation for Application.DoEvents)

“When you run a Windows Form, it creates the new form, which then waits for events to handle. Each time the form handles an event, it processes all the code associated with that event. All other events wait in the queue. While your code handles the event, your application does not respond. For example, the window does not repaint if another window is dragged on top.

If you call DoEvents in your code, your application can handle the other events. For example, if you have a form that adds data to a ListBox and add DoEvents to your code, your form repaints when another window is dragged over it. If you remove DoEvents from your code, your form will not repaint until the click event handler of the button is finished executing…”

In Visual FoxPro, it is the DOEVENTS command.

Since the bulk of the time spent within your application code may be within a Chilkat function call (especially if it involves communications over the Internet), then you must tell the Chilkat component to make periodic callbacks to your application code, so that your application can then call DoEvents. The standard way of doing this w/ Chilkat is via the AbortCheck event. The HeartbeatMs property controls the frequency of AbortCheck event callbacks. The default value is 0, which indicates no AbortCheck events. Set it to a value such as 100 for event callbacks every 1/10 of a second.

For more information: ActiveX Events in FoxPro

For more information: AbortCheck in C# and VB.NET

ActiveX Events in FoxPro

ActiveX components and controls are used in many programming languages, each of which has it’s own way of handling event callbacks.  This blog post provides helpful hints about how to receive event callbacks from an ActiveX component.

To receive the event, you must bind the ActiveX (also referred to as the COM server) event to the implemented interface methods on a Visual FoxPro object.   This is done using FoxPro’s EVENTHANDLER function.  For example:

* oCtrl will be the object in Visual FoxPro to receive the event notifications.
* It will implement one or more of the ActiveX's event callback methods
oCtrl = CREATEOBJECT("Ctrl")

* Create an instance of an ActiveX component:
loMailman = CreateObject('Chilkat.MailMan2')
...

*The EVENTHANDLER tells the COM object to send events to the VFP object:
EVENTHANDLER(loMailman,oCtrl)

Let’s look at the VFP object’s class (i.e. oCtrl):

*Definition of control class:
DEFINE CLASS Ctrl as Session OLEPUBLIC

*The IMPLEMENTS... line below is what makes Foxpro take control over the SendPercentDone,
ReadPercentDone and AbortCheck
*NOTE - This path part of the IMPLEMENTS must point to the dll, so locate and correct it
before you are using the program.
IMPLEMENTS _IChilkatMailEvents IN "c:\mydlls\chilkatmail_v7_9.dll"

PROCEDURE Init
ENDPROC

PROCEDURE _IChilkatMailEvents_SendPercentDone(percentDone AS Number, abort AS Number) AS VOID;
    HELPSTRING "method SendPercentDone"
    * add user code here

ENDPROC

PROCEDURE _IChilkatMailEvents_ReadPercentDone(percentDone AS Number, abort AS Number) AS VOID;
    HELPSTRING "method ReadPercentDone"
    * add user code here

ENDPROC

PROCEDURE _IChilkatMailEvents_AbortCheck(abort AS Number) AS VOID;
    HELPSTRING "method AbortCheck"
    * add user code here

ENDPROC

PROCEDURE _IChilkatMailEvents_EmailReceived(subject AS String, fromAddr AS String
    fromName AS String, returnPath AS String, date AS String, uidl AS String, 
    sizeInBytes AS Number) AS VOID;
    HELPSTRING "method EmailReceived"
    * add user code here

ENDPROC

ENDDEFINE

This is not enough for events to fire.  You’ll need to take one additional step:  Set the AutoYield property = .T. to allow ActiveX events to fire.

Finally, how do you know what events are available for a given ActiveX?   Unfortunately, Chilkat does not have programming-language specific help for the events.  We can look at the IDL for the events and then understand how to write the FoxPro event interfaces.  For example, here’s the IDL for Chilkat MailMan:

dispinterface _IChilkatMailEvents
{
properties:
methods:
[id(1), helpstring("method SendPercentDone")] HRESULT SendPercentDone([in] long percentDone, [out] long *abort);
[id(2), helpstring("method ReadPercentDone")] HRESULT ReadPercentDone([in] long percentDone, [out] long *abort);
[id(3), helpstring("method AbortCheck")] HRESULT AbortCheck([out] long *abort);
[id(4), helpstring("method EmailReceived")] HRESULT EmailReceived([in] BSTR subject, [in] BSTR fromAddr,
    [in] BSTR fromName, [in] BSTR returnPath, [in] BSTR date, [in] BSTR uidl, [in] long sizeInBytes);
};

A few notes:

  • Notice the “_IChilkatMailEvents” corresponds to the “_IChilkatMailEvents” in the FoxPro code.
  • All event methods will be declared as a PROCEDURE returning VOID (i.e. “AS VOID”)
  • Ignore the HRESULT in the IDL.  It doesn’t apply in FoxPro.
  • In the IDL, BSTR means “string”.
  • In the IDL, input arguments are specified by “[in]”, output arguments are specified by “[out]”.  A common output argument is “abort”.  Your event handler may set it equal to 1 to abort the current Chilkat method that is running, or leave it at 0 to allow it to continue.

That’s about it.   You should be able to look at the IDL and know how to create your event handling code in FoxPro.  Here’s a link to the IDL for SFtp, Zip, MailMan, Ftp2, HTTP, and IMAP: http://cknotes.com/?p=119

FTP2 Events for FoxPro

The Chilkat FTP2 ActiveX has events for progress monitoring. The events may also be used to abort an FTP upload/download, or to skip files and/or directories.

These are the events in Visual FoxPro terms:

PROCEDURE _IChilkatFtp2Events_PutProgress(percentDone AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_GetProgress(percentDone AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_AbortCheck(abortFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_BeginDownloadFile(filePath AS String, skipFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_EndDownloadFile(filePath AS String, numBytes AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_VerifyDownloadDir(dirPath AS String, skipFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_BeginUploadFile(filePath AS String, skipFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_EndUploadFile(filePath AS String, numBytes AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_VerifyUploadDir(dirPath AS String, skipFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_VerifyDeleteDir(dirPath AS String, skipFlag AS Number) AS VOID;
PROCEDURE _IChilkatFtp2Events_VerifyDeleteFile(filePath AS String, skipFlag AS Number) AS VOID;

The “skipFlag” and “abortFlag” args are output-only.

An example of using ActiveX events in FoxPro may be found here:
Email Events in FoxPro
Although the example is for sending email, the same programming techniques apply with the FTP2 component.