General discussion

  • Creator
    Topic
  • #2185601

    The SPS Weblog

    Locked

    by craigaaa3 ·

    blog root

All Comments

  • Author
    Replies
    • #3050193

      Email and VFP: Part 1f (WinExec)

      by craigaaa3 ·

      In reply to The SPS Weblog

      As we saw in the last example, ShellExecute comes with a pretty serious size restriction
      for the MailTo URL – 2048 bytes (though it was 2020 bytes on my system).  That’s
      just not large enough for the contents of most emails.  If your users use Outlook
      Express, then the following code may come in handy.  It raises the restriction
      from about 2KB to almost 32KB.

      *******************************
      *!* Example of using SendViaWinExec
      *******************************
      LOCAL lcTo, lcSubject, lcBody, lcCC, lcBCC, lcErrReturn
      lcTo = “
      someone@somewhere.com
      lcSubject = “Hey Have You Tried VFP Email?”
      lcBody = “Just wanted to let you know that VFP is pretty versatile” + CHR(13) + “and
      has a lot of ways to send email.”
      lcCC = “
      someoneelse@anotherhost.com
      lcBCC = “
      myboss@boss.com

      SendViaWinExec(@lcErrReturn, lcTo, lcSubject, lcBody,
      lcCC, lcBCC)

      IF EMPTY(lcErrReturn)
        MESSAGEBOX(“‘” + lcSubject + “‘ opened successfullly.”, 64, “Send email via
      WinExec”)
      ELSE
        MESSAGEBOX(“‘” + lcSubject + “‘ failed to be sent.  Reason:” + CHR(13)
      + lcErrReturn, 64, “Send email via WinExec”)
      ENDIF

      *******************************************
      PROCEDURE SendViaWinExec(tcReturn, tcTo, tcSubject, tcBody, tcCC, tcBCC)
      *******************************************

      DECLARE INTEGER WinExec IN kernel32 ;
          STRING lpCmdLine ,;
          INTEGER uCmdShow

        LOCAL lcCommand, lcCRLF
       

        TRY
          lcCRLF = “%0D%0A”
          lcCommand = [“C:\Program Files\Outlook Express\msimn.exe” /mailurl:mailto:]
      + tcTo + “?Subject=” + tcSubject + “&Body=” + STRTRAN(tcBody, CHR(13), lcCRLF)
          IF TYPE(“tcCC”) = “C”
            lcCommand = lcCommand + “&CC=” + tcCC
          ENDIF
          IF TYPE(“tcBCC”) = “C”
            lcCommand = lcCommand + “&BCC=” + tcBCC
          ENDIF
          IF LEN(lcCommand) > 32766 && should be 32768, but not
      on my system
            THROW “Mailto command is limited to 32768 bytes”
          ENDIF

       WinExec(lcCommand, 1)

        CATCH TO loError
          tcReturn = [Error: ] + STR(loError.ERRORNO) + CHR(13) + ;
            [LineNo: ] + STR(loError.LINENO) + CHR(13) + ;
            [Message: ] + loError.MESSAGE + CHR(13) + ;
            [Procedure: ] + loError.PROCEDURE + CHR(13) + ;
            [Details: ] + loError.DETAILS + CHR(13) + ;
            [StackLevel: ] + STR(loError.STACKLEVEL) + CHR(13)
      + ;
            [LineContents: ] + loError.LINECONTENTS
        FINALLY
          CLEAR DLLS “WinExec”
        ENDTRY
      ENDPROC

      UPDATES
      07/15/2005 Changed the THROW so it reflected 32768 bytes instead
      of 2048 bytes


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050196

      Email and VFP: Part 1h (BLAT)

      by craigaaa3 ·

      In reply to The SPS Weblog

      The code below requires BLAT 2.40 (the version of the DLL that was based on 1.9.4
      will not send multiple comma delimited attachments).  So, if you don’t have it, download
      BLAT here
      .

      BLAT comes in two flavors, the Exe and the DLL.  I personally prefer the the
      DLL… it’s small around 100kb and it is a C DLL so it doesn’t need to be registered
      on a user’s machine.  The best part of BLAT is that it was released into the
      Public Domain (Free as Free gets) and it is open source (you get the code). 
      The features that this little component has are pretty impressive.  Once you’ve
      had an opportunity to run the code below, take a look at some of the other
      features
      (switches) that are available.  Also, here is the official
      site for BLAT
      where you can get additional information regarding the project.

      Okay, with all that out of the way, let’s take a look at the code.

      *******************************
      *!* Example of using SendViaBLAT
      *******************************
      #DEFINE PRIORITYHIGH 1
      #DEFINE PRIORITYLOW 0

      DIMENSION aryAttach(2)
      aryAttach(1) = “C:\attachment1.txt” && change to an actual file that exists
      on your computer
      aryAttach(2) = “C:\attachment2.zip” && change to an actual file that exists
      on your computer

      LOCAL lcFrom, lcTo, lcSubject, lcBody, lcCC, lcBCC,
      lcMailServer, lcUserName, lcPassword, lnPort, lnPriority, llHTMLFormat, lcErrReturn

      lcFrom = “me@myhost.com
      lcTo = “someone@theirhost.com
      lcSubject = “Hey Have You Tried VFP Email?”
      *!* Sending the body in HTML format
      llHTMLFormat = .T. && change to .F. to send plain text message
      lcBody = “<a href=’http://www.sweetpotatosoftware.com/SPSBlog/default.aspx’>&#8221;
      + ;
       “Hey Have You Tried VFP Email?” + ;
       “</a>”
      lcCC = “someoneelse@someotherhost.com
      lcBCC = “myboss@bosshost.com
      lcMailServer = “mail.myhost.com” && my SMTP Server
      lnPort = 25 && default SMTP Server port
      lcUserName = “MyUsername” && my SMTP username
      lcPassword = “My_PaSsWoRd” && my SMTP password
      lnPriority = PRIORITYHIGH

      SendViaBLAT(@lcErrReturn, lcFrom, lcTo, lcSubject,
      lcBody, @aryAttach, lcCC, lcBCC, lcMailServer, lnPort, lcUserName, lcPassword, lnPriority,
      llHTMLFormat)

      IF EMPTY(lcErrReturn)
       MESSAGEBOX(“‘” + lcSubject + “‘ sent successfullly.”, 64, “Send email via BLAT”)
      ELSE
       MESSAGEBOX(“‘” + lcSubject + “‘ failed to be sent.  Reason:” + CHR(13)
      + lcErrReturn, 64, “Send email via BLAT”)
      ENDIF

      *******************************************
      PROCEDURE SendViaBLAT(tcReturn, tcFrom, tcTo, tcSubject, tcBody, taFiles, tcCC, tcBCC,
      tcMailServer, tnPort, tcUserName, tcPassword, tnPriority, tlHTMLFormat)
      *******************************************
       LOCAL lcBlatParam, lcBodyFile, lnCountAttachments, lnResult, loError as Exception
       
       lcBodyFile = “”
       
       TRY
        *!* Include full path in Declare, such as “C:\Blat240\full\blat.dll”
        *!* or make sure that blat.dll is included in the system’s PATH variable
        DECLARE INTEGER Send IN “blat.dll” STRING cParam
        
        lcBodyFile = ADDBS(SYS(2023)) + SYS(2015) + “.txt”
        STRTOFILE(tcBody, lcBodyFile, 0) && body is placed in a text file
      to be sent by BLAT
        
        lcBlatParam = GetShortPath(lcBodyFile)
        
        IF TYPE(“tcTo”) = “C”
          lcBlatParam = lcBlatParam + ” -to ” + ALLTRIM(tcTo)
        ENDIF
        IF TYPE(“tcFrom”) = “C”
          lcBlatParam = lcBlatParam + ” -f ” + ALLTRIM(tcFrom)
        ENDIF
        IF TYPE(“tcCC”) = “C”
          lcBlatParam = lcBlatParam + ” -cc ” + ALLTRIM(tcCC)
        ENDIF
        IF TYPE(“tcBCC”) = “C”
          lcBlatParam = lcBlatParam + ” -bcc ” + ALLTRIM(tcBCC)
        ENDIF
        IF TYPE(“tcSubject”) = “C”
          lcBlatParam = lcBlatParam + [ -s “] + ALLTRIM(tcSubject) + [“]
        ENDIF
        IF TYPE(“tcMailserver”) = “C”
          lcBlatParam = lcBlatParam + ” -server ” + ALLTRIM(tcMailserver)
        ENDIF
        IF TYPE(“tnPort”) = “N”
          lcBlatParam = lcBlatParam + “:” + TRANSFORM(tnPort)
        ENDIF
        IF TYPE(“tcUsername”) = “C”
          lcBlatParam = lcBlatParam + ” -u ” + ALLTRIM(tcUsername)
        ENDIF
        IF TYPE(“tcPassword”) = “C”
          lcBlatParam = lcBlatParam + ” -pw ” + ALLTRIM(tcPassword)
        ENDIF
        IF TYPE(“tnPriority”) = “N” AND BETWEEN(tnPriority, 0, 1)
          lcBlatParam = lcBlatParam + ” -priority ” + TRANSFORM(tnPriority)
        ENDIF
        IF TYPE(“tlHTMLFormat”) = “L” AND tlHTMLFormat
          lcBlatParam = lcBlatParam + ” -html”
        ENDIF

        IF TYPE(“taFiles”, 1) = “A”
          lcBlatParam = lcBlatParam + ” -attach “
         FOR lnCountAttachments = 1 TO ALEN(taFiles)
           lcBlatParam = lcBlatParam + GetShortPath(ALLTRIM(taFiles(lnCountAttachments)))
      + “,”
         ENDFOR
         lcBlatParam = LEFT(lcBlatParam, LEN(lcBlatParam) – 1) &&
      Remove Extra Comma
        ENDIF

        lnResult = Send(ALLTRIM(lcBlatParam))
        
        IF lnResult != 0
         DO CASE
          CASE lnResult = -2
           THROW “The server actively denied our connection./The
      mail server doesn’t like the sender name. “
          CASE lnResult = -1
           THROW “Unable to open SMTP socket” OR ;
             “SMTP get line did not return 220” OR ;
             “command unable to write to socket” OR ;
             “Server does not like To: address” OR ;
             “Mail server error accepting message data.”
          CASE lnResult = 1
           THROW “File name (message text) not given” OR ;
             “Bad argument given”
          CASE lnResult = 2
           THROW “File (message text) does not exist”
          CASE lnResult = 3
           THROW “Error reading the file (message text) or attached
      file”
          CASE lnResult = 4
           THROW “File (message text) not of type FILE_TYPE_DISK

          CASE lnResult = 5
           THROW “Error Reading File (message text)”
          CASE lnResult = 12
           THROW “-server or -f options not specified and not found
      in registry”
          CASE lnResult = 13
           THROW “Error opening temporary file in temp directory”
          OTHERWISE
           THROW “Unknown Error”
         ENDCASE
        ENDIF

       CATCH TO loError
        tcReturn = [Error: ] + STR(loError.ERRORNO) + CHR(13) + ;
         [LineNo: ] + STR(loError.LINENO) + CHR(13) + ;
         [Message: ] + loError.MESSAGE + CHR(13) + ;
         [Procedure: ] + loError.PROCEDURE + CHR(13) + ;
         [Details: ] + loError.DETAILS + CHR(13) + ;
         [StackLevel: ] + STR(loError.STACKLEVEL) + CHR(13) + ;
         [LineContents: ] + loError.LINECONTENTS
       FINALLY
        CLEAR DLLS “Send”
        IF FILE(lcBodyFile)
         ERASE (lcBodyFile)
        ENDIF
       ENDTRY
      ENDPROC

      ****************************************
      Function GetShortPath
      ****************************************
       LPARAMETERS lcFileName
       LOCAL lnReturn, lcBuffer

       Declare Integer GetShortPathNameA In Win32API
      As GetShortPathName String, String, Integer

       lcBuffer = SPACE(255)
       lnReturn= GetShortPathName(lcFileName, @lcBuffer, 255)

       Clear Dlls “GetShortPathName”
       
       Return (Left(lcBuffer, lnReturn))
      ENDFUNC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050195

      Email and VFP: Part 1g (w3JMail)

      by craigaaa3 ·

      In reply to The SPS Weblog

      The following code works with w3Jmail, which is available
      as FREEWARE
      .  They have other licenses available as well, so should
      you need more functionality than the code below provides you can have it.  Their
      documentation is good, especially when compared to most other 3rd party components
      for email.  I’ve used w3JMail with excellent success and highly recommend it
      (I’m not affiliated with the company in anyway). 

      *******************************
      *!* Example of using SendViaJMail
      *******************************
      ***Requires FREE w3JMail v4.4 (code works with v3.0 and above)
      ***Download at
      http://tech.dimac.net/default2.asp?M=Products/MenuCOM.asp&P=Products/w3JMail/start.htm

      *******************************
      #DEFINE PRIORITYURGENT 1
      #DEFINE PRIORITYHIGH 2
      #DEFINE PRIORITYNORMAL 3
      #DEFINE PRIORITYLOW 4
      #DEFINE PRIORITYLOWEST 5

      DIMENSION aryAttach(2)
      aryAttach(1) = “C:\attachment1.txt” && change to an actual file that exists
      on your computer
      aryAttach(2) = “C:\attachment2.zip” && change to an actual file that exists
      on your computer

      LOCAL lcToAddress, lcToName, lcFromAddress, lcFromName,
      lcSubject, lcBody, lcCC, lcBCC, lcMailServer, lcUserName, lcPassword, lnPort, lcErrReturn
      lcToAddress = “
      someone@somehost.com
      lcToName =  “Their Name”
      lcFromAddress = “
      me@myhost.com
      lcFromName = “My Name”
      lcSubject = “Hey Have You Tried VFP Email?”
      lcBody = “Just wanted to let you know that VFP is pretty versatile and has a lot of
      ways to send email.”
      lcCC = “
      someoneelse@someotherhost.com
      lcBCC = “
      myboss@bosshost.com
      lcMailServer = “mail.myhost.com”
      lcUserName = “MyUsername” && my SMTP username
      lcPassword = “My_PaSsWoRd” && my SMTP password
      lnPort = 25 && SMTP standard port
      llHTMLFormat = .F. && Change to .T. if lcBody is HTML
      SendViaJMail(@lcErrReturn, lcToAddress, lcToName, lcFromAddress, lcFromName, lcSubject,
      lcBody, @aryAttach, lcCC, lcBCC, lcMailServer, lcUserName, lcPassword, lnPort, PRIORITYURGENT,
      llHTMLFormat)

      IF EMPTY(lcErrReturn)
       MESSAGEBOX(“‘” + lcSubject + “‘ sent successfullly.”, 64, “Send email via JMail”)
      ELSE
       MESSAGEBOX(“‘” + lcSubject + “‘ failed to be sent.  Reason:” + CHR(13)
      + lcErrReturn, 64, “Send email via JMail”)
      ENDIF


      *******************************************
      PROCEDURE SendViaJMail(tcReturn, tcToAddress, tcToName, tcFromAddress, tcFromName,
      tcSubject, tcBody, taFiles, tcCC, tcBCC, tcMailServer, tcUserName, tcPassword, tnPort,
      tnPriority, tlHTMLFormat)
      *******************************************
       LOCAL loSMTPMail, lnCountAttachments, loError AS EXCEPTION

       tcReturn = “”

       TRY
           loSMTPMail  = CREATEOBJECT(“jmail.SMTPMail”)
           WITH loSMTPMail

            IF TYPE(“tcMailServer”) = “C”
             .ServerAddress = tcMailServer
             IF TYPE(“tcUserName”) = “C” AND TYPE(“tcPassword”)
      = “C”
              .ServerAddress = tcUserName + “:” + tcPassword
      + “@” + .ServerAddress
             ENDIF
             IF TYPE(“tnPort”) = “N”
              .ServerAddress = .ServerAddress + “:” +
      TRANSFORM(tnPort)
             ENDIF
            ENDIF
      *!*   .Charset = “US-ASCII” && Can change charset, iso-8859-1
      is default
        IF TYPE(“tcToName”) = “C”
         .AddRecipientEx(tcToAddress, tcToName )
        ELSE
               .AddRecipient(tcToAddress)
             ENDIF
               IF TYPE(“tcCC”) = “C”
                .AddRecipientCc(tcCC)
               ENDIF
               IF TYPE(“tcBCC”) = “C”
                .AddRecipientBcc(tcBCC)
        ENDIF
        IF TYPE(“tcFromAddress”) = “C”
               .Sender = tcFromAddress
              endif
               IF TYPE(“tcFromName”) = “C”
                .SenderName = tcFromName
               ENDIF
               IF TYPE(“tlHTMLFormat”) = “L” AND
      tlHTMLFormat
                .ContentType = “text/html”
               ELSE
                .ContentType = “text/plain”
      && Default
               ENDIF
               .Subject = tcSubject
               .Body = tcBody
               IF TYPE(“tnPriority”) = “N”
                .Priority = tnPriority
               ELSE
                .Priority = 3 && Default
               ENDIF
               IF TYPE(“taFiles”,1) = “A”
                   FOR lnCountAttachments
      = 1 TO ALEN(taFiles)
                      
      .AddAttachMent(taFiles(lnCountAttachments))
                   ENDFOR
               ENDIF
               .Execute()
           ENDWITH
       CATCH TO loError
        tcReturn = [Error: ] + STR(loError.ERRORNO) + CHR(13) + ;
         [LineNo: ] + STR(loError.LINENO) + CHR(13) + ;
         [Message: ] + loError.MESSAGE + CHR(13) + ;
         [Procedure: ] + loError.PROCEDURE + CHR(13) + ;
         [Details: ] + loError.DETAILS + CHR(13) + ;
         [StackLevel: ] + STR(loError.STACKLEVEL) + CHR(13) + ;
         [LineContents: ] + loError.LINECONTENTS
       FINALLY
           RELEASE loSMTPMail

           loSMTPMail  = .NULL.
       ENDTRY
      ENDPROC


      >>
      >
      >>
      >


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050194

      Take the MIT Weblog Survey

      by craigaaa3 ·

      In reply to The SPS Weblog

      Take the MIT Weblog Survey

      This is a general social survey of the greater weblog community being conducted at
      the Massachusetts Institute of Technology.

      Some additional early%20resultsfrom%20the%20survey%20look%20interesting. %20The%20full%20results%20should%20be%20coming%20out%20soon,%20so%20if%20you%20haven’t%20taken%20the%20survey,%20but%20want%20to,%20now’s%20the%20time.

      They’ve%20provided%20some%20more%20detailed
      information about the survey, privacy etc..

      Ran into this survey while reading Rockford
      Lhotka’s Weblog
      .


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050192

      Email and VFP: Part 1e (Shell)

      by craigaaa3 ·

      In reply to The SPS Weblog

      You can send a Mailto URL as the command to ShellExecute to facilitate email
      in VFP.  It should be noted that the command line (URL) is limited to 2048 bytes
      (though on my system I couldn’t create one longer than 2020 bytes) and there is no
      facility for attaching files using this method.  These severe limitations aside,
      it is a solution that has its places in VFP development.

      *******************************
      *!* Example of using SendViaShell
      *******************************
      LOCAL lcTo, lcSubject, lcBody, lcCC, lcBCC, lcErrReturn
      lcTo = “
      someone@somehost.com
      lcSubject = “Hey Have You Tried VFP Email?”
      lcBody = “Just wanted to let you know that VFP is pretty versatile” + CHR(13) + “and
      has a lot of ways to send email.”
      lcCC = “
      someoneelse@anotherhost.com
      lcBCC = “
      myboss@bosshost.com

      SendViaShell(@lcErrReturn, lcTo, lcSubject, lcBody,
      lcCC, lcBCC)

      IF EMPTY(lcErrReturn)
        MESSAGEBOX(“‘” + lcSubject + “‘ opened successfullly.”, 64, “Send email via
      Shell”)
      ELSE
        MESSAGEBOX(“‘” + lcSubject + “‘ failed to be sent.  Reason:” + CHR(13)
      + lcErrReturn, 64, “Send email via Shell”)
      ENDIF

      *******************************************
      PROCEDURE SendViaShell(tcReturn, tcTo, tcSubject, tcBody, tcCC, tcBCC)
      *******************************************
        DECLARE INTEGER ShellExecute IN shell32.DLL ;
          INTEGER hwndWin, STRING cOperation, STRING cFile, ;
          STRING cParameters, STRING cDirectory, INTEGER nShowWin

        LOCAL lcCommand, lcCRLF
       

        TRY
          lcCRLF = “%0D%0A”
          lcCommand = “mailto:” + tcTo + “?Subject=” + tcSubject + “&Body=”
      + STRTRAN(tcBody, CHR(13), lcCRLF)
          IF TYPE(“tcCC”) = “C”
            lcCommand = lcCommand + “&CC=” + tcCC
          ENDIF
          IF TYPE(“tcBCC”) = “C”
            lcCommand = lcCommand + “&BCC=” + tcBCC
          ENDIF
          IF LEN(lcCommand) > 2020 && should be 2048, but not
      on my system
            THROW “Mailto command is limited to 2048 bytes”
          ENDIF
          ShellExecute(0, “open”, lcCommand, “”, “”, 1)
        CATCH TO loError
          tcReturn = [Error: ] + STR(loError.ERRORNO) + CHR(13) + ;
            [LineNo: ] + STR(loError.LINENO) + CHR(13) + ;
            [Message: ] + loError.MESSAGE + CHR(13) + ;
            [Procedure: ] + loError.PROCEDURE + CHR(13) + ;
            [Details: ] + loError.DETAILS + CHR(13) + ;
            [StackLevel: ] + STR(loError.STACKLEVEL) + CHR(13)
      + ;
            [LineContents: ] + loError.LINECONTENTS
        FINALLY
          CLEAR DLLS “ShellExecute”
        ENDTRY
      ENDPROC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050191

      GDI+ Constants

      by craigaaa3 ·

      In reply to The SPS Weblog

      I ran into this really cool GDI+ typelib that was written by Dana Seaman as I was
      studying GDI+ for VFP.  Given VFP’s lack of Enumerations, it sure was a big help
      and saved me countless searches to find the values.  These will go hand-in-hand
      with the Declares I posted this morning.  With Dana’s permission, here they are:

      **************************
      *!* VFP GDI+ Constants
      *!* 07/16/2005 – Created and modified for VFP
      *!* by Craig Boyd from Dana Seaman’s gdi+ typelib
      *!* Dana’s email addresses have been removed to

      *!* prevent spamming, they’re easy enough to get
      *!* as the tlb is freely available from CyberActiveX
      *!* website.  Permission to post was granted 07-17-2005
      **************************
      *!* #DEFINE GDIplus_TYPELIB_DATE “Friday, 07 February 2003 02:40:20 UTC” 
      *!* #DEFINE GDIplus_TYPELIB_AUTHOR “Dana Seaman”
      *!* #DEFINE GDIplus_TYPELIB_VERSION “1.05” 
      *!* #DEFINE GDIplus_TYPELIB_COPYRIGHT “Copyright 2003, Dana Seaman” 
      *!* #DEFINE GDIplus_TYPELIB_DESCRIPTION “Windows GDI+ Type Library” 
      *!* #DEFINE GDIplus_TYPELIB_URL “
      http://www.cyberactivex.com/” 

      #DEFINE IPictureGUID “{7BF80980-BF32-101A-8BBB-00AA00300CAB}” 

      #DEFINE ImageFormatUndefined  “{B96B3CA9-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatMemoryBMP  “{B96B3CAA-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatBMP    “{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatEMF    “{B96B3CAC-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatWMF    “{B96B3CAD-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatJPEG    “{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatPNG    “{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatGIF    “{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatTIFF    “{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatEXIF    “{B96B3CB2-0728-11D3-9D7B-0000F81EF32E}” 
      #DEFINE ImageFormatIcon    “{B96B3CB5-0728-11D3-9D7B-0000F81EF32E}” 

      #DEFINE FrameDimensionTime   “{6AEDBD6D-3FB5-418A-83A6-7F45229DC872}” 
      #DEFINE FrameDimensionResolution “{84236F7B-3BD3-428F-8DAB-4EA1439CA315}” 
      #DEFINE FrameDimensionPage   “{7462DC86-6180-4C7E-8E3F-EE7333A7A483}” 

      #DEFINE FormatIDImageInformation “{E5836CBE-5EEF-0F1D-ACDE-AE4C43B608CE}” 
      #DEFINE FormatIDJpegAppHeaders  “{1C4AFDCD-6177-43CF-ABC7-5F51AF39EE85}” 

      #DEFINE EncoderCompression  “{E09D739D-CCD4-44EE-8EBA-3FBF8BE4FC58}” 
      #DEFINE EncoderColorDepth  “{66087055-AD66-4C7C-9A18-38A2310B8337}” 
      #DEFINE EncoderScanMethod  “{3A4E2661-3109-4E56-8536-42C156E7DCFA}” 
      #DEFINE EncoderVersion   “{24D18C76-814A-41A4-BF53-1C219CCCF797}” 
      #DEFINE EncoderRenderMethod  “{6D42C53A-229A-4825-8BB7-5C99E2B9A8B8}” 
      #DEFINE EncoderQuality   “{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}” 
      #DEFINE EncoderTransformation “{8D0EB2D1-A58E-4EA8-AA14-108074B7B6F9}” 
      #DEFINE EncoderLuminanceTable “{EDB33BCE-0266-4A77-B904-27216099E717}” 
      #DEFINE EncoderChrominanceTable “{F2E455DC-09B3-4316-8260-676ADA32481C}” 
      #DEFINE EncoderSaveFlag   “{292266FC-AC40-47BF-8CFC-A85B89A655DE}” 

      #DEFINE CodecIImageBytes  “{025D1823-6C7D-447B-BBDB-A3CBC3DFA2FC}” 

      #DEFINE DIB_RGB_COLORS 0 

      #DEFINE PixelFormatIndexed    65536 
      #DEFINE PixelFormatGDI     131072 
      #DEFINE PixelFormatAlpha    262144 
      #DEFINE PixelFormatPAlpha    524288 
      #DEFINE PixelFormatExtended    1048576 
      #DEFINE PixelFormatCanonical   2097152 
      #DEFINE PixelFormatUndefined   0 
      #DEFINE PixelFormatDontCare    0 
      #DEFINE PixelFormat1bppIndexed   196865 
      #DEFINE PixelFormat4bppIndexed   197634 
      #DEFINE PixelFormat8bppIndexed   198659 
      #DEFINE PixelFormat16bppGrayScale  1052676 
      #DEFINE PixelFormat16bppRGB555   135173 
      #DEFINE PixelFormat16bppRGB565   135174 
      #DEFINE PixelFormat16bppARGB1555  397319 
      #DEFINE PixelFormat24bppRGB    137224 
      #DEFINE PixelFormat32bppRGB    139273 
      #DEFINE PixelFormat32bppARGB   2498570 
      #DEFINE PixelFormat32bppPARGB   925707 
      #DEFINE PixelFormat48bppRGB    1060876 
      #DEFINE PixelFormat64bppARGB   3424269 
      #DEFINE PixelFormat64bppPARGB   29622286 
      #DEFINE PixelFormatMax     15 

      #DEFINE AlphaShift 24 
      #DEFINE RedShift 16 
      #DEFINE GreenShift 8 
      #DEFINE BlueShift 0 

      #DEFINE AlphaMask -16777216 
      #DEFINE RedMask  16711680 
      #DEFINE GreenMask 65280 
      #DEFINE BlueMask 255 

      #DEFINE FillModeAlternate 0 
      #DEFINE FillModeWinding  1 

      #DEFINE QualityModeInvalid -1 
      #DEFINE QualityModeDefault 0 
      #DEFINE QualityModeLow  1 
      #DEFINE QualityModeHigh  2 

      #DEFINE CompositingModeSourceOver 0 
      #DEFINE CompositingModeSourceCopy 1
       
      #DEFINE CompositingQualityInvalid   -1 
      #DEFINE CompositingQualityDefault   0 
      #DEFINE CompositingQualityHighSpeed   1 
      #DEFINE CompositingQualityHighQuality  2 
      #DEFINE CompositingQualityGammaCorrected 3 
      #DEFINE CompositingQualityAssumeLinear  4 

      #DEFINE UnitWorld  0 
      #DEFINE UnitDisplay  1 
      #DEFINE UnitPixel  2 
      #DEFINE UnitPoint  3 
      #DEFINE UnitInch  4 
      #DEFINE UnitDocument 5 
      #DEFINE UnitMillimeter 6 

      #DEFINE MetafileFrameUnitPixel   2 
      #DEFINE MetafileFrameUnitPoint   3 
      #DEFINE MetafileFrameUnitInch   4 
      #DEFINE MetafileFrameUnitDocument  5 
      #DEFINE MetafileFrameUnitMillimeter  6 
      #DEFINE MetafileFrameUnitGdi   7 

      #DEFINE CoordinateSpaceWorld 0 
      #DEFINE CoordinateSpacePage  1 
      #DEFINE CoordinateSpaceDevice 2 

      #DEFINE WrapModeTile  0 
      #DEFINE WrapModeTileFlipX 1 
      #DEFINE WrapModeTileFlipy 2 
      #DEFINE WrapModeTileFlipXY 3 
      #DEFINE WrapModeClamp  4 

      #DEFINE HatchStyleHorizontal    0 
      #DEFINE HatchStyleVertical     1 
      #DEFINE HatchStyleForwardDiagonal   2 
      #DEFINE HatchStyleBackwardDiagonal   3 
      #DEFINE HatchStyleCross      4 
      #DEFINE HatchStyleDiagonalCross    5 
      #DEFINE HatchStyle05Percent     6 
      #DEFINE HatchStyle10Percent     7 
      #DEFINE HatchStyle20Percent     8 
      #DEFINE HatchStyle25Percent     9 
      #DEFINE HatchStyle30Percent     10 
      #DEFINE HatchStyle40Percent     11 
      #DEFINE HatchStyle50Percent     12 
      #DEFINE HatchStyle60Percent     13 
      #DEFINE HatchStyle70Percent     14 
      #DEFINE HatchStyle75Percent     15 
      #DEFINE HatchStyle80Percent     16 
      #DEFINE HatchStyle90Percent     17 
      #DEFINE HatchStyleLightDownwardDiagonal  18 
      #DEFINE HatchStyleLightUpwardDiagonal  19 
      #DEFINE HatchStyleDarkDownwardDiagonal  20 
      #DEFINE HatchStyleDarkUpwardDiagonal  21 
      #DEFINE HatchStyleWideDownwardDiagonal  22 
      #DEFINE HatchStyleWideUpwardDiagonal  23 
      #DEFINE HatchStyleLightVertical    24 
      #DEFINE HatchStyleLightHorizontal   25 
      #DEFINE HatchStyleNarrowVertical   26 
      #DEFINE HatchStyleNarrowHorizontal   27 
      #DEFINE HatchStyleDarkVertical    28 
      #DEFINE HatchStyleDarkHorizontal   29 
      #DEFINE HatchStyleDashedDownwardDiagonal 30 
      #DEFINE HatchStyleDashedUpwardDiagonal  31 
      #DEFINE HatchStyleDashedHorizontal   32 
      #DEFINE HatchStyleDashedVertical   33 
      #DEFINE HatchStyleSmallConfetti    34 
      #DEFINE HatchStyleLargeConfetti    35 
      #DEFINE HatchStyleZigZag     36 
      #DEFINE HatchStyleWave      37 
      #DEFINE HatchStyleDiagonalBrick    38 
      #DEFINE HatchStyleHorizontalBrick   39 
      #DEFINE HatchStyleWeave      40 
      #DEFINE HatchStylePlaid      41 
      #DEFINE HatchStyleDivot      42 
      #DEFINE HatchStyleDottedGrid    43 
      #DEFINE HatchStyleDottedDiamond    44 
      #DEFINE HatchStyleShingle     45 
      #DEFINE HatchStyleTrellis     46 
      #DEFINE HatchStyleSphere     47 
      #DEFINE HatchStyleSmallGrid     48 
      #DEFINE HatchStyleSmallCheckerBoard   49 
      #DEFINE HatchStyleLargeCheckerBoard   50 
      #DEFINE HatchStyleOutlinedDiamond   51 
      #DEFINE HatchStyleSolidDiamond    52 
      #DEFINE HatchStyleTotal      53
       
      #DEFINE HatchStyleLargeGrid 4
      #DEFINE HatchStyleMin  0 
      #DEFINE HatchStyleMax  52

      #DEFINE DashStyleSolid   0 
      #DEFINE DashStyleDash   1 
      #DEFINE DashStyleDot   2 
      #DEFINE DashStyleDashDot  3 
      #DEFINE DashStyleDashDotDot  4 
      #DEFINE DashStyleCustom   5

      #DEFINE DashCapFlat   0 
      #DEFINE DashCapRound  2 
      #DEFINE DashCapTriangle  3 

      #DEFINE LineCapFlat    0 
      #DEFINE LineCapSquare   1 
      #DEFINE LineCapRound   2 
      #DEFINE LineCapTriangle   3 
      #DEFINE LineCapNoAnchor   16 
      #DEFINE LineCapSquareAnchor  17 
      #DEFINE LineCapRoundAnchor  18 
      #DEFINE LineCapDiamondAnchor 19 
      #DEFINE LineCapArrowAnchor  20 
      #DEFINE LineCapAnchorMask  240 
      #DEFINE LineCapCustom   255 

      #DEFINE CustomLineCapTypeDefault   0 
      #DEFINE CustomLineCapTypeAdjustableArrow 1 

      #DEFINE LineJoinMiter   0 
      #DEFINE LineJoinBevel   1 
      #DEFINE LineJoinRound   2 
      #DEFINE LineJoinMiterClipped 3 

      #DEFINE PathPointTypeStart   0 
      #DEFINE PathPointTypeLine   1 
      #DEFINE PathPointTypeBezier   3 
      #DEFINE PathPointTypeBezier3  3 
      #DEFINE PathPointTypePathTypeMask 7 
      #DEFINE PathPointTypeDashMode  16 
      #DEFINE PathPointTypePathMarker  32 
      #DEFINE PathPointTypeCloseSubpath 128 

      #DEFINE WarpModePerspective 0 
      #DEFINE WarpModeBilinear 1 

      #DEFINE LinearGradientModeHorizontal  0 
      #DEFINE LinearGradientModeVertical   1 
      #DEFINE LinearGradientModeForwardDiagonal 2 
      #DEFINE LinearGradientModeBackwardDiagonal 3 

      #DEFINE CombineModeReplace  0 
      #DEFINE CombineModeIntersect 1 
      #DEFINE CombineModeUnion  2 
      #DEFINE CombineModeXor   3 
      #DEFINE CombineModeExclude  4 
      #DEFINE CombineModeComplement 5 

      #DEFINE ImageTypeUnknown 0 
      #DEFINE ImageTypeBitmap  1 
      #DEFINE ImageTypeMetafile 2 

      #DEFINE InterpolationModeInvalid    -1 
      #DEFINE InterpolationModeDefault    0 
      #DEFINE InterpolationModeLowQuality    1 
      #DEFINE InterpolationModeHighQuality   2 
      #DEFINE InterpolationModeBilinear    3 
      #DEFINE InterpolationModeBicubic    4 
      #DEFINE InterpolationModeNearestNeighbor  5 
      #DEFINE InterpolationModeHighQualityBilinear 6 
      #DEFINE InterpolationModeHighQualityBicubic  7 

      #DEFINE PenAlignmentCenter 0 
      #DEFINE PenAlignmentInset 1 

      #DEFINE BrushTypeSolidColor  0 
      #DEFINE BrushTypeHatchFill  1 
      #DEFINE BrushTypeTextureFill 2 
      #DEFINE BrushTypePathGradient 3 
      #DEFINE BrushTypeLinearGradient 4 

      #DEFINE PenTypeSolidColor  0 
      #DEFINE PenTypeHatchFill  1 
      #DEFINE PenTypeTextureFill  2 
      #DEFINE PenTypePathGradient  3 
      #DEFINE PenTypeLinearGradient 4 
      #DEFINE PenTypeUnknown   -1 

      #DEFINE MatrixOrderPrepend 0 
      #DEFINE MatrixOrderAppend 1 

      #DEFINE GenericFontFamilySerif  0 
      #DEFINE GenericFontFamilySansSerif 1 
      #DEFINE GenericFontFamilyMonospace 2 

      #DEFINE FontStyleRegular 0 
      #DEFINE FontStyleBold  1 
      #DEFINE FontStyleItalic  2 
      #DEFINE FontStyleBoldItalic 3 
      #DEFINE FontStyleUnderline 4 
      #DEFINE FontStyleStrikeout 8 

      #DEFINE SmoothingModeInvalid  -1 
      #DEFINE SmoothingModeDefault  0 
      #DEFINE SmoothingModeHighSpeed  1 
      #DEFINE SmoothingModeHighQuality 2 
      #DEFINE SmoothingModeNone   3 
      #DEFINE SmoothingModeAntiAlias  4 

      #DEFINE PixelOffsetModeInvalid  -1 
      #DEFINE PixelOffsetModeDefault  0 
      #DEFINE PixelOffsetModeHighSpeed 1 
      #DEFINE PixelOffsetModeHighQuality 2 
      #DEFINE PixelOffsetModeNone   3 
      #DEFINE PixelOffsetModeHalf   4 

      #DEFINE TextRenderingHintSystemDefault    0 
      #DEFINE TextRenderingHintSingleBitPerPixelGridFit 1 
      #DEFINE TextRenderingHintAntiAliasGridFit   3 
      #DEFINE TextRenderingHintClearTypeGridFit   5 

      #DEFINE MetafileTypeInvalid   0 
      #DEFINE MetafileTypeWmf    1 
      #DEFINE MetafileTypeWmfPlaceable 2 
      #DEFINE MetafileTypeEmf    3 
      #DEFINE MetafileTypeEmfPlusOnly  4 
      #DEFINE MetafileTypeEmfPlusDual  5 

      #DEFINE EmfTypeEmfOnly  3 
      #DEFINE EmfTypeEmfPlusOnly 4 
      #DEFINE EmfTypeEmfPlusDual 5 

      #DEFINE ObjectTypeInvalid   0 
      #DEFINE ObjectTypeBrush    1 
      #DEFINE ObjectTypePen    2 
      #DEFINE ObjectTypePath    3 
      #DEFINE ObjectTypeRegion   4 
      #DEFINE ObjectTypeImage    5 
      #DEFINE ObjectTypeFont    6 
      #DEFINE ObjectTypeStringFormat  7 
      #DEFINE ObjectTypeImageAttributes 8 
      #DEFINE ObjectTypeCustomLineCap  9 

      #DEFINE ObjectTypeMax 9 
      #DEFINE ObjectTypeMin 1 

      #DEFINE StringFormatFlagsDirectionRightToLeft 1 
      #DEFINE StringFormatFlagsDirectionVertical  2 
      #DEFINE StringFormatFlagsNoFitBlackBox   4 
      #DEFINE StringFormatFlagsDisplayFormatControl 32 
      #DEFINE StringFormatFlagsNoFontFallback   1024 
      #DEFINE StringFormatFlagsMeasureTrailingSpaces 2048 
      #DEFINE StringFormatFlagsNoWrap     4096 
      #DEFINE StringFormatFlagsLineLimit    8192 
      #DEFINE StringFormatFlagsNoClip     16384 

      #DEFINE StringTrimmingNone    0 
      #DEFINE StringTrimmingCharacter   1 
      #DEFINE StringTrimmingWord    2 
      #DEFINE StringTrimmingEllipsisCharacter 3 
      #DEFINE StringTrimmingEllipsisWord  4 
      #DEFINE StringTrimmingEllipsisPath  5 

      #DEFINE StringDigitSubstituteUser   0 
      #DEFINE StringDigitSubstituteNone   1 
      #DEFINE StringDigitSubstituteNational  2 
      #DEFINE StringDigitSubstituteTraditional 3 

      #DEFINE HotkeyPrefixNone 0 
      #DEFINE HotkeyPrefixShow 1 
      #DEFINE HotkeyPrefixHide 2 

      #DEFINE StringAlignmentNear 0 
      #DEFINE StringAlignmentCenter 1 
      #DEFINE StringAlignmentFar  2 

      #DEFINE DriverStringOptionsCmapLookup   1 
      #DEFINE DriverStringOptionsVertical    2 
      #DEFINE DriverStringOptionsRealizedAdvance  4 
      #DEFINE DriverStringOptionsLimitSubpixel  8 

      #DEFINE FlushIntentionFlush 0 
      #DEFINE FlushIntentionSync 1 

      #DEFINE EncoderParameterValueTypeByte   1 
      #DEFINE EncoderParameterValueTypeASCII   2 
      #DEFINE EncoderParameterValueTypeShort   3 
      #DEFINE EncoderParameterValueTypeLong   4 
      #DEFINE EncoderParameterValueTypeRational  5 
      #DEFINE EncoderParameterValueTypeLongRange  6 
      #DEFINE EncoderParameterValueTypeUndefined  7 
      #DEFINE EncoderParameterValueTypeRationalRange 8 

      #DEFINE EncoderValueColorTypeCMYK    0 
      #DEFINE EncoderValueColorTypeYCCK    1 
      #DEFINE EncoderValueCompressionLZW    2 
      #DEFINE EncoderValueCompressionCCITT3   3 
      #DEFINE EncoderValueCompressionCCITT4   4 
      #DEFINE EncoderValueCompressionRle    5 
      #DEFINE EncoderValueCompressionNone    6 
      #DEFINE EncoderValueScanMethodInterlaced  7 
      #DEFINE EncoderValueScanMethodNonInterlaced  8 
      #DEFINE EncoderValueVersionGif87    9 
      #DEFINE EncoderValueVersionGif89    10 
      #DEFINE EncoderValueRenderProgressive   11 
      #DEFINE EncoderValueRenderNonProgressive  12 
      #DEFINE EncoderValueTransformRotate90   13 
      #DEFINE EncoderValueTransformRotate180   14 
      #DEFINE EncoderValueTransformRotate270   15 
      #DEFINE EncoderValueTransformFlipHorizontal  16 
      #DEFINE EncoderValueTransformFlipVertical  17 
      #DEFINE EncoderValueMultiFrame     18 
      #DEFINE EncoderValueLastFrame     19 
      #DEFINE EncoderValueFlush      20 
      #DEFINE EncoderValueFrameDimensionTime   21 
      #DEFINE EncoderValueFrameDimensionResolution 22 
      #DEFINE EncoderValueFrameDimensionPage   23 

      #DEFINE EmfToWmfBitsFlagsDefault   0 
      #DEFINE EmfToWmfBitsFlagsEmbedEmf   1 
      #DEFINE EmfToWmfBitsFlagsIncludePlaceable 2 
      #DEFINE EmfToWmfBitsFlagsNoXORClip   4 

      #DEFINE WmfRecordTypeSetBkColor    66049 
      #DEFINE WmfRecordTypeSetBkMode    65794 
      #DEFINE WmfRecordTypeSetMapMode    5795 
      #DEFINE WmfRecordTypeSetROP2    65796 
      #DEFINE WmfRecordTypeSetRelAbs    65797 
      #DEFINE WmfRecordTypeSetPolyFillMode  65798 
      #DEFINE WmfRecordTypeSetStretchBltMode  65799 
      #DEFINE WmfRecordTypeSetTextCharExtra  65800 
      #DEFINE WmfRecordTypeSetTextColor   66057 
      #DEFINE WmfRecordTypeSetTextJustification 66058 
      #DEFINE WmfRecordTypeSetWindowOrg   66059 
      #DEFINE WmfRecordTypeSetWindowExt   66060 
      #DEFINE WmfRecordTypeSetViewportOrg   6061 
      #DEFINE WmfRecordTypeSetViewportExt   66062 
      #DEFINE WmfRecordTypeOffsetWindowOrg  66063 
      #DEFINE WmfRecordTypeScaleWindowExt   6576 
      #DEFINE WmfRecordTypeOffsetViewportOrg  6065 
      #DEFINE WmfRecordTypeScaleViewportExt  66578 
      #DEFINE WmfRecordTypeLineTo     66067 
      #DEFINE WmfRecordTypeMoveTo     6068 
      #DEFINE WmfRecordTypeExcludeClipRect  66581 
      #DEFINE WmfRecordTypeIntersectClipRect  66582 
      #DEFINE WmfRecordTypeArc     67607 
      #DEFINE WmfRecordTypeEllipse    66584 
      #DEFINE WmfRecordTypeFloodFill    66585 
      #DEFINE WmfRecordTypePie     67610 
      #DEFINE WmfRecordTypeRectangle    66587 
      #DEFINE WmfRecordTypeRoundRect    67100 
      #DEFINE WmfRecordTypePatBlt     67101 
      #DEFINE WmfRecordTypeSaveDC     5566 
      #DEFINE WmfRecordTypeSetPixel    66591 
      #DEFINE WmfRecordTypeOffsetClipRgn   66080 
      #DEFINE WmfRecordTypeTextOut    66849 
      #DEFINE WmfRecordTypeBitBlt     67874 
      #DEFINE WmfRecordTypeStretchBlt    68387 
      #DEFINE WmfRecordTypePolygon    66340 
      #DEFINE WmfRecordTypePolyline    66341 
      #DEFINE WmfRecordTypeEscape     67110 
      #DEFINE WmfRecordTypeRestoreDC    65831 
      #DEFINE WmfRecordTypeFillRegion    66088 
      #DEFINE WmfRecordTypeFrameRegion   66601 
      #DEFINE WmfRecordTypeInvertRegion   65834 
      #DEFINE WmfRecordTypePaintRegion   65835 
      #DEFINE WmfRecordTypeSelectClipRegion  65836 
      #DEFINE WmfRecordTypeSelectObject   65837 
      #DEFINE WmfRecordTypeSetTextAlign   65838 
      #DEFINE WmfRecordTypeDrawText    67119 
      #DEFINE WmfRecordTypeChord     67632 
      #DEFINE WmfRecordTypeSetMapperFlags   6097 
      #DEFINE WmfRecordTypeExtTextOut    68146 
      #DEFINE WmfRecordTypeSetDIBToDev   68915 
      #DEFINE WmfRecordTypeSelectPalette   66100 
      #DEFINE WmfRecordTypeRealizePalette   65589 
      #DEFINE WmfRecordTypeAnimatePalette   66614 
      #DEFINE WmfRecordTypeSetPalEntries   65591 
      #DEFINE WmfRecordTypePolyPolygon   66872 
      #DEFINE WmfRecordTypeResizePalette   65849 
      #DEFINE WmfRecordTypeDIBBitBlt    67904 
      #DEFINE WmfRecordTypeDIBStretchBlt   68417 
      #DEFINE WmfRecordTypeDIBCreatePatternBrush 65858 
      #DEFINE WmfRecordTypeStretchDIB    69443 
      #DEFINE WmfRecordTypeExtFloodFill   66888 
      #DEFINE WmfRecordTypeSetLayout    65865 
      #DEFINE WmfRecordTypeResetDC    65868 
      #DEFINE WmfRecordTypeStartDoc    65869 
      #DEFINE WmfRecordTypeStartPage    65615 
      #DEFINE WmfRecordTypeEndPage    65616 
      #DEFINE WmfRecordTypeAbortDoc    65618 
      #DEFINE WmfRecordTypeEndDoc     65630 
      #DEFINE WmfRecordTypeDeleteObject   66032 
      #DEFINE WmfRecordTypeCreatePalette   65783 
      #DEFINE WmfRecordTypeCreateBrush   65784 
      #DEFINE WmfRecordTypeCreatePatternBrush  66041 
      #DEFINE WmfRecordTypeCreatePenIndirect  66298 
      #DEFINE WmfRecordTypeCreateFontIndirect  66299 
      #DEFINE WmfRecordTypeCreateBrushIndirect 66300 
      #DEFINE WmfRecordTypeCreateBitmapIndirect 66301 
      #DEFINE WmfRecordTypeCreateRegion   67327 

      #DEFINE EmfRecordTypeHeader       1 
      #DEFINE EmfRecordTypePolyBezier      2 
      #DEFINE EmfRecordTypePolygon      3 
      #DEFINE EmfRecordTypePolyline      4 
      #DEFINE EmfRecordTypePolyBezierTo     5 
      #DEFINE EmfRecordTypePolyLineTo      6 
      #DEFINE EmfRecordTypePolyPolyline     7 
      #DEFINE EmfRecordTypePolyPolygon     8 
      #DEFINE EmfRecordTypeSetWindowExtEx     9 
      #DEFINE EmfRecordTypeSetWindowOrgEx     10 
      #DEFINE EmfRecordTypeSetViewportExtEx    11 
      #DEFINE EmfRecordTypeSetViewportOrgEx    12 
      #DEFINE EmfRecordTypeSetBrushOrgEx     13 
      #DEFINE EmfRecordTypeEOF       14 
      #DEFINE EmfRecordTypeSetPixelV      15 
      #DEFINE EmfRecordTypeSetMapperFlags     16 
      #DEFINE EmfRecordTypeSetMapMode      17 
      #DEFINE EmfRecordTypeSetBkMode      18 
      #DEFINE EmfRecordTypeSetPolyFillMode    19 
      #DEFINE EmfRecordTypeSetROP2      20 
      #DEFINE EmfRecordTypeSetStretchBltMode    21 
      #DEFINE EmfRecordTypeSetTextAlign     22 
      #DEFINE EmfRecordTypeSetColorAdjustment    23 
      #DEFINE EmfRecordTypeSetTextColor     24 
      #DEFINE EmfRecordTypeSetBkColor      25 
      #DEFINE EmfRecordTypeOffsetClipRgn     26 
      #DEFINE EmfRecordTypeMoveToEx      27 
      #DEFINE EmfRecordTypeSetMetaRgn      28 
      #DEFINE EmfRecordTypeExcludeClipRect    29 
      #DEFINE EmfRecordTypeIntersectClipRect    30 
      #DEFINE EmfRecordTypeScaleViewportExtEx    31 
      #DEFINE EmfRecordTypeScaleWindowExtEx    32 
      #DEFINE EmfRecordTypeSaveDC       33 
      #DEFINE EmfRecordTypeRestoreDC      34 
      #DEFINE EmfRecordTypeSetWorldTransform    35 
      #DEFINE EmfRecordTypeModifyWorldTransform   36 
      #DEFINE EmfRecordTypeSelectObject     37 
      #DEFINE EmfRecordTypeCreatePen      38 
      #DEFINE EmfRecordTypeCreateBrushIndirect   39 
      #DEFINE EmfRecordTypeDeleteObject     40 
      #DEFINE EmfRecordTypeAngleArc      41 
      #DEFINE EmfRecordTypeEllipse      42 
      #DEFINE EmfRecordTypeRectangle      43 
      #DEFINE EmfRecordTypeRoundRect      44 
      #DEFINE EmfRecordTypeArc       45 
      #DEFINE EmfRecordTypeChord       46 
      #DEFINE EmfRecordTypePie       47 
      #DEFINE EmfRecordTypeSelectPalette     48 
      #DEFINE EmfRecordTypeCreatePalette     49 
      #DEFINE EmfRecordTypeSetPaletteEntries    50 
      #DEFINE EmfRecordTypeResizePalette     51 
      #DEFINE EmfRecordTypeRealizePalette     52 
      #DEFINE EmfRecordTypeExtFloodFill     53 
      #DEFINE EmfRecordTypeLineTo       54 
      #DEFINE EmfRecordTypeArcTo       55 
      #DEFINE EmfRecordTypePolyDraw      56 
      #DEFINE EmfRecordTypeSetArcDirection    57 
      #DEFINE EmfRecordTypeSetMiterLimit     58 
      #DEFINE EmfRecordTypeBeginPath      59 
      #DEFINE EmfRecordTypeEndPath      60 
      #DEFINE EmfRecordTypeCloseFigure     61 
      #DEFINE EmfRecordTypeFillPath      62 
      #DEFINE EmfRecordTypeStrokeAndFillPath    63 
      #DEFINE EmfRecordTypeStrokePath      64 
      #DEFINE EmfRecordTypeFlattenPath     65 
      #DEFINE EmfRecordTypeWidenPath      66 
      #DEFINE EmfRecordTypeSelectClipPath     67 
      #DEFINE EmfRecordTypeAbortPath      68 
      #DEFINE EmfRecordTypeReserved_069     69 
      #DEFINE EmfRecordTypeGdiComment      70 
      #DEFINE EmfRecordTypeFillRgn      71 
      #DEFINE EmfRecordTypeFrameRgn      72 
      #DEFINE EmfRecordTypeInvertRgn      73 
      #DEFINE EmfRecordTypePaintRgn      74 
      #DEFINE EmfRecordTypeExtSelectClipRgn    75 
      #DEFINE EmfRecordTypeBitBlt       76 
      #DEFINE EmfRecordTypeStretchBlt      77 
      #DEFINE EmfRecordTypeMaskBlt      78 
      #DEFINE EmfRecordTypePlgBlt       79 
      #DEFINE EmfRecordTypeSetDIBitsToDevice    80 
      #DEFINE EmfRecordTypeStretchDIBits     81 
      #DEFINE EmfRecordTypeExtCreateFontIndirect   82 
      #DEFINE EmfRecordTypeExtTextOutA     83 
      #DEFINE EmfRecordTypeExtTextOutW     84 
      #DEFINE EmfRecordTypePolyBezier16     85 
      #DEFINE EmfRecordTypePolygon16      86 
      #DEFINE EmfRecordTypePolyline16      87 
      #DEFINE EmfRecordTypePolyBezierTo16     88 
      #DEFINE EmfRecordTypePolylineTo16     89 
      #DEFINE EmfRecordTypePolyPolyline16     90 
      #DEFINE EmfRecordTypePolyPolygon16     91 
      #DEFINE EmfRecordTypePolyDraw16      92 
      #DEFINE EmfRecordTypeCreateMonoBrush    93 
      #DEFINE EmfRecordTypeCreateDIBPatternBrushPt  94 
      #DEFINE EmfRecordTypeExtCreatePen     95 
      #DEFINE EmfRecordTypePolyTextOutA     96 
      #DEFINE EmfRecordTypePolyTextOutW     97 
      #DEFINE EmfRecordTypeSetICMMode      98 
      #DEFINE EmfRecordTypeCreateColorSpace    99 
      #DEFINE EmfRecordTypeSetColorSpace     100 
      #DEFINE EmfRecordTypeDeleteColorSpace    101 
      #DEFINE EmfRecordTypeGLSRecord      102 
      #DEFINE EmfRecordTypeGLSBoundedRecord    103 
      #DEFINE EmfRecordTypePixelFormat     104 
      #DEFINE EmfRecordTypeDrawEscape      105 
      #DEFINE EmfRecordTypeExtEscape      106 
      #DEFINE EmfRecordTypeStartDoc      107 
      #DEFINE EmfRecordTypeSmallTextOut     108 
      #DEFINE EmfRecordTypeForceUFIMapping    109 
      #DEFINE EmfRecordTypeNamedEscape     110 
      #DEFINE EmfRecordTypeColorCorrectPalette   111 
      #DEFINE EmfRecordTypeSetICMProfileA     112 
      #DEFINE EmfRecordTypeSetICMProfileW     113 
      #DEFINE EmfRecordTypeAlphaBlend      114 
      #DEFINE EmfRecordTypeSetLayout      115 
      #DEFINE EmfRecordTypeTransparentBlt     116 
      #DEFINE EmfRecordTypeReserved_117     117 
      #DEFINE EmfRecordTypeGradientFill     118 
      #DEFINE EmfRecordTypeSetLinkedUFIs     119 
      #DEFINE EmfRecordTypeSetTextJustification   120 
      #DEFINE EmfRecordTypeColorMatchToTargetW   121 
      #DEFINE EmfRecordTypeCreateColorSpaceW    122 
      #DEFINE EmfRecordTypeMax       122 
      #DEFINE EmfRecordTypeMin       1 
      #DEFINE EmfPlusRecordTypeInvalid     16384 
      #DEFINE EmfPlusRecordTypeHeader      16385 
      #DEFINE EmfPlusRecordTypeEndOfFile     16386 
      #DEFINE EmfPlusRecordTypeComment     16387 
      #DEFINE EmfPlusRecordTypeGetDC      16388 
      #DEFINE EmfPlusRecordTypeMultiFormatStart   16389 
      #DEFINE EmfPlusRecordTypeMultiFormatSection   16390 
      #DEFINE EmfPlusRecordTypeMultiFormatEnd    16391 
      #DEFINE EmfPlusRecordTypeObject      16392 
      #DEFINE EmfPlusRecordTypeClear      16393 
      #DEFINE EmfPlusRecordTypeFillRects     16394 
      #DEFINE EmfPlusRecordTypeDrawRects     16395 
      #DEFINE EmfPlusRecordTypeFillPolygon    16396 
      #DEFINE EmfPlusRecordTypeDrawLines     16397 
      #DEFINE EmfPlusRecordTypeFillEllipse    16398 
      #DEFINE EmfPlusRecordTypeDrawEllipse    16399 
      #DEFINE EmfPlusRecordTypeFillPie     16400 
      #DEFINE EmfPlusRecordTypeDrawPie     16401 
      #DEFINE EmfPlusRecordTypeDrawArc     16402 
      #DEFINE EmfPlusRecordTypeFillRegion     16403 
      #DEFINE EmfPlusRecordTypeFillPath     16404 
      #DEFINE EmfPlusRecordTypeDrawPath     16405 
      #DEFINE EmfPlusRecordTypeFillClosedCurve   16406 
      #DEFINE EmfPlusRecordTypeDrawClosedCurve   16407 
      #DEFINE EmfPlusRecordTypeDrawCurve     16408 
      #DEFINE EmfPlusRecordTypeDrawBeziers    16409 
      #DEFINE EmfPlusRecordTypeDrawImage     16410 
      #DEFINE EmfPlusRecordTypeDrawImagePoints   16411 
      #DEFINE EmfPlusRecordTypeDrawString     16412 
      #DEFINE EmfPlusRecordTypeSetRenderingOrigin   16413 
      #DEFINE EmfPlusRecordTypeSetAntiAliasMode   16414 
      #DEFINE EmfPlusRecordTypeSetTextRenderingHint  16415 
      #DEFINE EmfPlusRecordTypeSetTextContrast   16416 
      #DEFINE EmfPlusRecordTypeSetInterpolationMode  16417 
      #DEFINE EmfPlusRecordTypeSetPixelOffsetMode   16418 
      #DEFINE EmfPlusRecordTypeSetCompositingMode   16419 
      #DEFINE EmfPlusRecordTypeSetCompositingQuality  16420 
      #DEFINE EmfPlusRecordTypeSave      16421 
      #DEFINE EmfPlusRecordTypeRestore     16422 
      #DEFINE EmfPlusRecordTypeBeginContainer    16423 
      #DEFINE EmfPlusRecordTypeBeginContainerNoParams  16424 
      #DEFINE EmfPlusRecordTypeEndContainer    16425 
      #DEFINE EmfPlusRecordTypeSetWorldTransform   16426 
      #DEFINE EmfPlusRecordTypeResetWorldTransform  16427 
      #DEFINE EmfPlusRecordTypeMultiplyWorldTransform  16428 
      #DEFINE EmfPlusRecordTypeTranslateWorldTransform 16429 
      #DEFINE EmfPlusRecordTypeScaleWorldTransform  16430 
      #DEFINE EmfPlusRecordTypeRotateWorldTransform  16431 
      #DEFINE EmfPlusRecordTypeSetPageTransform   16432 
      #DEFINE EmfPlusRecordTypeResetClip     16433 
      #DEFINE EmfPlusRecordTypeSetClipRect    16434 
      #DEFINE EmfPlusRecordTypeSetClipPath    16435 
      #DEFINE EmfPlusRecordTypeSetClipRegion    16436 
      #DEFINE EmfPlusRecordTypeOffsetClip     16437 
      #DEFINE EmfPlusRecordTypeDrawDriverString   16438 
      #DEFINE EmfPlusRecordTotal       16439 
      #DEFINE EmfPlusRecordTypeMax      16438 
      #DEFINE EmfPlusRecordTypeMin      16385 

      #DEFINE ImageCodecFlagsEncoder   1 
      #DEFINE ImageCodecFlagsDecoder   2 
      #DEFINE ImageCodecFlagsSupportBitmap 4 
      #DEFINE ImageCodecFlagsSupportVector 8 
      #DEFINE ImageCodecFlagsSeekableEncode 16 
      #DEFINE ImageCodecFlagsBlockingDecode 32 
      #DEFINE ImageCodecFlagsBuiltin   65536 
      #DEFINE ImageCodecFlagsSystem   131072 
      #DEFINE ImageCodecFlagsUser    262144

      #DEFINE ImageLockModeRead   1 
      #DEFINE ImageLockModeWrite   2 
      #DEFINE ImageLockModeUserInputBuf 4
       
      #DEFINE ImageFlagsNone    0 
      #DEFINE ImageFlagsScalable   1 
      #DEFINE ImageFlagsHasAlpha   2 
      #DEFINE ImageFlagsHasTranslucent 4 
      #DEFINE ImageFlagsPartiallyScalable 8 
      #DEFINE ImageFlagsColorSpaceRGB  16 
      #DEFINE ImageFlagsColorSpaceCMYK 32 
      #DEFINE ImageFlagsColorSpaceGRAY 64 
      #DEFINE ImageFlagsColorSpaceYCBCR 128 
      #DEFINE ImageFlagsColorSpaceYCCK 256 
      #DEFINE ImageFlagsHasRealDPI  4096 
      #DEFINE ImageFlagsHasRealPixelSize 8192 
      #DEFINE ImageFlagsReadOnly   65536 
      #DEFINE ImageFlagsCaching   131072 

      #DEFINE RotateNoneFlipNone 0 
      #DEFINE Rotate90FlipNone 1 
      #DEFINE Rotate180FlipNone 2 
      #DEFINE Rotate270FlipNone 3 
      #DEFINE RotateNoneFlipX  4 
      #DEFINE Rotate90FlipX  5 
      #DEFINE Rotate180FlipX  6 
      #DEFINE Rotate270FlipX  7 

      #DEFINE Rotate180FlipXY  0 
      #DEFINE Rotate270FlipXY  1 
      #DEFINE RotateNoneFlipXY 2 
      #DEFINE Rotate90FlipXY  3 
      #DEFINE Rotate180FlipY  4 
      #DEFINE Rotate270FlipY  5 
      #DEFINE RotateNoneFlipY  6 
      #DEFINE Rotate90FlipY  7 

      #DEFINE PropertyTagTypeByte       1 
      #DEFINE PropertyTagTypeASCII      2 
      #DEFINE PropertyTagTypeShort      3 
      #DEFINE PropertyTagTypeLong       4 
      #DEFINE PropertyTagTypeRational      5 
      #DEFINE PropertyTagTypeUndefined     7 
      #DEFINE PropertyTagTypeSLONG      9 
      #DEFINE PropertyTagTypeSRational     10 
      #DEFINE PropertyTagExifIFD       34665 
      #DEFINE PropertyTagsIFD        34853 
      #DEFINE PropertyTagNewSubfileType     254 
      #DEFINE PropertyTagSubfileType      255 
      #DEFINE PropertyTagImageWidth      256 
      #DEFINE PropertyTagImageHeight      257 
      #DEFINE PropertyTagBitsPerSample     258 
      #DEFINE PropertyTagCompression      259 
      #DEFINE PropertyTagPhotometricInterp    262 
      #DEFINE PropertyTagThreshHolding     263 
      #DEFINE PropertyTagCellWidth      264 
      #DEFINE PropertyTagCellHeight      265 
      #DEFINE PropertyTagFillOrder      266 
      #DEFINE PropertyTagDocumentName      269 
      #DEFINE PropertyTagImageDescription     270 
      #DEFINE PropertyTagEquipMake      271 
      #DEFINE PropertyTagEquipModel      272 
      #DEFINE PropertyTagStripOffsets      273 
      #DEFINE PropertyTagOrientation      274 
      #DEFINE PropertyTagSamplesPerPixel     277 
      #DEFINE PropertyTagRowsPerStrip      278 
      #DEFINE PropertyTagStripBytesCount     279 
      #DEFINE PropertyTagMinSampleValue     280 
      #DEFINE PropertyTagMaxSampleValue     281 
      #DEFINE PropertyTagXResolution      282 
      #DEFINE PropertyTagYResolution      283 
      #DEFINE PropertyTagPlanarConfig      284 
      #DEFINE PropertyTagPageName       285 
      #DEFINE PropertyTagXPosition      286 
      #DEFINE PropertyTagYPosition      287 
      #DEFINE PropertyTagFreeOffset      288 
      #DEFINE PropertyTagFreeByteCounts     289 
      #DEFINE PropertyTagGrayResponseUnit     290 
      #DEFINE PropertyTagGrayResponseCurve    291 
      #DEFINE PropertyTagT4Option       292 
      #DEFINE PropertyTagT6Option       293 
      #DEFINE PropertyTagResolutionUnit     296 
      #DEFINE PropertyTagPageNumber      297 
      #DEFINE PropertyTagTransferFuncition    301 
      #DEFINE PropertyTagSoftwareUsed      305 
      #DEFINE PropertyTagDateTime       306 
      #DEFINE PropertyTagArtist       315 
      #DEFINE PropertyTagHostComputer      316 
      #DEFINE PropertyTagPredictor      317 
      #DEFINE PropertyTagWhitePoint      318 
      #DEFINE PropertyTagPrimaryChromaticities   319 
      #DEFINE PropertyTagColorMap       320 
      #DEFINE PropertyTagHalftoneHints     321 
      #DEFINE PropertyTagTileWidth      322 
      #DEFINE PropertyTagTileLength      323 
      #DEFINE PropertyTagTileOffset      324 
      #DEFINE PropertyTagTileByteCounts     325 
      #DEFINE PropertyTagInkSet       332 
      #DEFINE PropertyTagInkNames       333 
      #DEFINE PropertyTagNumberOfInks      334 
      #DEFINE PropertyTagDotRange&nbs

    • #3050190

      GDI+ and VFP

      by craigaaa3 ·

      In reply to The SPS Weblog

      I’m doing an extensive series for FoxTalk regarding GDI+ and
      VFP.  The first article will be in the August issue and I believe it will also
      be made available for free to the community.  It deals with the basics of drawing
      on a VFP form with GDI+, including an effective double-buffering technique. 
      It’s just the start, and once everyone is warmed up then the second article will blow
      doors off (guaranteed). I’ll be submitting the second article to David Stevenson sometime
      today.  Then I’ll begin working on the third article in the series.  By
      the time I’m done, there should be very little that is not known or accessible to
      VFP developers when it comes to GDI+.  This series of GDI+ articles and another
      one (different topic) I’m doing for FoxPro Advisor is the reason behind this
      blog entry (well sort of)…

      I’ve been somewhat quiet about GDI+ and VFP for the last couple months
      (out on the forums), because most of the stuff I would be able to post would come
      from the code I’m working on for the articles and that’s not allowed under most, if
      not all, publishing contracts.  It’s been really difficult for me to hold a bunch
      of stuff back like this.  I do like having the opportunity to have my stuff published,
      but it’s been a big change for me.  For years now, I’ve written cool code and
      been able to instantly thrust it into the public domain.  What I haven’t placed
      in the public domain has been making its way into my website
      http://www.vfpcode.com which
      should be ready for primetime by the end of this year (when I’ll open up the registration
      for the VFP Community – and yes, VFP Code will be free and stay that way).  Don’t
      get me wrong, I think it’s important to VFP’s visibility that quality articles are
      written for the industry rags, and I’m trying to do my part.  I’m just not use
      to the lag time between when I’ve figured something out to when I can let everyone
      know about it.

      I absolutely burn to give stuff away to the VFP Community and promote
      one of the greatest languages on earth.  It’s an itch that needs to be scratched
      and while my forum posts, and latest SPS Blog entries on VFP Email, have helped, it’s
      just not enough.  So, here are 603 GDI+ DECLARE statements that I’ve translated,
      and rest assured that I’ll be going through examples of how to use many of them in
      my FoxTalk series.

      DECLARE LONG GdiplusStartup IN GDIPLUS LONG @token,
      STRING @inputbuf, LONG outputbuf
      DECLARE LONG GdiplusShutdown IN GDIPLUS LONG token
      *!* Graphics
      DECLARE LONG GdipFlush IN GDIPLUS LONG graphics, LONG intention
      DECLARE LONG GdipCreateFromHDC IN GDIPLUS LONG hdc, LONG @graphics
      DECLARE LONG GdipCreateFromHWND IN GDIPLUS LONG hwnd, LONG @graphics
      DECLARE LONG GdipCreateFromHWNDICM IN GDIPLUS LONG hwnd, LONG @graphics
      DECLARE LONG GdipDeleteGraphics IN GDIPLUS LONG graphics
      DECLARE LONG GdipGetDC IN GDIPLUS LONG graphics, LONG @hdc
      DECLARE LONG GdipReleaseDC IN GDIPLUS LONG graphics, LONG hdc
      DECLARE LONG GdipSetCompositingMode IN GDIPLUS LONG graphics, LONG CompositingMd
      DECLARE LONG GdipGetCompositingMode IN GDIPLUS LONG graphics, LONG @CompositingMd
      DECLARE LONG GdipSetRenderingOrigin IN GDIPLUS LONG graphics, LONG x, LONG y
      DECLARE LONG GdipGetRenderingOrigin IN GDIPLUS LONG graphics, LONG @x, LONG @y
      DECLARE LONG GdipSetCompositingQuality IN GDIPLUS LONG graphics, LONG CompositingQlty
      DECLARE LONG GdipGetCompositingQuality IN GDIPLUS LONG graphics, LONG @CompositingQlty
      DECLARE LONG GdipSetSmoothingMode IN GDIPLUS LONG graphics, LONG SmoothingMd
      DECLARE LONG GdipGetSmoothingMode IN GDIPLUS LONG graphics, LONG @SmoothingMd
      DECLARE LONG GdipSetPixelOffsetMode IN GDIPLUS LONG graphics, LONG PixOffsetMode
      DECLARE LONG GdipGetPixelOffsetMode IN GDIPLUS LONG graphics, LONG @PixOffsetMode
      DECLARE LONG GdipSetTextRenderingHint IN GDIPLUS LONG graphics, LONG mode
      DECLARE LONG GdipGetTextRenderingHint IN GDIPLUS LONG graphics, LONG @mode
      DECLARE LONG GdipSetTextContrast IN GDIPLUS LONG graphics, LONG contrast
      DECLARE LONG GdipGetTextContrast IN GDIPLUS LONG graphics, LONG @contrast
      DECLARE LONG GdipSetInterpolationMode IN GDIPLUS LONG graphics, LONG interpolation
      DECLARE LONG GdipGetInterpolationMode IN GDIPLUS LONG graphics, LONG @interpolation
      DECLARE LONG GdipSetWorldTransform IN GDIPLUS LONG graphics, LONG matrix
      DECLARE LONG GdipResetWorldTransform IN GDIPLUS LONG graphics
      DECLARE LONG GdipMultiplyWorldTransform IN GDIPLUS LONG graphics, LONG matrix, LONG
      order
      DECLARE LONG GdipTranslateWorldTransform IN GDIPLUS LONG graphics, SINGLE dx, SINGLE
      dy, LONG order
      DECLARE LONG GdipScaleWorldTransform IN GDIPLUS LONG graphics, SINGLE sx, SINGLE sy,
      LONG order
      DECLARE LONG GdipRotateWorldTransform IN GDIPLUS LONG graphics, SINGLE angle, LONG
      order
      DECLARE LONG GdipGetWorldTransform IN GDIPLUS LONG graphics, LONG matrix
      DECLARE LONG GdipResetPageTransform IN GDIPLUS LONG graphics
      DECLARE LONG GdipGetPageUnit IN GDIPLUS LONG graphics, LONG @unit
      DECLARE LONG GdipGetPageScale IN GDIPLUS LONG graphics, SINGLE @sscale
      DECLARE LONG GdipSetPageUnit IN GDIPLUS LONG graphics, LONG unit
      DECLARE LONG GdipSetPageScale IN GDIPLUS LONG graphics, SINGLE sscale
      DECLARE LONG GdipGetDpiX IN GDIPLUS LONG graphics, SINGLE @dpi
      DECLARE LONG GdipGetDpiY IN GDIPLUS LONG graphics, SINGLE @dpi
      DECLARE LONG GdipTransformPoints IN GDIPLUS LONG graphics, LONG destSpace, LONG srcSpace,
      STRING @pPoint, LONG Count
      DECLARE LONG GdipTransformPointsI IN GDIPLUS LONG graphics, LONG destSpace, LONG srcSpace,
      STRING @pPoint, LONG Count
      DECLARE LONG GdipGetNearestColor IN GDIPLUS LONG graphics, LONG @argb
      DECLARE LONG GdipCreateHalftonePalette IN GDIPLUS
      DECLARE LONG GdipDrawLine IN GDIPLUS LONG graphics, LONG pen, SINGLE x1, SINGLE y1,
      SINGLE x2, SINGLE y2
      DECLARE LONG GdipDrawLineI IN GDIPLUS LONG graphics, LONG pen, LONG x1, LONG y1, LONG
      x2, LONG y2
      DECLARE LONG GdipDrawLines IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count
      DECLARE LONG GdipDrawLinesI IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count
      DECLARE LONG GdipDrawArc IN GDIPLUS LONG graphics, LONG pen, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipDrawArcI IN GDIPLUS LONG graphics, LONG pen, LONG x, LONG y, LONG
      nWidth, LONG Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipDrawBezier IN GDIPLUS LONG graphics, LONG pen, SINGLE x1, SINGLE
      y1, SINGLE x2, SINGLE y2, SINGLE x3, SINGLE y3, SINGLE x4, SINGLE y4
      DECLARE LONG GdipDrawBezierI IN GDIPLUS LONG graphics, LONG pen, LONG x1, LONG y1,
      LONG x2, LONG y2, LONG x3, LONG y3, LONG x4, LONG y4
      DECLARE GdipDrawBeziers IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG Count
      DECLARE LONG GdipDrawBeziersI IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipDrawRectangle IN GDIPLUS LONG graphics, LONG pen, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height
      DECLARE LONG GdipDrawRectangleI IN GDIPLUS LONG graphics, LONG pen, LONG x, LONG y,
      LONG nWidth, LONG Height
      DECLARE LONG GdipDrawRectangles IN GDIPLUS LONG graphics, LONG pen, STRING @rects,
      LONG Count
      DECLARE LONG GdipDrawRectanglesI IN GDIPLUS LONG graphics, LONG pen, STRING @rects,
      LONG Count
      DECLARE LONG GdipDrawEllipse IN GDIPLUS LONG graphics, LONG pen, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height
      DECLARE LONG GdipDrawEllipseI IN GDIPLUS LONG graphics, LONG pen, LONG x, LONG y,
      LONG nWidth, LONG Height
      DECLARE LONG GdipDrawPie IN GDIPLUS LONG graphics, LONG pen, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipDrawPieI IN GDIPLUS LONG graphics, LONG pen, LONG x, LONG y, LONG
      nWidth, LONG Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipDrawPolygon IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count
      DECLARE LONG GdipDrawPolygonI IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipDrawPath IN GDIPLUS LONG graphics, LONG pen, LONG path
      DECLARE LONG GdipDrawCurve IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count
      DECLARE LONG GdipDrawCurveI IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count
      DECLARE LONG GdipDrawCurve2 IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count, SINGLE tension
      DECLARE LONG GdipDrawCurve2I IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count, SINGLE tension
      DECLARE LONG GdipDrawCurve3 IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count, LONG offset, LONG numberOfSegments, SINGLE tension
      DECLARE LONG GdipDrawCurve3I IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint, LONG
      Count, LONG offset, LONG numberOfSegments, SINGLE tension
      DECLARE LONG GdipDrawClosedCurve IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipDrawClosedCurveI IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipDrawClosedCurve2 IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count, SINGLE tension
      DECLARE LONG GdipDrawClosedCurve2I IN GDIPLUS LONG graphics, LONG pen, STRING @pPoint,
      LONG Count, SINGLE tension
      DECLARE LONG GdipGraphicsClear IN GDIPLUS LONG graphics, LONG lColor
      DECLARE LONG GdipFillRectangle IN GDIPLUS LONG graphics, LONG brush, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height
      DECLARE LONG GdipFillRectangleI IN GDIPLUS LONG graphics, LONG brush, LONG x, LONG
      y, LONG nWidth, LONG Height
      DECLARE LONG GdipFillRectangles IN GDIPLUS LONG graphics, LONG brush, STRING @rects,
      LONG Count
      DECLARE LONG GdipFillRectanglesI IN GDIPLUS LONG graphics, LONG brush, STRING @rects,
      LONG Count
      DECLARE LONG GdipFillPolygon IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count, LONG FillMd
      DECLARE LONG GdipFillPolygonI IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count, LONG FillMd
      DECLARE LONG GdipFillPolygon2 IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipFillPolygon2I IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipFillEllipse IN GDIPLUS LONG graphics, LONG brush, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height
      DECLARE LONG GdipFillEllipseI IN GDIPLUS LONG graphics, LONG brush, LONG x, LONG y,
      LONG nWidth, LONG Height
      DECLARE LONG GdipFillPie IN GDIPLUS LONG graphics, LONG brush, SINGLE x, SINGLE y,
      SINGLE nWidth, SINGLE Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipFillPieI IN GDIPLUS LONG graphics, LONG brush, LONG x, LONG y, LONG
      nWidth, LONG Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipFillPath IN GDIPLUS LONG graphics, LONG brush, LONG path
      DECLARE LONG GdipFillClosedCurve IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipFillClosedCurveI IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count
      DECLARE LONG GdipFillClosedCurve2 IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count, SINGLE tension, LONG FillMd
      DECLARE LONG GdipFillClosedCurve2I IN GDIPLUS LONG graphics, LONG brush, STRING @pPoint,
      LONG Count, SINGLE tension, LONG FillMd
      DECLARE LONG GdipFillRegion IN GDIPLUS LONG graphics, LONG brush, LONG region
      DECLARE LONG GdipDrawImage IN GDIPLUS LONG graphics, LONG nImage, SINGLE x, SINGLE
      y
      DECLARE LONG GdipDrawImageI IN GDIPLUS LONG graphics, LONG nImage, LONG x, LONG y
      DECLARE LONG GdipDrawImageRect IN GDIPLUS LONG graphics, LONG nImage, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height
      DECLARE LONG GdipDrawImageRectI IN GDIPLUS LONG graphics, LONG nImage, LONG x, LONG
      y, LONG nWidth, LONG Height
      DECLARE LONG GdipDrawImagePoints IN GDIPLUS LONG graphics, LONG nImage, STRING @dstpoints,
      LONG Count
      DECLARE LONG GdipDrawImagePointsI IN GDIPLUS LONG graphics, LONG nImage, STRING @dstpoints,
      LONG Count
      DECLARE LONG GdipDrawImagePointRect IN GDIPLUS LONG graphics, LONG nImage, SINGLE
      x, SINGLE y, SINGLE srcx, SINGLE srcy, SINGLE srcwidth, SINGLE srcheight, LONG srcUnit
      DECLARE LONG GdipDrawImagePointRectI IN GDIPLUS LONG graphics, LONG nImage, LONG x,
      LONG y, LONG srcx, LONG srcy, LONG srcwidth, LONG srcheight, LONG srcUnit
      DECLARE LONG GdipDrawImageRectRect IN GDIPLUS LONG graphics, LONG nImage, SINGLE dstx,
      SINGLE dsty, LONG dstwidth, SINGLE dstheight, SINGLE srcx, SINGLE srcy, SINGLE srcwidth,
      SINGLE srcheight, LONG srcUnit, LONG imageAttributes, LONG pCALLBACK, LONG callbackData
      DECLARE LONG GdipDrawImageRectRectI IN GDIPLUS LONG graphics, LONG nImage, LONG dstx,
      LONG dsty, LONG dstwidth, LONG dstheight, LONG srcx, LONG srcy, LONG srcwidth, LONG
      srcheight, LONG srcUnit, LONG imageAttributes, LONG pCALLBACK, LONG callbackData
      DECLARE LONG GdipDrawImagePointsRect IN GDIPLUS LONG graphics, LONG nImage, STRING
      @pPoint, LONG Count, SINGLE srcx, SINGLE srcy, SINGLE srcwidth, SINGLE srcheight,
      LONG srcUnit, LONG imageAttributes, LONG pCALLBACK, LONG callbackData
      DECLARE LONG GdipDrawImagePointsRectI IN GDIPLUS LONG graphics, LONG nImage, STRING
      @pPoint, LONG Count, LONG srcx, LONG srcy, LONG srcwidth, LONG srcheight, LONG srcUnit,
      LONG imageAttributes, LONG pCALLBACK, LONG callbackData
      DECLARE LONG GdipEnumerateMetafileDestPoint IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destPoint, LONG @lpEnumerateMetafileProc, LONG callbackData, LONG @imageAttributes
      DECLARE LONG GdipEnumerateMetafileDestPointI IN GDIPLUS LONG @graphics, LONG metafile,
      STRING @destPoint, LONG lpEnumerateMetafileProc, LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileDestRect IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destRect, LONG @lpEnumerateMetafileProc, LONG callbackData, LONG @imageAttributes
      DECLARE LONG GdipEnumerateMetafileDestRectI IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destRect, LONG @lpEnumerateMetafileProc, LONG callbackData, LONG @imageAttributes
      DECLARE LONG GdipEnumerateMetafileDestPoints IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destPoint, LONG Count, LONG @lpEnumerateMetafileProc, LONG callbackData, LONG
      @imageAttributes
      DECLARE LONG GdipEnumerateMetafileDestPointsI IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destPoint, LONG Count, LONG @lpEnumerateMetafileProc, LONG callbackData, LONG
      @imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestPoint IN GDIPLUS LONG graphics, LONG
      metafile, STRING @destPoint, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc,
      LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestPointI IN GDIPLUS LONG graphics, LONG
      metafile, STRING @destPoint, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc,
      LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestRect IN GDIPLUS LONG graphics, LONG metafile,
      STRING @destRect, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc, LONG
      callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestRectI IN GDIPLUS LONG graphics, LONG
      metafile, STRING @destRect, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc,
      LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestPoints IN GDIPLUS LONG graphics, LONG
      metafile, STRING @destPoints, LONG Count, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc,
      LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipEnumerateMetafileSrcRectDestPointsI IN GDIPLUS LONG graphics, LONG
      metafile, STRING @destPoints, LONG Count, STRING @srcRect, LONG srcUnit, LONG lpEnumerateMetafileProc,
      LONG callbackData, LONG imageAttributes
      DECLARE LONG GdipPlayMetafileRecord IN GDIPLUS LONG metafile, STRING recordType, LONG
      flags, LONG dataSize, STRING @byteData
      DECLARE LONG GdipSetClipGraphics IN GDIPLUS LONG graphics, LONG srcgraphics, LONG
      CombineMd
      DECLARE LONG GdipSetClipRect IN GDIPLUS LONG graphics, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height, LONG CombineMd
      DECLARE LONG GdipSetClipRectI IN GDIPLUS LONG graphics, LONG x, LONG y, LONG nWidth,
      LONG Height, LONG CombineMd
      DECLARE LONG GdipSetClipPath IN GDIPLUS LONG graphics, LONG path, LONG CombineMd
      DECLARE LONG GdipSetClipRegion IN GDIPLUS LONG graphics, LONG region, LONG CombineMd
      DECLARE LONG GdipSetClipHrgn IN GDIPLUS LONG graphics, LONG hRgn, LONG CombineMd
      DECLARE LONG GdipResetClip IN GDIPLUS LONG graphics
      DECLARE LONG GdipTranslateClip IN GDIPLUS LONG graphics, SINGLE dx, SINGLE dy
      DECLARE LONG GdipTranslateClipI IN GDIPLUS LONG graphics, LONG dx, LONG dy
      DECLARE LONG GdipGetClip IN GDIPLUS LONG graphics, LONG region
      DECLARE LONG GdipGetClipBounds IN GDIPLUS LONG graphics, STRING @nRect
      DECLARE LONG GdipGetClipBoundsI IN GDIPLUS LONG graphics, STRING @nRect
      DECLARE LONG GdipIsClipEmpty IN GDIPLUS LONG graphics, LONG @result
      DECLARE LONG GdipGetVisibleClipBounds IN GDIPLUS LONG graphics, STRING @nRect
      DECLARE LONG GdipGetVisibleClipBoundsI IN GDIPLUS LONG graphics, STRING @nRect
      DECLARE LONG GdipIsVisibleClipEmpty IN GDIPLUS LONG graphics, LONG @result
      DECLARE LONG GdipIsVisiblePoint IN GDIPLUS LONG graphics, SINGLE x, SINGLE y, LONG
      @result
      DECLARE LONG GdipIsVisiblePointI IN GDIPLUS LONG graphics, LONG x, LONG y, LONG @result
      DECLARE LONG GdipIsVisibleRect IN GDIPLUS LONG graphics, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height, LONG @result
      DECLARE LONG GdipIsVisibleRectI IN GDIPLUS LONG graphics, LONG x, LONG y, LONG nWidth,
      LONG Height, LONG @result
      DECLARE LONG GdipSaveGraphics IN GDIPLUS LONG graphics, LONG @STATE
      DECLARE LONG GdipRestoreGraphics IN GDIPLUS LONG graphics, LONG STATE
      DECLARE LONG GdipBeginContainer IN GDIPLUS LONG graphics, STRING @dstrect, STRING
      @srcRect, LONG unit, LONG @STATE
      DECLARE LONG GdipBeginContainerI IN GDIPLUS LONG graphics, STRING @dstrect, STRING
      @srcRect, LONG unit, LONG @STATE
      DECLARE LONG GdipBeginContainer2 IN GDIPLUS LONG graphics, LONG @STATE
      DECLARE LONG GdipEndContainer IN GDIPLUS LONG graphics, LONG STATE
      DECLARE LONG GdipGetMetafileHeaderFromWmf IN GDIPLUS LONG hWmf, STRING @WmfPlaceableFileHdr,
      STRING @header
      DECLARE LONG GdipGetMetafileHeaderFromEmf IN GDIPLUS LONG hEmf, STRING @header
      DECLARE LONG GdipGetMetafileHeaderFromFile IN GDIPLUS STRING FilName, STRING @header
      DECLARE LONG GdipGetMetafileHeaderFromStream IN GDIPLUS INTEGER stream, STRING @header
      DECLARE LONG GdipGetMetafileHeaderFromMetafile IN GDIPLUS LONG metafile, STRING @header
      DECLARE LONG GdipGetHemfFromMetafile IN GDIPLUS LONG metafile, LONG @hEmf
      DECLARE LONG GdipCreateStreamOnFile IN GDIPLUS STRING FilName, LONG access, INTEGER
      @stream
      DECLARE LONG GdipCreateMetafileFromWmf IN GDIPLUS LONG hWmf, LONG bDeleteWmf, STRING
      @WmfPlaceableFileHdr, LONG metafile
      DECLARE LONG GdipCreateMetafileFromEmf IN GDIPLUS LONG hEmf, LONG bDeleteEmf, LONG
      @metafile
      DECLARE LONG GdipCreateMetafileFromFile IN GDIPLUS STRING @byvalfile, LONG @metafile
      DECLARE LONG GdipCreateMetafileFromWmfFile IN GDIPLUS STRING file, STRING @WmfPlaceableFileHdr,
      LONG @metafile
      DECLARE LONG GdipCreateMetafileFromStream IN GDIPLUS INTEGER stream, Long @metafile
      DECLARE LONG GdipRecordMetafile IN GDIPLUS LONG referenceHdc, LONG @etype, STRING
      @frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipRecordMetafileI IN GDIPLUS LONG referenceHdc, LONG @etype, STRING
      @frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipRecordMetafileFileName IN GDIPLUS STRING FilName, LONG referenceHdc,
      LONG @etype, STRING @frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipRecordMetafileFileNameI IN GDIPLUS STRING FilName, LONG referenceHdc,
      LONG @etype, STRING @frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipRecordMetafileFileStream IN GDIPLUS INTEGER stream, LONG referenceHdc,
      LONG @etype, STRING frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipRecordMetafileFileStreamI IN GDIPLUS INTEGER stream, LONG referenceHdc,
      LONG @etype, STRING @frameRect, LONG frameUnit, STRING description, LONG @metafile
      DECLARE LONG GdipSetMetafileDownLevelRasterizationLimit IN GDIPLUS LONG metafile,
      LONG metafileRasterizationLimitDpi
      DECLARE LONG GdipGetMetafileDownLevelRasterizationLimit IN GDIPLUS LONG metafile,
      LONG @metafileRasterizationLimitDpi
      DECLARE LONG GdipGetImageDecodersSize IN GDIPLUS LONG @numDecoders, LONG @SIZE
      DECLARE LONG GdipGetImageDecoders IN GDIPLUS LONG numDecoders, LONG SIZE, STRING @decoders
      DECLARE LONG GdipGetImageEncodersSize IN GDIPLUS LONG @numEncoders, LONG @SIZE
      DECLARE LONG GdipGetImageEncoders IN GDIPLUS LONG numEncoders, LONG SIZE, STRING @encoders
      DECLARE LONG GdipComment IN GDIPLUS LONG graphics, LONG sizeData, STRING @nData
      *!* Image
      DECLARE LONG GdipLoadImageFromFile IN GDIPLUS STRING FilName, LONG @nImage
      DECLARE LONG GdipLoadImageFromFileICM IN GDIPLUS STRING FilName, LONG @nImage
      DECLARE LONG GdipLoadImageFromStream IN GDIPLUS INTEGER stream, LONG @nImage
      DECLARE LONG GdipLoadImageFromStreamICM IN GDIPLUS INTEGER stream, LONG @nImage
      DECLARE LONG GdipDisposeImage IN GDIPLUS LONG nImage
      DECLARE LONG GdipSaveImageToFile IN GDIPLUS LONG nImage, STRING FilName, STRING @clsidEncoder,
      STRING @encoderParams
      DECLARE LONG GdipSaveImageToStream IN GDIPLUS LONG nImage, INTEGER stream, STRING
      @clsidEncoder, STRING @encoderParams
      DECLARE LONG GdipSaveAdd IN GDIPLUS LONG nImage, LONG @encoderParams
      DECLARE LONG GdipSaveAddImage IN GDIPLUS LONG nImage, LONG newnImage, LONG @encoderParams
      DECLARE LONG GdipGetImageGraphicsContext IN GDIPLUS LONG nImage, LONG @graphics
      DECLARE LONG GdipGetImageBounds IN GDIPLUS LONG nImage, STRING @srcRect, LONG @srcUnit
      DECLARE LONG GdipGetImageDimension IN GDIPLUS LONG nImage, SINGLE @nWidth, SINGLE
      @Height
      DECLARE LONG GdipGetImageType IN GDIPLUS LONG nImage, LONG @itype
      DECLARE LONG GdipGetImageWidth IN GDIPLUS LONG nImage, LONG @nWidth
      DECLARE LONG GdipGetImageHeight IN GDIPLUS LONG nImage, LONG @Height
      DECLARE LONG GdipGetImageHorizontalResolution IN GDIPLUS LONG nImage, SINGLE @resolution
      DECLARE LONG GdipGetImageVerticalResolution IN GDIPLUS LONG nImage, SINGLE @resolution
      DECLARE LONG GdipGetImageFlags IN GDIPLUS LONG nImage, LONG @flags
      DECLARE LONG GdipGetImageRawFormat IN GDIPLUS LONG nImage, STRING @format
      DECLARE LONG GdipGetImagePixelFormat IN GDIPLUS LONG nImage, LONG @PixelFormat
      DECLARE LONG GdipGetImageThumbnail IN GDIPLUS LONG nImage, LONG thumbWidth, LONG thumbHeight,
      LONG @thumbnImage, LONG pCALLBACK, LONG callbackData
      DECLARE LONG GdipGetEncoderParameterListSize IN GDIPLUS LONG nImage, STRING @clsidEncoder,
      LONG @SIZE
      DECLARE LONG GdipGetEncoderParameterList IN GDIPLUS LONG nImage, STRING @clsidEncoder,
      LONG SIZE, LONG @buffer
      DECLARE LONG GdipImageGetFrameDimensionsCount IN GDIPLUS LONG nImage, LONG @Count
      DECLARE LONG GdipImageGetFrameDimensionsList IN GDIPLUS LONG nImage, STRING @dimensionIDs,
      LONG Count
      DECLARE LONG GdipImageGetFrameCount IN GDIPLUS LONG nImage, STRING @dimensionID, LONG
      @Count
      DECLARE LONG GdipImageSelectActiveFrame IN GDIPLUS LONG nImage, STRING @dimensionID,
      LONG frameIndex
      DECLARE LONG GdipImageRotateFlip IN GDIPLUS LONG nImage, LONG rfType
      DECLARE LONG GdipGetImagePalette IN GDIPLUS LONG nImage, LONG @palette, LONG SIZE
      DECLARE LONG GdipSetImagePalette IN GDIPLUS LONG nImage, LONG @palette
      DECLARE LONG GdipGetImagePaletteSize IN GDIPLUS LONG nImage, LONG @SIZE
      DECLARE LONG GdipGetPropertyCount IN GDIPLUS LONG nImage, LONG @numOfProperty
      DECLARE LONG GdipGetPropertyIdList IN GDIPLUS LONG nImage, LONG numOfProperty, LONG
      @list
      DECLARE LONG GdipGetPropertyItemSize IN GDIPLUS LONG nImage, LONG propId, LONG @SIZE
      DECLARE LONG GdipGetPropertyItem IN GDIPLUS LONG nImage, LONG propId, LONG propSize,
      STRING @buffer
      DECLARE LONG GdipGetPropertySize IN GDIPLUS LONG nImage, LONG @totalBufferSize, LONG
      @numProperties
      DECLARE LONG GdipGetAllPropertyItems IN GDIPLUS LONG nImage, LONG totalBufferSize,
      LONG numProperties, STRING @allItems
      DECLARE LONG GdipRemovePropertyItem IN GDIPLUS LONG nImage, LONG propId
      DECLARE LONG GdipSetPropertyItem IN GDIPLUS LONG nImage, STRING @item
      DECLARE LONG GdipImageForceValidation IN GDIPLUS LONG nImage
      *!* Bitmap
      DECLARE LONG GdipCreateBitmapFromFile IN GDIPLUS LONG FilName, LONG @nBitmap
      DECLARE LONG GdipCreateBitmapFromFileICM IN GDIPLUS LONG FilName, LONG @nBitmap
      DECLARE LONG GdipCreateBitmapFromStream IN GDIPLUS INTEGER stream, Long @nBitmap
      DECLARE LONG GdipCreateBitmapFromStreamICM IN GDIPLUS INTEGER stream, Long @nBitmap
      DECLARE LONG GdipCreateBitmapFromScan0 IN GDIPLUS LONG nWidth, LONG Height, LONG stride,
      LONG PixelFormat, STRING @scan0, LONG @nBitmap
      DECLARE LONG GdipCreateBitmapFromGraphics IN GDIPLUS LONG nWidth, LONG Height, LONG
      graphics, LONG @nBitmap
      DECLARE LONG GdipCreateBitmapFromDirectDrawSurface IN GDIPLUS LONG @surface, Long
      @nBitmap
      DECLARE LONG GdipCreateBitmapFromGdiDib IN GDIPLUS STRING @gdiBitmapInfo, LONG gdiBitmapData,
      LONG @nBitmap
      DECLARE LONG GdipCreateBitmapFromHBITMAP IN GDIPLUS LONG hbm, LONG hpal, LONG @nBitmap
      DECLARE LONG GdipCreateHBITMAPFromBitmap IN GDIPLUS LONG nBitmap, LONG @hbmReturn,
      LONG background
      DECLARE LONG GdipCreateBitmapFromHICON IN GDIPLUS LONG hicon, LONG @nBitmap
      DECLARE LONG GdipCreateHICONFromBitmap IN GDIPLUS LONG nBitmap, LONG @hbmReturn
      DECLARE LONG GdipCreateBitmapFromResource IN GDIPLUS LONG hInstance, STRING lpBitmapName,
      LONG @nBitmap
      DECLARE LONG GdipCloneBitmapArea IN GDIPLUS SINGLE x, SINGLE y, SINGLE nWidth, SINGLE
      Height, LONG PixelFormat, LONG srcBitmap, LONG @dstBitmap
      DECLARE LONG GdipCloneBitmapAreaI IN GDIPLUS LONG x, LONG y, LONG nWidth, LONG Height,
      LONG PixelFormat, LONG srcBitmap, LONG @dstBitmap
      DECLARE LONG GdipBitmapLockBits IN GDIPLUS LONG nBitmap, STRING @nRect, LONG flags,
      LONG PixelFormat, LONG @lockedBitmapData
      DECLARE LONG GdipBitmapUnlockBits IN GDIPLUS LONG nBitmap, LONG @lockedBitmapData
      DECLARE LONG GdipBitmapGetPixel IN GDIPLUS LONG nBitmap, LONG x, LONG y, LONG @COLOR
      DECLARE LONG GdipBitmapSetPixel IN GDIPLUS LONG nBitmap, LONG x, LONG y, LONG COLOR
      DECLARE LONG GdipBitmapSetResolution IN GDIPLUS LONG nBitmap, SINGLE xdpi, SINGLE
      ydpi
      *!* CachedBitmap
      DECLARE LONG GdipCreateCachedBitmap IN GDIPLUS LONG nBitmap, LONG graphics, LONG @cachedBitmap
      DECLARE LONG GdipDeleteCachedBitmap IN GDIPLUS LONG cachedBitmap
      DECLARE LONG GdipDrawCachedBitmap IN GDIPLUS LONG graphics, LONG cachedBitmap, LONG
      x, LONG y
      *!* Brush
      DECLARE LONG GdipCloneBrush IN GDIPLUS LONG brush, LONG @cloneBrush
      DECLARE LONG GdipDeleteBrush IN GDIPLUS LONG brush
      DECLARE LONG GdipGetBrushType IN GDIPLUS LONG brush, LONG @brshType
      *!* HatchBrush
      DECLARE LONG GdipCreateHatchBrush IN GDIPLUS LONG style, LONG forecolr, LONG backcolr,
      LONG @brush
      DECLARE LONG GdipGetHatchStyle IN GDIPLUS LONG brush, LONG @style
      DECLARE LONG GdipGetHatchForegroundColor IN GDIPLUS LONG brush, LONG @forecolr
      DECLARE LONG GdipGetHatchBackgroundColor IN GDIPLUS LONG brush, LONG @backcolr
      *!* SolidBrush
      DECLARE LONG GdipCreateSolidFill IN GDIPLUS LONG argb, LONG @brush
      DECLARE LONG GdipSetSolidFillColor IN GDIPLUS LONG brush, LONG argb
      DECLARE LONG GdipGetSolidFillColor IN GDIPLUS LONG brush, LONG @argb
      *!* LineBrush
      DECLARE LONG GdipCreateLineBrush IN GDIPLUS STRING @point1, STRING @point2, LONG color1,
      LONG color2, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipCreateLineBrushI IN GDIPLUS STRING @point1, STRING @point2, LONG
      color1, LONG color2, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipCreateLineBrushFromRect IN GDIPLUS STRING @nRect, LONG color1, LONG
      color2, LONG mode, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipCreateLineBrushFromRectI IN GDIPLUS STRING @nRect, LONG color1, LONG
      color2, LONG mode, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipCreateLineBrushFromRectWithAngle IN GDIPLUS STRING @nRect, LONG color1,
      LONG color2, SINGLE angle, LONG isAngleScalable, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipCreateLineBrushFromRectWithAngleI IN GDIPLUS STRING @nRect, LONG
      color1, LONG color2, SINGLE angle, LONG isAngleScalable, LONG WrapMd, LONG @lineGradient
      DECLARE LONG GdipSetLineColors IN GDIPLUS LONG brush, LONG color1, LONG color2
      DECLARE LONG GdipGetLineColors IN GDIPLUS LONG brush, LONG @lColors
      DECLARE LONG GdipGetLineRect IN GDIPLUS LONG brush, STRING @nRect
      DECLARE LONG GdipGetLineRectI IN GDIPLUS LONG brush, STRING @nRect
      DECLARE LONG GdipSetLineGammaCorrection IN GDIPLUS LONG brush, LONG useGammaCorrection
      DECLARE LONG GdipGetLineGammaCorrection IN GDIPLUS LONG brush, LONG @useGammaCorrection
      DECLARE LONG GdipGetLineBlendCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipGetLineBlend IN GDIPLUS LONG brush, SINGLE @blend, SINGLE @positions,
      LONG Count
      DECLARE LONG GdipSetLineBlend IN GDIPLUS LONG brush, SINGLE @blend, SINGLE @positions,
      LONG Count
      DECLARE LONG GdipGetLinePresetBlendCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipGetLinePresetBlend IN GDIPLUS LONG brush, LONG @blend, SINGLE @positions,
      LONG Count
      DECLARE LONG GdipSetLinePresetBlend IN GDIPLUS LONG brush, LONG @blend, SINGLE @positions,
      LONG Count
      DECLARE LONG GdipSetLineSigmaBlend IN GDIPLUS LONG brush, SINGLE FOCUS, SINGLE theScale
      DECLARE LONG GdipSetLineLinearBlend IN GDIPLUS LONG brush, SINGLE FOCUS, SINGLE theScale
      DECLARE LONG GdipSetLineWrapMode IN GDIPLUS LONG brush, LONG WrapMd
      DECLARE LONG GdipGetLineWrapMode IN GDIPLUS LONG brush, LONG @WrapMd
      DECLARE LONG GdipGetLineTransform IN GDIPLUS LONG brush, LONG @matrix
      DECLARE LONG GdipSetLineTransform IN GDIPLUS LONG brush, LONG matrix
      DECLARE LONG GdipResetLineTransform IN GDIPLUS LONG brush
      DECLARE LONG GdipMultiplyLineTransform IN GDIPLUS LONG brush, LONG matrix, LONG order
      DECLARE LONG GdipTranslateLineTransform IN GDIPLUS LONG brush, SINGLE dx, SINGLE dy,
      LONG order
      DECLARE LONG GdipScaleLineTransform IN GDIPLUS LONG brush, SINGLE sx, SINGLE sy, LONG
      order
      DECLARE LONG GdipRotateLineTransform IN GDIPLUS LONG brush, SINGLE angle, LONG order
      *!* TextureBrush
      DECLARE LONG GdipCreateTexture IN GDIPLUS LONG nImage, LONG WrapMd, LONG @texture
      DECLARE LONG GdipCreateTexture2 IN GDIPLUS LONG nImage, LONG WrapMd, SINGLE x, SINGLE
      y, SINGLE nWidth, SINGLE Height, LONG @texture
      DECLARE LONG GdipCreateTextureIA IN GDIPLUS LONG nImage, LONG imageAttributes, SINGLE
      x, SINGLE y, SINGLE nWidth, SINGLE Height, LONG @texture
      DECLARE LONG GdipCreateTexture2I IN GDIPLUS LONG nImage, LONG WrapMd, LONG x, LONG
      y, LONG nWidth, LONG Height, LONG @texture
      DECLARE LONG GdipCreateTextureIAI IN GDIPLUS LONG nImage, LONG imageAttributes, LONG
      x, LONG y, LONG nWidth, LONG Height, LONG @texture
      DECLARE LONG GdipGetTextureTransform IN GDIPLUS LONG brush, LONG matrix
      DECLARE LONG GdipSetTextureTransform IN GDIPLUS LONG brush, LONG matrix
      DECLARE LONG GdipResetTextureTransform IN GDIPLUS LONG brush
      DECLARE LONG GdipTranslateTextureTransform IN GDIPLUS LONG brush, SINGLE dx, SINGLE
      dy, LONG order
      DECLARE LONG GdipMultiplyTextureTransform IN GDIPLUS LONG brush, LONG matrix, LONG
      order
      DECLARE LONG GdipScaleTextureTransform IN GDIPLUS LONG brush, SINGLE sx, SINGLE sy,
      LONG order
      DECLARE LONG GdipRotateTextureTransform IN GDIPLUS LONG brush, SINGLE angle, LONG
      order
      DECLARE LONG GdipSetTextureWrapMode IN GDIPLUS LONG brush, LONG WrapMd
      DECLARE LONG GdipGetTextureWrapMode IN GDIPLUS LONG brush, LONG @WrapMd
      DECLARE LONG GdipGetTextureImage IN GDIPLUS LONG brush, LONG @nImage
      *!* PathGradientBrush
      DECLARE LONG GdipCreatePathGradient IN GDIPLUS STRING @pPoint, LONG Count, LONG WrapMd,
      LONG @polyGradient
      DECLARE LONG GdipCreatePathGradientI IN GDIPLUS STRING @pPoint, LONG Count, LONG WrapMd,
      LONG @polyGradient
      DECLARE LONG GdipCreatePathGradientFromPath IN GDIPLUS LONG path, LONG @polyGradient
      DECLARE LONG GdipGetPathGradientCenterColor IN GDIPLUS LONG brush, LONG @lColors
      DECLARE LONG GdipSetPathGradientCenterColor IN GDIPLUS LONG brush, LONG lColors
      DECLARE LONG GdipGetPathGradientSurroundColorsWithCount IN GDIPLUS LONG brush, LONG
      @argb, LONG @Count
      DECLARE LONG GdipSetPathGradientSurroundColorsWithCount IN GDIPLUS LONG brush, LONG
      @argb, LONG @Count
      DECLARE LONG GdipGetPathGradientPath IN GDIPLUS LONG brush, LONG path
      DECLARE LONG GdipSetPathGradientPath IN GDIPLUS LONG brush, LONG path
      DECLARE LONG GdipGetPathGradientCenterPoint IN GDIPLUS LONG brush, STRING @pPoint
      DECLARE LONG GdipGetPathGradientCenterPointI IN GDIPLUS LONG brush, STRING @pPoint
      DECLARE LONG GdipSetPathGradientCenterPoint IN GDIPLUS LONG brush, STRING @pPoint
      DECLARE LONG GdipSetPathGradientCenterPointI IN GDIPLUS LONG brush, STRING @pPoint
      DECLARE LONG GdipGetPathGradientRect IN GDIPLUS LONG brush, STRING @nRect
      DECLARE LONG GdipGetPathGradientRectI IN GDIPLUS LONG brush, STRING @nRect
      DECLARE LONG GdipGetPathGradientPointCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipGetPathGradientSurroundColorCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipSetPathGradientGammaCorrection IN GDIPLUS LONG brush, LONG useGammaCorrection
      DECLARE LONG GdipGetPathGradientGammaCorrection IN GDIPLUS LONG brush, LONG @useGammaCorrection
      DECLARE LONG GdipGetPathGradientBlendCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipGetPathGradientBlend IN GDIPLUS LONG brush, SINGLE @blend, SINGLE
      @positions, LONG Count
      DECLARE LONG GdipSetPathGradientBlend IN GDIPLUS LONG brush, SINGLE @blend, SINGLE
      @positions, LONG Count
      DECLARE LONG GdipGetPathGradientPresetBlendCount IN GDIPLUS LONG brush, LONG @Count
      DECLARE LONG GdipGetPathGradientPresetBlend IN GDIPLUS LONG brush, LONG @blend, SINGLE
      @positions, LONG Count
      DECLARE LONG GdipSetPathGradientPresetBlend IN GDIPLUS LONG brush, LONG @blend, SINGLE
      @positions, LONG Count
      DECLARE LONG GdipSetPathGradientSigmaBlend IN GDIPLUS LONG brush, SINGLE FOCUS, SINGLE
      sscale
      DECLARE LONG GdipSetPathGradientLinearBlend IN GDIPLUS LONG brush, SINGLE FOCUS, SINGLE
      sscale
      DECLARE LONG GdipGetPathGradientWrapMode IN GDIPLUS LONG brush, LONG @WrapMd
      DECLARE LONG GdipSetPathGradientWrapMode IN GDIPLUS LONG brush, LONG WrapMd
      DECLARE LONG GdipGetPathGradientTransform IN GDIPLUS LONG brush, LONG matrix
      DECLARE LONG GdipSetPathGradientTransform IN GDIPLUS LONG brush, LONG matrix
      DECLARE LONG GdipResetPathGradientTransform IN GDIPLUS LONG brush
      DECLARE LONG GdipMultiplyPathGradientTransform IN GDIPLUS LONG brush, LONG matrix,
      LONG order
      DECLARE LONG GdipTranslatePathGradientTransform IN GDIPLUS LONG brush, SINGLE dx,
      SINGLE dy, LONG order
      DECLARE LONG GdipScalePathGradientTransform IN GDIPLUS LONG brush, SINGLE sx, SINGLE
      sy, LONG order
      DECLARE LONG GdipRotatePathGradientTransform IN GDIPLUS LONG brush, SINGLE angle,
      LONG order
      DECLARE LONG GdipGetPathGradientFocusScales IN GDIPLUS LONG brush, SINGLE @xScale,
      SINGLE @yScale
      DECLARE LONG GdipSetPathGradientFocusScales IN GDIPLUS LONG brush, SINGLE xScale,
      SINGLE yScale
      *!* Path
      DECLARE LONG GdipCreatePath IN GDIPLUS LONG brushmode, LONG @path
      DECLARE LONG GdipCreatePath2 IN GDIPLUS STRING @pPoint, STRING @types, LONG Count,
      LONG @brushmode, LONG @path
      DECLARE LONG GdipCreatePath2I IN GDIPLUS STRING @pPoint, STRING @types, LONG Count,
      LONG @brushmode, LONG @path
      DECLARE LONG GdipClonePath IN GDIPLUS LONG path, LONG @clonePath
      DECLARE LONG GdipDeletePath IN GDIPLUS LONG path
      DECLARE LONG GdipResetPath IN GDIPLUS LONG path
      DECLARE LONG GdipGetPointCount IN GDIPLUS LONG path, LONG @Count
      DECLARE LONG GdipGetPathTypes IN GDIPLUS LONG path, STRING @types, LONG Count
      DECLARE LONG GdipGetPathPoints IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipGetPathPointsI IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipGetPathFillMode IN GDIPLUS LONG path, LONG brushmode
      DECLARE LONG GdipSetPathFillMode IN GDIPLUS LONG path, LONG brushmode
      DECLARE LONG GdipGetPathData IN GDIPLUS LONG path, STRING @pdata
      DECLARE LONG GdipStartPathFigure IN GDIPLUS LONG path
      DECLARE LONG GdipClosePathFigure IN GDIPLUS LONG path
      DECLARE LONG GdipClosePathFigures IN GDIPLUS LONG path
      DECLARE LONG GdipSetPathMarker IN GDIPLUS LONG path
      DECLARE LONG GdipClearPathMarkers IN GDIPLUS LONG path
      DECLARE LONG GdipReversePath IN GDIPLUS LONG path
      DECLARE LONG GdipGetPathLastPoint IN GDIPLUS LONG path, STRING @lastPoint
      DECLARE LONG GdipAddPathLine IN GDIPLUS LONG path, SINGLE x1, SINGLE y1, SINGLE x2,
      SINGLE y2
      DECLARE LONG GdipAddPathLine2 IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathArc IN GDIPLUS LONG path, SINGLE x, SINGLE y, SINGLE nWidth,
      SINGLE Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipAddPathBezier IN GDIPLUS LONG path, SINGLE x1, SINGLE y1, SINGLE
      x2, SINGLE y2, SINGLE x3, SINGLE y3, SINGLE x4, SINGLE y4
      DECLARE LONG GdipAddPathBeziers IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathCurve IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathCurve2 IN GDIPLUS LONG path, STRING @pPoint, LONG Count, SINGLE
      tension
      DECLARE LONG GdipAddPathCurve3 IN GDIPLUS LONG path, STRING @pPoint, LONG Count, LONG
      offset, LONG numberOfSegments, SINGLE tension
      DECLARE LONG GdipAddPathClosedCurve IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathClosedCurve2 IN GDIPLUS LONG path, STRING @pPoint, LONG Count,
      SINGLE tension
      DECLARE LONG GdipAddPathRectangle IN GDIPLUS LONG path, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height
      DECLARE LONG GdipAddPathRectangles IN GDIPLUS LONG path, STRING @nRect, LONG Count
      DECLARE LONG GdipAddPathEllipse IN GDIPLUS LONG path, SINGLE x, SINGLE y, SINGLE nWidth,
      SINGLE Height
      DECLARE LONG GdipAddPathPie IN GDIPLUS LONG path, SINGLE x, SINGLE y, SINGLE nWidth,
      SINGLE Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipAddPathPolygon IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathPath IN GDIPLUS LONG path, LONG addingPath, LONG bConnect
      DECLARE LONG GdipAddPathString IN GDIPLUS LONG path, STRING str, LONG length, LONG
      family, LONG style, SINGLE emSize, STRING @layoutRect, LONG StringFormat
      DECLARE LONG GdipAddPathStringI IN GDIPLUS LONG path, STRING str, LONG length, LONG
      family, LONG style, SINGLE emSize, STRING @layoutRect, LONG StringFormat
      DECLARE LONG GdipAddPathLineI IN GDIPLUS LONG path, LONG x1, LONG y1, LONG x2, LONG
      y2
      DECLARE LONG GdipAddPathLine2I IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathArcI IN GDIPLUS LONG path, LONG x, LONG y, LONG nWidth, LONG
      Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipAddPathBezierI IN GDIPLUS LONG path, LONG x1, LONG y1, LONG x2, LONG
      y2, LONG x3, LONG y3, LONG x4, LONG y4
      DECLARE LONG GdipAddPathBeziersI IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathCurveI IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathCurve2I IN GDIPLUS LONG path, STRING @pPoint, LONG Count,
      LONG tension
      DECLARE LONG GdipAddPathCurve3I IN GDIPLUS LONG path, STRING @pPoint, LONG Count,
      LONG offset, LONG numberOfSegments, SINGLE tension
      DECLARE LONG GdipAddPathClosedCurveI IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipAddPathClosedCurve2I IN GDIPLUS LONG path, STRING @pPoint, LONG Count,
      SINGLE tension
      DECLARE LONG GdipAddPathRectangleI IN GDIPLUS LONG path, LONG x, LONG y, LONG nWidth,
      LONG Height
      DECLARE LONG GdipAddPathRectanglesI IN GDIPLUS LONG path, STRING @rects, LONG Count
      DECLARE LONG GdipAddPathEllipseI IN GDIPLUS LONG path, LONG x, LONG y, LONG nWidth,
      LONG Height
      DECLARE LONG GdipAddPathPieI IN GDIPLUS LONG path, LONG x, LONG y, LONG nWidth, LONG
      Height, SINGLE startAngle, SINGLE sweepAngle
      DECLARE LONG GdipAddPathPolygonI IN GDIPLUS LONG path, STRING @pPoint, LONG Count
      DECLARE LONG GdipFlattenPath IN GDIPLUS LONG path, LONG matrix, SINGLE flatness
      DECLARE LONG GdipWindingModeOutline IN GDIPLUS LONG path, LONG matrix, SINGLE flatness
      DECLARE LONG GdipWidenPath IN GDIPLUS LONG nativePath, LONG pen, LONG matrix, SINGLE
      flatness
      DECLARE LONG GdipWarpPath IN GDIPLUS LONG path, LONG matrix, STRING @pPoint, LONG
      Count, SINGLE srcx, SINGLE srcy, SINGLE srcwidth, SINGLE srcheight, LONG WarpMd, SINGLE
      flatness
      DECLARE LONG GdipTransformPath IN GDIPLUS LONG path, LONG matrix
      DECLARE LONG GdipGetPathWorldBounds IN GDIPLUS LONG path, STRING @bounds, LONG matrix,
      LONG pen
      DECLARE LONG GdipGetPathWorldBoundsI IN GDIPLUS LONG path, STRING @bounds, LONG matrix,
      LONG pen
      DECLARE LONG GdipIsVisiblePathPoint IN GDIPLUS LONG path, SINGLE x, SINGLE y, LONG
      graphics, LONG @result
      DECLARE LONG GdipIsVisiblePathPointI IN GDIPLUS LONG path, LONG x, LONG y, LONG graphics,
      LONG @result
      DECLARE LONG GdipIsOutlineVisiblePathPoint IN GDIPLUS LONG path, SINGLE x, SINGLE
      y, LONG pen, LONG graphics, LONG @result
      DECLARE LONG GdipIsOutlineVisiblePathPointI IN GDIPLUS LONG path, LONG x, LONG y,
      LONG pen, LONG graphics, LONG @result
      *!* PathIterator
      DECLARE LONG GdipCreatePathIter IN GDIPLUS LONG @iterator, LONG path
      DECLARE LONG GdipDeletePathIter IN GDIPLUS LONG iterator
      DECLARE LONG GdipPathIterNextSubpath IN GDIPLUS LONG iterator, LONG @resultCount,
      LONG @startIndex, LONG @endIndex, LONG @isClosed
      DECLARE LONG GdipPathIterNextSubpathPath IN GDIPLUS LONG iterator, LONG @resultCount,
      LONG path, LONG @isClosed
      DECLARE LONG GdipPathIterNextPathType IN GDIPLUS LONG iterator, LONG @resultCount,
      STRING @pathType, LONG @startIndex, LONG @endIndex
      DECLARE LONG GdipPathIterNextMarker IN GDIPLUS LONG iterator, LONG @resultCount, LONG
      @startIndex, LONG @endIndex
      DECLARE LONG GdipPathIterNextMarkerPath IN GDIPLUS LONG iterator, LONG @resultCount,
      LONG path
      DECLARE LONG GdipPathIterGetCount IN GDIPLUS LONG iterator, LONG @Count
      DECLARE LONG GdipPathIterGetSubpathCount IN GDIPLUS LONG iterator, LONG @Count
      DECLARE LONG GdipPathIterIsValid IN GDIPLUS LONG iterator, LONG @valid
      DECLARE LONG GdipPathIterHasCurve IN GDIPLUS LONG iterator, LONG @hasCurve
      DECLARE LONG GdipPathIterRewind IN GDIPLUS LONG iterator
      DECLARE LONG GdipPathIterEnumerate IN GDIPLUS LONG iterator, LONG @resultCount, STRING
      @pPoint, STRING @types, LONG Count
      DECLARE LONG GdipPathIterCopyData IN GDIPLUS LONG iterator, LONG @resultCount, STRING
      @pPoint, STRING @types, LONG startIndex, LONG endIndex
      *!* Region
      DECLARE LONG GdipCreateRegion IN GDIPLUS LONG @region
      DECLARE LONG GdipCreateRegionRect IN GDIPLUS STRING @nRect, LONG @region
      DECLARE LONG GdipCreateRegionRectI IN GDIPLUS STRING @nRect, LONG @region
      DECLARE LONG GdipCreateRegionPath IN GDIPLUS LONG path, LONG @region
      DECLARE LONG GdipCreateRegionRgnData IN GDIPLUS STRING @regionData, LONG SIZE, LONG
      @region
      DECLARE LONG GdipCreateRegionHrgn IN GDIPLUS LONG hRgn, LONG @region
      DECLARE LONG GdipCloneRegion IN GDIPLUS LONG region, LONG @cloneRegion
      DECLARE LONG GdipDeleteRegion IN GDIPLUS LONG region
      DECLARE LONG GdipSetInfinite IN GDIPLUS LONG region
      DECLARE LONG GdipSetEmpty IN GDIPLUS LONG region
      DECLARE LONG GdipCombineRegionRect IN GDIPLUS LONG region, STRING @nRect, LONG CombineMd
      DECLARE LONG GdipCombineRegionRectI IN GDIPLUS LONG region, STRING @nRect, LONG CombineMd
      DECLARE LONG GdipCombineRegionPath IN GDIPLUS LONG region, LONG path, LONG CombineMd
      DECLARE LONG GdipCombineRegionRegion IN GDIPLUS LONG region, LONG region2, LONG CombineMd
      DECLARE LONG GdipTranslateRegion IN GDIPLUS LONG region, SINGLE dx, SINGLE dy
      DECLARE LONG GdipTranslateRegionI IN GDIPLUS LONG region, LONG dx, LONG dy
      DECLARE LONG GdipTransformRegion IN GDIPLUS LONG region, LONG matrix
      DECLARE LONG GdipGetRegionBounds IN GDIPLUS LONG region, LONG graphics, STRING @nRect
      DECLARE LONG GdipGetRegionBoundsI IN GDIPLUS LONG region, LONG graphics, STRING @nRect
      DECLARE LONG GdipGetRegionHRgn IN GDIPLUS LONG region, LONG graphics, LONG @hRgn
      DECLARE LONG GdipIsEmptyRegion IN GDIPLUS LONG region, LONG graphics, LONG @result
      DECLARE LONG GdipIsInfiniteRegion IN GDIPLUS LONG region, LONG graphics, LONG @result
      DECLARE LONG GdipIsEqualRegion IN GDIPLUS LONG region, LONG region2, LONG graphics,
      LONG @result
      DECLARE LONG GdipGetRegionDataSize IN GDIPLUS LONG region, LONG @bufferSize
      DECLARE LONG GdipGetRegionData IN GDIPLUS LONG region, STRING @buffer, LONG bufferSize,
      LONG @sizeFilled
      DECLARE LONG GdipIsVisibleRegionPoint IN GDIPLUS LONG region, SINGLE x, SINGLE y,
      LONG graphics, LONG @result
      DECLARE LONG GdipIsVisibleRegionPointI IN GDIPLUS LONG region, LONG x, LONG y, LONG
      graphics, LONG @result
      DECLARE LONG GdipIsVisibleRegionRect IN GDIPLUS LONG region, SINGLE x, SINGLE y, SINGLE
      nWidth, SINGLE Height, LONG graphics, LONG @result
      DECLARE LONG GdipIsVisibleRegionRectI IN GDIPLUS LONG region, LONG x, LONG y, LONG
      nWidth, LONG Height, LONG graphics, LONG @result
      DECLARE LONG GdipGetRegionScansCount IN GDIPLUS LONG region, LONG @Ucount, LONG matrix
      DECLARE LONG GdipGetRegionScans IN GDIPLUS LONG region, STRING @rects, LONG @Count,
      LONG matrix
      DECLARE LONG GdipGetRegionScansI IN GDIPLUS LONG region, STRING @rects, LONG @Count,
      LONG matrix
      *!* Pen
      DECLARE LONG GdipCreatePen1 IN GDIPLUS LONG Colr, SINGLE nWidth, LONG unit, LONG @pen
      DECLARE LONG GdipCreatePen2 IN GDIPLUS LONG brush, SINGLE nWidth, LONG unit, LONG
      @pen
      DECLARE LONG GdipClonePen IN GDIPLUS LONG pen, LONG @clonepen
      DECLARE LONG GdipDeletePen IN GDIPLUS LONG pen
      DECLARE LONG GdipSetPenWidth IN GDIPLUS LONG pen, SINGLE nWidth
      DECLARE LONG GdipGetPenWidth IN GDIPLUS LONG pen, SINGLE @nWidth
      DECLARE LONG GdipSetPenUnit IN GDIPLUS LONG pen, LONG unit
      DECLARE LONG GdipGetPenUnit IN GDIPLUS LONG pen, LONG @unit
      DECLARE LONG GdipSetPenLineCap IN GDIPLUS LONG pen, LONG startCap, LONG endCap, LONG
      dcap
      DECLARE LONG GdipSetPenStartCap IN GDIPLUS LONG pen, LONG startCap
      DECLARE LONG GdipSetPenEndCap IN GDIPLUS LONG pen, LONG endCap
      DECLARE LONG GdipSetPenDashCap IN GDIPLUS LONG pen, LONG dcap
      DECLARE LONG GdipGetPenStartCap IN GDIPLUS LONG pen, LONG @startCap
      DECLARE LONG GdipGetPenEndCap IN GDIPLUS LONG pen, LONG @endCap
      DECLARE LONG GdipGetPenDashCap IN GDIPLUS LONG pen, LONG @dcap
      DECLARE LONG GdipSetPenLineJoin IN GDIPLUS LONG pen, LONG LnJoin
      DECLARE LONG GdipGetPenLineJoin IN GDIPLUS LONG pen, LONG @LnJoin
      DECLARE LONG GdipSetPenCustomStartCap IN GDIPLUS LONG pen, LONG customCap
      DECLARE LONG GdipGetPenCustomStartCap IN GDIPLUS LONG pen, LONG @customCap
      DECLARE LONG GdipSetPenCustomEndCap IN GDIPLUS LONG pen, LONG customCap
      DECLARE LONG GdipGetPenCustomEndCap IN GDIPLUS LONG pen, LONG @customCap
      DECLARE LONG GdipSetPenMiterLimit IN GDIPLUS LONG pen, SINGLE miterLimit
      DECLARE LONG GdipGetPenMiterLimit IN GDIPLUS LONG pen, SINGLE @miterLimit
      DECLARE LONG GdipSetPenMode IN GDIPLUS LONG pen, LONG penMode
      DECLARE LONG GdipGetPenMode IN GDIPLUS LONG pen, LONG @penMode
      DECLARE LONG GdipSetPenTransform IN GDIPLUS LONG pen, LONG matrix
      DECLARE LONG GdipGetPenTransform IN GDIPLUS LONG pen, LONG matrix
      DECLARE LONG GdipResetPenTransform IN GDIPLUS LONG pen
      DECLARE LONG GdipMultiplyPenTransform IN GDIPLUS LONG pen, LONG matrix, LONG order
      DECLARE LONG GdipTranslatePenTransform IN GDIPLUS LONG pen, SINGLE dx, SINGLE dy,
      LONG order
      DECLARE LONG GdipScalePenTransform IN GDIPLUS LONG pen, SINGLE sx, SINGLE sy, LONG
      order
      DECLARE LONG GdipRotatePenTransform IN GDIPLUS LONG pen, SINGLE angle, LONG order
      DECLARE LONG GdipSetPenColor IN GDIPLUS LONG pen, LONG argb
      DECLARE LONG GdipGetPenColor IN GDIPLUS LONG pen, LONG @argb
      DECLARE LONG GdipSetPenBrushFill IN GDIPLUS LONG pen, LONG brush
      DECLARE LONG GdipGetPenBrushFill IN GDIPLUS LONG pen, LONG @brush
      DECLARE LONG GdipGetPenFillType IN GDIPLUS LONG pen, LONG @ptype
      DECLARE LONG GdipGetPenDashStyle IN GDIPLUS LONG pen, LONG @dStyle
      DECLARE LONG GdipSetPenDashStyle IN GDIPLUS LONG pen, LONG dStyle
      DECLARE LONG GdipGetPenDashOffset IN GDIPLUS LONG pen, SINGLE @offset
      DECLARE LONG GdipSetPenDashOffset IN GDIPLUS LONG pen, SINGLE offset
      DECLARE LONG GdipGetPenDashCount IN GDIPLUS LONG pen, LONG @Count
      DECLARE LONG GdipSetPenDashArray IN GDIPLUS LONG pen, SINGLE @dash, LONG Count
      DECLARE LONG GdipGetPenDashArray IN GDIPLUS LONG pen, SINGLE @dash, LONG Count
      DECLARE LONG GdipGetPenCompoundCount IN GDIPLUS LONG pen, LONG @Count
      DECLARE LONG GdipSetPenCompoundArray IN GDIPLUS LONG pen, SINGLE @dash, LONG Count
      DECLARE LONG GdipGetPenCompoundArray IN GDIPLUS LONG pen, SINGLE @dash, LONG Count
      *!* FontFamily
      DECLARE LONG GdipCreateFontFamilyFromName IN GDIPLUS STRING FontName, LONG fontCollection,
      LONG @fontFamily
      DECLARE LONG GdipDeleteFontFamily IN GDIPLUS LONG fontFamily
      DECLARE LONG GdipCloneFontFamily IN GDIPLUS LONG fontFamily, LONG @clonedFontFamily
      DECLARE LONG GdipGetGenericFontFamilySansSerif IN GDIPLUS LONG @nativeFamily
      DECLARE LONG GdipGetGenericFontFamilySerif IN GDIPLUS LONG @nativeFamily
      DECLARE LONG GdipGetGenericFontFamilyMonospace IN GDIPLUS LONG @nativeFamily
      DECLARE LONG GdipGetFamilyName IN GDIPLUS LONG family, STRING FilName, INTEGER language
      DECLARE LONG GdipIsStyleAvailable IN GDIPLUS LONG family, LONG style, LONG @IsStyleAvailable
      DECLARE LONG GdipFontCollectionEnumerable IN GDIPLUS LONG fontCollection, LONG graphics,
      LONG @numFound
      DECLARE LONG GdipFontCollectionEnumerate IN GDIPLUS LONG fontCollection, LONG numSought,
      LONG @gpfamilies, LONG numFound, LONG graphics
      DECLARE LONG GdipGetEmHeight IN GDIPLUS LONG family, LONG style, INTEGER @EmHeight
      DECLARE LONG GdipGetCellAscent IN GDIPLUS LONG family, LONG style, INTEGER @CellAscent
      DECLARE LONG GdipGetCellDescent IN GDIPLUS LONG family, LONG style, INTEGER @CellDescent
      DECLARE LONG GdipGetLineSpacing IN GDIPLUS LONG family, LONG style, INTEGER @LineSpacing
      *!* Font
      DECLARE LONG GdipCreateFontFromDC IN GDIPLUS LONG hdc, LONG @createdfont
      DECLARE LONG GdipCreateFontFromLogfontA IN GDIPLUS LONG hdc, LOGFONTA @lfont, LONG
      @createdfont
      DECLARE LONG GdipCreateFontFromLogfontW IN GDIPLUS LONG hdc, LOGFONTW @lfont, LONG
      @createdfont
      DECLARE LONG GdipCreateFont IN GDIPLUS LONG fontFamily, SINGLE emSize, LONG style,
      LONG unit, LONG @createdfont
      DECLARE LONG GdipCloneFont IN GDIPLUS LONG curFont, LONG @cloneFont
      DECLARE LONG GdipDeleteFont IN GDIPLUS LONG curFont
      DECLARE LONG GdipGetFamily IN GDIPLUS LONG curFont, LONG @family
      DECLARE LONG GdipGetFontStyle IN GDIPLUS LONG curFont, LONG @style
      DECLARE LONG GdipGetFontSize IN GDIPLUS LONG curFont, SINGLE @SIZE
      DECLARE LONG GdipGetFontUnit IN GDIPLUS LONG curFont, LONG @unit
      DECLARE LONG GdipGetFontHeight IN GDIPLUS LONG curFont, LONG graphics, SINGLE @Height
      DECLARE LONG GdipGetFontHeightGivenDPI IN GDIPLUS LONG curFont, SINGLE dpi, SINGLE
      @Height
      DECLARE LONG GdipGetLogFontA IN GDIPLUS LONG curFont, LONG graphics, LOGFONTA @lfont
      DECLARE LONG GdipGetLogFontW IN GDIPLUS LONG curFont, LONG graphics, LOGFONTW @lfont
      DECLARE LONG GdipNewInstalledFontCollection IN GDIPLUS LONG @fontCollection
      DECLARE LONG GdipNewPrivateFontCollection IN GDIPLUS LONG @fontCollection
      DECLARE LONG GdipDeletePrivateFontCollection IN GDIPLUS LONG @fontCollection
      DECLARE LONG GdipGetFontCollectionFamilyCount IN GDIPLUS LONG fontCollection, LONG
      @numFound
      DECLARE LONG GdipGetFontCollectionFamilyList IN GDIPLUS LONG fontCollection, LONG
      numSought, LONG @gpfamilies, LONG @numFound
      DECLARE LONG GdipPrivateAddFontFile IN GDIPLUS LONG fontCollection, STRING FilName
      DECLARE LONG GdipPrivateAddMemoryFont IN GDIPLUS LONG fontCollection, LONG memory,
      LONG length
      *!* String
      DECLARE LONG GdipDrawString IN GDIPLUS LONG graphics, STRING str, LONG length, LONG
      thefont, STRING @layoutRect, LONG StringFormat, LONG brush
      DECLARE LONG GdipMeasureString IN GDIPLUS LONG graphics, STRING str, LONG length,
      LONG thefont, STRING @layoutRect, LONG StringFormat, STRING @boundingBox, LONG @codepointsFitted,
      LONG @linesFilled
      DECLARE LONG GdipMeasureCharacterRanges IN GDIPLUS LONG graphics, STRING str, LONG
      length, LONG thefont, STRING @layoutRect, LONG StringFormat, LONG regionCount, LONG
      @regions
      DECLARE LONG GdipDrawDriverString IN GDIPLUS LONG graphics, STRING st
    • #3050189

      RSS 2.0 and VFP

      by craigaaa3 ·

      In reply to The SPS Weblog

      Ken Levy mentioned out on the UT yesterday that it would be a cool
      VFP open source project to create a table that RSS could be imported into and the
      exported out of. I thought it was an excellent idea. So, I played around with
      RSS 2.0 last night. After more than a little reading on the specifications for RSS
      2.0, and some trial and error, I was able to create a workable XML schema (XSD) for
      RSS 2.0. When I say workable, I mean I wanted it to work with VFP’s XMLAdapter
      class. I’ll be working on the other RSS schemas as time permits.

      Below is a runnable example using the new schema and pulling RSS
      2.0 sample content from:
      http://media-cyber.law.harvard.edu/blogs/gems/tech/rss2sample.xml

      It’s a lot of code, but most of it is the XML schema, and that could
      be placed in a file to be used as the XMLAdapter’s schema. I just wanted to provide
      an example here that runs right out of the box with a copy of VFP 9 and an internet
      connetction. Have fun! (I’ll quit getting side-tracked and get back to Emal and VFP
      shortly)

      LOCAL loXMLAdapter, loBrowser, lcXSD, lcRSSContent,
      lcXMLHeader, lcXMLFooter

      lcXMLHeader = GetHeader()
      lcXSD = VFPRSS2Schema()
      lcRSSContent = RetrieveRSS(“
      http://media-cyber.law.harvard.edu/blogs/gems/tech/rss2sample.xml“)
      lcXMLFooter = GetFooter()

      oXMLAdapter = NEWOBJECT(‘XMLAdapter’)
      oXMLAdapter.LOADXML(lcXMLHeader + lcXSD + lcRSSContent + lcXMLFooter)

      CLOSE DATABASES ALL
      oXMLAdapter.TABLES(1).TOCURSOR && Cloud
      oXMLAdapter.TABLES(2).TOCURSOR && Image
      oXMLAdapter.TABLES(3).TOCURSOR && Textinput
      oXMLAdapter.TABLES(4).TOCURSOR && Enclosure
      oXMLAdapter.TABLES(5).TOCURSOR && Item
      oXMLAdapter.TABLES(6).TOCURSOR && Channel
      SET

      *****************************
      FUNCTION GetHeader()
      *****************************
       LOCAL lcHeader
       TEXT TO lcHeader NOSHOW
      <?xml version=”1.0″ encoding=”utf-8″ ?>
      <VFPDataSet>
       ENDTEXT
       RETURN lcHeader
      ENDFUNC

      *****************************
      FUNCTION GetFooter()
      *****************************
       LOCAL lcFooter
       TEXT TO lcFooter NOSHOW
      </VFPDataSet>
       ENDTEXT
       RETURN lcFooter
      ENDFUNC

      *****************************
      FUNCTION VFPRSS2Schema()
      *****************************
       LOCAL lcXML
       TEXT TO lcXML NOSHOW
      <xsd:schema id=”VFPDataSet” xmlns:xsd=”
      http://www.w3.org/2001/XMLSchema
      xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata”>
       <xsd:element name=”VFPDataSet” msdata:IsDataSet=”true”>
        <xsd:complexType>
         <xsd:choice maxOccurs=”unbounded”>
         <xsd:element name=”channel”>
          <xsd:complexType>
           <xsd:sequence>
            <xsd:element name=”title” minOccurs=”1″ maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”link” minOccurs=”1″ maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”description” minOccurs=”1″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”language” minOccurs=”0″
      maxOccurs=”1″  default=”en-us”>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”copyright” minOccurs=”0″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”managingEditor” minOccurs=”0″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”webMaster” minOccurs=”0″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”pubDate” minOccurs=”0″ maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”lastBuildDate” minOccurs=”0″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”category” minOccurs=”0″
      maxOccurs=”unbounded”>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”generator” minOccurs=”0″
      maxOccurs=”1″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”docs” default=”
      http://blogs.law.harvard.edu/tech/rss“>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”cloud”>
             <xsd:complexType>
              <xsd:sequence>
               <xsd:element name=”domain”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:string”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”port”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:integer”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”path”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:string”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”registerProcedure”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:string”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”protocol”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:string”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
              </xsd:sequence>
             </xsd:complexType>
            </xsd:element>
            <xsd:element name=”ttl”>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:integer”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”image”>
             <xsd:complexType>
              <xsd:sequence>
               <xsd:element name=”url” minOccurs=”1″
      maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:anyURI”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”title”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:string”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”link”
      minOccurs=”1″ maxOccurs=”1″>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:anyURI”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”width”
      default=”88″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:decimal”>
                  <xsd:maxInclusive
      value=”144″></xsd:maxInclusive>
                  <xsd:minInclusive
      value=”0″></xsd:minInclusive>
                  <xsd:fractionDigits
      value=”0″></xsd:fractionDigits>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”height”
      default=”31″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:decimal”>
                  <xsd:maxInclusive
      value=”400″></xsd:maxInclusive>
                  <xsd:minInclusive
      value=”0″></xsd:minInclusive>
                  <xsd:fractionDigits
      value=”0″></xsd:fractionDigits>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”description”>
                 <xsd:simpleType>
                  <xsd:restriction
      base=”xsd:anyURI”>
                  </xsd:restriction>
                 </xsd:simpleType>
               </xsd:element>
              </xsd:sequence>
             </xsd:complexType>
            </xsd:element>
            <xsd:element name=”rating”>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”textInput”>
             <xsd:complexType>
              <xsd:sequence>
               <xsd:element name=”title”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”description”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”name”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”link”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:anyURI”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
              </xsd:sequence>
             </xsd:complexType>
            </xsd:element>
            <xsd:element name=”skipHours” minOccurs=”0″
      maxOccurs=”24″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”skipDays” minOccurs=”0″
      maxOccurs=”7″>
             <xsd:simpleType>
              <xsd:restriction base=”xsd:string”>
              </xsd:restriction>
             </xsd:simpleType>
            </xsd:element>
            <xsd:element name=”item”>
             <xsd:complexType>
              <xsd:sequence>
               <xsd:element name=”title”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”link”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”description”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”author”
      minOccurs=”0″ maxOccurs=”1″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”category”
      minOccurs=”0″ maxOccurs=”unbounded”>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”comments”
      minOccurs=”0″ maxOccurs=”1″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:anyURI”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”enclosure”>
                <xsd:complexType>
                 <xsd:sequence>
                  <xsd:element
      name=”url” minOccurs=”1″ maxOccurs=”1″>
                   <xsd:simpleType>
                    <xsd:restriction
      base=”xsd:anyURI”>
                    </xsd:restriction>
                   </xsd:simpleType>
                  </xsd:element>
                  <xsd:element
      name=”length” minOccurs=”1″ maxOccurs=”1″>
                   <xsd:simpleType>
                    <xsd:restriction
      base=”xsd:integer”>
                    </xsd:restriction>
                   </xsd:simpleType>
                  </xsd:element>
                  <xsd:element
      name=”type” minOccurs=”1″ maxOccurs=”1″>
                   <xsd:simpleType>
                    <xsd:restriction
      base=”xsd:string”>
                    </xsd:restriction>
                   </xsd:simpleType>
                  </xsd:element>
                 </xsd:sequence>
                </xsd:complexType>
               </xsd:element>
               <xsd:element name=”guid”
      minOccurs=”0″ maxOccurs=”1″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                 <!–
                  <xsd:attribute
      name=”isPermaLink” type=”xs:boolean” default=”true”></xsd:attribute>
                 –>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”pubDate”
      minOccurs=”0″ maxOccurs=”1″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
               <xsd:element name=”source”
      minOccurs=”0″ maxOccurs=”1″>
                <xsd:simpleType>
                 <xsd:restriction
      base=”xsd:string”>
                 </xsd:restriction>
                </xsd:simpleType>
               </xsd:element>
              </xsd:sequence>
             </xsd:complexType>
            </xsd:element>
           </xsd:sequence>
          <xsd:attribute name=”version” default=”2.0″></xsd:attribute>
          </xsd:complexType>
         </xsd:element>
         </xsd:choice>
        </xsd:complexType>
       </xsd:element>
      </xsd:schema>
       ENDTEXT
       RETURN lcXML
      ENDFUNC

      *****************************
      FUNCTION RetrieveRSS(tcURL)
      *****************************
       #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
       #DEFINE SYNCHRONOUS 0
       #DEFINE INTERNET_FLAG_RELOAD 2147483648

       DECLARE INTEGER InternetOpen IN WININET STRING
      Agent, ;
        INTEGER AccessType, STRING ProxyName, ;
        STRING ProxyBypass, INTEGER Flags

       DECLARE INTEGER InternetOpenUrl IN WININET ;
        INTEGER hInternetSession, STRING Url, STRING Header, ;
        INTEGER HeaderLength, INTEGER Flags, INTEGER Context

       DECLARE INTEGER InternetReadFile IN WININET
      INTEGER file, ;
        STRING @Buffer, INTEGER NumberOfBytesToRead, INTEGER @BytesRead

       DECLARE SHORT InternetCloseHandle IN WININET
      INTEGER hInst

       LOCAL lcAgent, lhInternetSession, lhFile, llOK,
      lnReturn, lcReadBuffer, lnBytesRead, lcRetVal

       lcAgent = “VFP RSS 2.0 Reader”
       lhInternetSession = InternetOpen(lcAgent, INTERNET_OPEN_TYPE_PRECONFIG, “”,
      “”, SYNCHRONOUS)

       IF lhInternetSession = 0
        ? “Problem Encountered: Internet session cannot be established”
       ELSE
        lhFile = InternetOpenUrl( lhInternetSession, tcURL, ”, 0, INTERNET_FLAG_RELOAD,
      0)
        IF lhFile = 0
         ? “Problem Encountered: URL cannot be opened”
        ELSE
         lcRetVal = “”
         llOK = .T.
         
         DO WHILE llOK
          lcReadBuffer = SPACE(1500)
          lnBytesRead = 0
          lnReturn = InternetReadFile(lhFile, @lcReadBuffer, LEN(lcReadBuffer),
      @lnBytesRead)
          IF (lnBytesRead > 0)
           lcRetVal = lcRetVal + LEFT(lcReadBuffer, lnBytesRead)
          ENDIF
          llOK = (lnReturn = 1 AND lnBytesRead > 0)
         ENDDO
         
         InternetCloseHandle(lhFile)
         InternetCloseHandle(lhInternetSession)
         lcRetVal = SUBSTR(lcRetVal, ATC(“<channel”, lcRetVal))
         
         RETURN LEFT(lcRetVal, ATC(“</channel>”, lcRetVal) + 9)
        ENDIF
       ENDIF
       RETURN “”
      ENDFUNC

      UPDATES: Fixed malformed html in entry


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050188

      Email and VFP: Part 1i (EsSmtp)

      by craigaaa3 ·

      In reply to The SPS Weblog

      As we’ve seen in the previous entries, emailing from VFP can be done in a variety
      of ways.  In this entry, I explore the use of a freely avaliable ActiveX control,
      simply known as EsSmtp.  This control was once sold commercially by Eurosource,
      but now resides on SourceForge
      It’s not only free, it’s open source (you get the source code). There’s quite a few
      controls available, but the only one I am currently familiar with is EsSmtp.

      You’ll need to download and register this control in order for this example to work. 
      You can Download
      it here
      .  And, additional information about the properties and methods of
      the control can be found here.

      Okay, without taking up anymore precious time, here’s the code.

      *******************************
      *!* Example of using SendViaEsSmtp
      *******************************
      DIMENSION aryAttach(2)
      aryAttach(1) = “C:\attachment1.txt” && change to an actual file that exists
      on your computer
      aryAttach(2) = “C:\attachment2.zip” && change to an actual file that exists
      on your computer

      LOCAL lcFromName, lcFromAddress, lcTo, lcSubject,
      lcBody, lcCC, lcBCC, lcSMTPServer, lcErrReturn

      lcFromName = “My Name”
      lcFromAddress = “
      me@myhost.com
      lcTo = “
      someone@theirhost.com
      lcSubject = “Hey Have You Tried VFP Email?”
      lcBody = “Just wanted to let you know that VFP is pretty versatile and has a lot of
      ways to send email.”
      lcCC = “
      someoneelse@someotherhost.com
      lcBCC = “
      myboss@bosshost.com
      lcSMTPServer = “mail.myhost.com”

      SendViaEsSmtp(@lcErrReturn, lcFromName, lcFromAddress,
      lcTo, lcSubject, lcBody, @aryAttach, lcCC, lcBCC, lcSMTPServer)

      IF EMPTY(lcErrReturn)
       MESSAGEBOX(“‘” + lcSubject + “‘ sent successfullly.”, 64, “Send email via EsSmtp”)
      ELSE
       MESSAGEBOX(“‘” + lcSubject + “‘ failed to be sent.  Reason:” + CHR(13)
      + lcErrReturn, 64, “Send email via EsSmtp”)
      ENDIF

      *******************************************
      PROCEDURE SendViaEsSmtp(tcReturn, tcFromName, tcFromAddress, tcTo, tcSubject, tcBody,
      taFiles, tcCC, tcBCC, tcSMTPSever)
      *******************************************
       LOCAL loEsSmtp, lnCountAttachments, lnErrorNo
       TRY
        loEsSmtp = CREATEOBJECT(“ESSMTP.EsSmtpCtrl.1”)
        WITH loEsSmtp
         IF TYPE(“tcSMTPSever”) = “C”
          .SMTPServer = tcSMTPSever
         ENDIF   
         IF TYPE(“tcFromName”) = “C”
          .SourceName = tcFromName
         ENDIF
         IF TYPE(“tcFromAddress”) = “C”
          .SourceAddress = tcFromAddress
         ENDIF
         .DestinationAddress = tcTo
         IF TYPE(“tcCC”) = “C”
          .CCDestinationAddress = tcCC
         ENDIF
         IF TYPE(“tcBCC”) = “C”
          .BCCDestinationAddress = tcBCC
         ENDIF
         .Subject = tcSubject
         .MailData = tcBody
         IF TYPE(“taFiles”, 1) = “A”
          FOR lnCountAttachments = 1 TO ALEN(taFiles)
           .AddAttachment(taFiles(lnCountAttachments), 0) &&
      0 signifies base64 encoding when needed
          ENDFOR
         ENDIF
         IF .SendMail() != 1 && there was a problem
          lnErrorNo = .ErrorNo
          DO CASE
           CASE lnErrorNo = 421
            THROW “Service not available, closing transmission
      channel”
           CASE lnErrorNo = 450
            THROW “Requested mail action not taken: mailbox
      unavailable [E.g., mailbox busy]”
           CASE lnErrorNo = 451
            THROW “Requested action aborted: local error in
      processing”
           CASE lnErrorNo = 452
            THROW “Requested action not taken: insufficient
      system storage”
           CASE lnErrorNo = 500
            THROW “Syntax error, command unrecognized [This
      may include errors such as command line too long]”
           CASE lnErrorNo = 501
            THROW “Syntax error in parameters or arguments”
           CASE lnErrorNo = 502
            THROW “Command not implemented”
           CASE lnErrorNo = 503
            THROW “Bad sequence of commands”
           CASE lnErrorNo = 504
            THROW “Command parameter not implemented”
           CASE lnErrorNo = 550
            THROW “Requested action not taken: mailbox unavailable
      [E.g., mailbox not found, no access]”
           CASE lnErrorNo = 552
            THROW “Requested mail action aborted: exceeded
      storage allocation”
           CASE lnErrorNo = 553
            THROW “Requested action not taken: mailbox name
      not allowed [E.g., mailbox syntax incorrect]”
           CASE lnErrorNo = 554
            THROW “Transaction failed”
           OTHERWISE
            THROW “Unknown Error – Might be WinSock Related”
           ENDCASE
         ENDIF
        ENDWITH

       CATCH TO loError
        tcReturn = [Error: ] + STR(loError.ERRORNO) + CHR(13) + ;
         [LineNo: ] + STR(loError.LINENO) + CHR(13) + ;
         [Message: ] + loError.MESSAGE + CHR(13) + ;
         [Procedure: ] + loError.PROCEDURE + CHR(13) + ;
         [Details: ] + loError.DETAILS + CHR(13) + ;
         [StackLevel: ] + STR(loError.STACKLEVEL) + CHR(13) + ;
         [LineContents: ] + loError.LINECONTENTS
       FINALLY
        RELEASE loEsSmtp
        loEsSmtp = .NULL.
       ENDTRY
      ENDPROC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050187

      ATOM and VFP

      by craigaaa3 ·

      In reply to The SPS Weblog

      I wanted to do RSS 2.0 first given that it has the most momentum at the moment, but
      that’s hardly the only accepted syndication format. Here’s the formats and the players
      involved (consider it the abridged, highlights-only history of syndication by
      yours truly)….

      • RSS 0.9 : Netscape/Dan Libby (considered obsolete and too complex by most – RDF specification
        based – Netscape dropped out of the game about the time the simplified version 0.91
        was proposed, big mistake – RSS stands for “RDF Site Summary”)
      • RSS 0.91 : Netscape/Dan Libby (never got off the ground – it is argued
        by some that this didn’t even constitute a version… but it’s documented, but it
        is analogous to Visual FoxPro version 4… you hear about people who have the beta,
        but never really seen it.)
      • RSS 0.91 : UserLand Software/Dave Winer (officially
        obsoleted by RSS 2.0 – UserLand picks up the ball and runs with it – RSS stands for
        Rich Site Summary“)
      • RSS 0.92 : UserLand Software (officially obsoleted by RSS 2.0)
      • RSS 0.93 : UserLand Software (officially obsoleted by RSS 2.0)
      • RSS 0.94 : UserLand Software (officially obsoleted by RSS 2.0)
      • RSS 1.0 : RSS-DEV Working Group (Active
        – not from 0.94 as you may think, it is actually considered a branch from 0.90 and
        RDF specification based – not affiliated with UserLand Software – RSS stands for “RDF
        Site Summary
        “)
      • RSS 2.0 : UserLand Software (Active – next generation taking over where 0.94 left
        off – RSS stands for “Really Simple Syndication“)
      • ATOM 0.1-1.0 IETF Atom Publishing Format
        and Protocol (atompub) Working Group. (Active – entirely seperate from all previous
        efforts, IETF didn’t come into the picture until ATOM 0.3, has a very good chance
        of becoming the internet standard for syndication. Note: UserLand/Dave Winer offered
        to merge with ATOM in 2004, ATOM has so far declined the offer. Work on the specification
        is on-going and affectionately referred to as the ATOM
        Project
        )

      My blog offers RSS 2.0 and ATOM 0.2 syndication, so here’s the code to grab ATOM into
      Visual FoxPro tables via a schema and the XMLAdapter (I need to dig into the ATOM
      1.0 specification before I can do a more thorough job, but this is a good start)…

      LOCAL loXMLAdapter, loBrowser, lcXSD, lcATOMContent,
      lcXMLHeader, lcXMLFooter

      lcXMLHeader = GetHeader()
      lcXSD = VFPATOMSchema()

      *!* Atom .02 feed, need to dig into 1.0 specification
      http://ietfreport.isoc.org/idref/draft-ietf-atompub-format/

      lcATOMContent = RetrieveATOM(“http://www.sweetpotatosoftware.com/SPSBlog/SyndicationServiceExperimental.asmx/GetAtom“)
      lcXMLFooter = GetFooter()

      oXMLAdapter = NEWOBJECT(‘XMLAdapter’)

      oXMLAdapter.LOADXML(lcXMLHeader + lcXSD+ lcATOMContent
      + lcXMLFooter)

      CLOSE DATABASES ALL
      oXMLAdapter.TABLES(1).TOCURSOR && Generator
      oXMLAdapter.TABLES(2).TOCURSOR && Author
      oXMLAdapter.TABLES(3).ToCursor && Entry
      oXMLAdapter.TABLES(4).ToCursor && Feed
      SET

      *****************************
      FUNCTION GetHeader()
      *****************************
       LOCAL lcHeader
       TEXT TO lcHeader NOSHOW
      <?xml version=”1.0″ encoding=”utf-8″ ?>
      <VFPDataSet>
       ENDTEXT
       RETURN lcHeader
      ENDFUNC

      *****************************
      FUNCTION GetFooter()
      *****************************
       LOCAL lcFooter
       TEXT TO lcFooter NOSHOW
      </VFPDataSet>
       ENDTEXT
       RETURN lcFooter
      ENDFUNC

      *****************************
      FUNCTION VFPATOMSchema()
      *****************************
       LOCAL lcXML
      *!* Use bare minimum abbreviated notation to show all that is necessary
      TEXT TO lcXML NOSHOW
      <xsd:schema xmlns:tns=”
      http://purl.org/atom/ns#”
      attributeFormDefault=”unqualified” elementFormDefault=”qualified” targetNamespace=”
      http://purl.org/atom/ns#”
      xmlns:xsd=”
      http://www.w3.org/2001/XMLSchema“>
        <xsd:import namespace=”
      http://www.w3.org/XML/1998/namespace
      />
        <xsd:element name=”feed”>
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name=”title” type=”xsd:string”
      />
              <xsd:element name=”link” type=”xsd:string”
      />
              <xsd:element name=”modified” type=”xsd:dateTime”
      />
              <xsd:element name=”tagline” type=”xsd:string”
      />
              <xsd:element name=”generator”>
                <xsd:complexType>
                  <xsd:simpleContent>
                    <xsd:extension
      base=”xsd:string”>
                     
      <xsd:attribute name=”name” type=”xsd:string” use=”required” />
                    </xsd:extension>
                  </xsd:simpleContent>
                </xsd:complexType>
              </xsd:element>
              <xsd:element name=”author”>
                <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element
      name=”name” type=”xsd:string” />
                  </xsd:sequence>
                </xsd:complexType>
              </xsd:element>
              <xsd:element maxOccurs=”unbounded” name=”entry”>
                <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element
      name=”title” type=”xsd:string” />
                    <xsd:element
      name=”link” type=”xsd:string” />
                    <xsd:element
      name=”id” type=”xsd:string” />
                    <xsd:element
      name=”issued” type=”xsd:dateTime” />
                    <xsd:element
      name=”modified” type=”xsd:dateTime” />
                    <xsd:element
      name=”created” type=”xsd:dateTime” />
                    <xsd:element
      name=”content” type=”xsd:string” />
                  </xsd:sequence>
                </xsd:complexType>
              </xsd:element>
            </xsd:sequence>
            <xsd:attribute name=”version” type=”xsd:decimal”
      use=”required” />
          </xsd:complexType>
        </xsd:element>
      </xsd:schema>
      ENDTEXT
       RETURN lcXML
      ENDFUNC

      *****************************
      FUNCTION RetrieveATOM(tcURL)
      *****************************
       #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
       #DEFINE SYNCHRONOUS 0
       #DEFINE INTERNET_FLAG_RELOAD 2147483648

       DECLARE INTEGER InternetOpen IN WININET STRING
      Agent, ;
        INTEGER AccessType, STRING ProxyName, ;
        STRING ProxyBypass, INTEGER Flags

       DECLARE INTEGER InternetOpenUrl IN WININET ;
        INTEGER hInternetSession, STRING Url, STRING Header, ;
        INTEGER HeaderLength, INTEGER Flags, INTEGER Context

       DECLARE INTEGER InternetReadFile IN WININET
      INTEGER file, ;
        STRING @Buffer, INTEGER NumberOfBytesToRead, INTEGER @BytesRead

       DECLARE SHORT InternetCloseHandle IN WININET
      INTEGER hInst

       LOCAL lcAgent, lhInternetSession, lhFile, llOK,
      lnReturn, lcReadBuffer, lnBytesRead, lcRetVal

       lcAgent = “VFP ATOM 0.2 Reader”
       lhInternetSession = InternetOpen(lcAgent, INTERNET_OPEN_TYPE_PRECONFIG, “”,
      “”, SYNCHRONOUS)

       IF lhInternetSession = 0
        ? “Problem Encountered: Internet session cannot be established”
       ELSE
        lhFile = InternetOpenUrl( lhInternetSession, tcURL, ”, 0, INTERNET_FLAG_RELOAD,
      0)
        IF lhFile = 0
         ? “Problem Encountered: URL cannot be opened”
        ELSE
         lcRetVal = “”
         llOK = .T.
         
         DO WHILE llOK
          lcReadBuffer = SPACE(1500)
          lnBytesRead = 0
          lnReturn = InternetReadFile(lhFile, @lcReadBuffer, LEN(lcReadBuffer),
      @lnBytesRead)
          IF (lnBytesRead > 0)
           lcRetVal = lcRetVal + LEFT(lcReadBuffer, lnBytesRead)
          ENDIF
          llOK = (lnReturn = 1 AND lnBytesRead > 0)
         ENDDO
         
         InternetCloseHandle(lhFile)
         InternetCloseHandle(lhInternetSession)
         lcRetVal = SUBSTR(lcRetVal, ATC(“<feed”, lcRetVal))
         
         RETURN LEFT(lcRetVal, ATC(“</feed>”, lcRetVal) + 9)
        ENDIF
       ENDIF
       RETURN “”
      ENDFUNC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050186

      Visual Basic to Visual FoxPro Conversion Utility

      by craigaaa3 ·

      In reply to The SPS Weblog

      Visual Basic (versions 6 and below) code examples are everywhere. It’s a huge
      resource that many Visual FoxPro developers utilize, but converting a Visual Basic
      example to Visual FoxPro is, more often than not, a pain. It’s the same thing over
      and over again… change dims to locals, change msgbox to messagebox, add parenthesis
      around the procedure calls, etc., etc., ad nauseam.

      As a programmer who develops in Visual Basic as well as Visual FoxPro, I was
      intrigued when, about a year ago on Tek-Tips, William GC Steinford offered the
      idea of a Visual Basic to Visual FoxPro converter. I decided it was a great idea and
      created my own. It is driven from a conversion table (of course), and handles most
      of the basic things that need to be changed when porting Visual Basic code to Visual
      FoxPro.

      I’ve used it internally for awhile now, and it is a real time saver. Now, bear
      in mind that I’m not putting on a code clinic with this thing (like I said, I was
      just using it internally for some down and dirty conversions), but it’s functional
      and new vb to vfp syntax conversions can be added to the program just by adding records
      in the conversion.dbf. There are a couple of extra fields in that table as well
      that are reserved for future use (they will be used for such things as converting
      API Declare statements properly and such – basically anything that can’t be done in
      one pass through the conversion.dbf or needs special handling).

      If you add to the conversion table or the program, I would really appreciate
      it
      if you would email me the changes. I would like to incorporate any useful
      changes with my own, and continue to offer them back to the Visual FoxPro community.
      Other than that, feel free to use it however or whenever you see fit.

      A sample Visual Basic .BAS file has been included in the zip. When you run the vbtovfp.exe
      just click the ellipsis button […] and select the vbsample.bas file to open it in
      the conversion utility. Here’s a screen shot of vbtovfp and you can download vbtovfp
      here (source included)
      .

      Note: Originally written in VFP 7, but ported to VFP 9 – so, you will need VFP 9 to
      run this (or take the time to take out the VFP 9-only features and recompile it in
      whatever VFP you got). Also, there is selection/right-click functionality with the
      editboxes you’ll want to explore.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050185

      Craig Bailey and VFP Solution Explorer

      by craigaaa3 ·

      In reply to The SPS Weblog

      If you’re like me and didn’t have a clue that something called the “VFP Solution
      Explorer” was being worked on, check out Craig
      Bailey’s most recent blog entry
      . I downloaded the presentation,
      and I can’t say enough good things about what I saw and read. If the “VFP Solution
      Explorer” and it’s lofty goals are carried out in a timely fashion, then I suspect
      that a great many of us could be ditching Visual FoxPro’s project manager in the not
      too distant future.

      This is exactly the kind of project that I was speaking of in my
      last post
      . I hope that Scott Scovell and Craig Bailey make the release sooner
      rather than later, because I suspect there are plenty of experienced Visual FoxPro
      developers, I can think of at least one right now, that would be willing to contribute
      to this worthwhile goal/project.

      To Scott Scovell and Craig Bailey, I say, “Keep up the good work and be sure
      to give me another heads up when you’ve released the beta. I’ll take an alpha if you
      decide to reconsider.”


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050184

      Visual FoxPro Community Action

      by craigaaa3 ·

      In reply to The SPS Weblog

      A Call to Action
      While bemoaning its state, speculating as to an uncertain future or
      even impending doom, whining about the lack of product marketing from Microsoft, tearing
      down the IDE, and focusing, to the point of exhaustion, on the deficiencies
      in the product known as Visual FoxPro might improve a developer’s mental health for
      the moment (letting off steam can be a good thing), it does little to address the
      problems at hand. I am infinitely surprised at the tendency of otherwise solution
      oriented, brilliant individuals to waste their time on a myriad of ineffectual
      methods when it comes to pushing Visual FoxPro forward and beyond. I am equally surprised to
      see so much in-depth problem analysis result in little more than “so much in-depth
      problem analysis“.

      To Be Clear
      Now, just so we’re clear… I’m not saying that there isn’t a basis for some
      of the fears or complaints surrounding/leveled against Visual FoxPro. Neither
      am I saying that one should not voice their disapproval when real-world problems exist
      and criticism is warranted. My contention is merely that, once the problems have been
      suitably identified, one could/should do more than throw words at them. This is especially
      true when it comes to Visual FoxPro.

      What Can Be Done
      These problems beg the question, “What can be done?”. Not long
      after the question is spoken, the defeatists throw their hands up in the air and answer,
      “Nothing!”. This answer is usually followed by some identification
      of the parties directly responsible for the developer’s inability to do anything;
      more often than not, Microsoft is included in the list. However, the reaction to this
      question is quite different in the minds of scores of other Visual FoxPro developers.
      Visions begin to whirl around in the ether, slowly solidifying into concrete ideas
      of what could/should be. This mindset, coupled with an enterprising, can-do spirit,
      is directly responsible for more than a few of the solutions to problems past, and
      it is my firm contention that the future of Visual FoxPro has a lot more to do with
      the Visual FoxPro Community’s action, or lack thereof, than anything the folks in
      Redmond may be up to. So, here is my list of solutions, that are either being done
      or could be done.

      Marketing:
      Harness all the energy that is currently going into pointing out the deficiencies
      in this area (for the 1 millionth time), and direct it into more weblogs and websites
      with good Visual FoxPro related content. If you don’t have a weblog, but have
      some insights, code, or Visual FoxPro related solutions you’d like to share…
      get one. Start blogging about the advantages of Visual FoxPro and solutions created
      with it. There are countless places on the internet to sign-up for, and start, your
      very own weblog for free. Here are a few resources:
      http://weblogs.foxite.com/

      http://www.blogger.com/start

      http://www.myblogsite.com/index.shtml

      If you already have a webserver and would like to create your own blog, then give dasBlog or .Text a
      look. This blog runs on the dasBlog engine, and many of the blogs listed in my Blogroll
      are using .Text. (Blogroll is over there —->)

      Also, there are some really good forums/boards on the internet that you should consider
      becoming an active member of. These forums/boards spread the good word and help countless
      Visual FoxPro developers across the globe. One of the best kinds of marketing for
      a product is support, and the Visual FoxPro Community supports its product like no
      other. Here are a few forums I recommend:
      http://www.universalthread.com

      http://www.tek-tips.com

      http://fox.wikis.com

      http://www.foxite.com

      http://forums.microsoft.com/msdn/ShowForum.aspx?ForumID=60

      http://community.compuserve.com/n/pfx/forum.aspx?webtag=ws-msdevapps

      Have you created a great Visual FoxPro 9 application? Then write a case study on it,
      and have it included on the Microsoft site for all to see. There have been repeated
      calls for Visual FoxPro case studies
      by Ken Levy and other members of the Visual
      FoxPro Community. I had the pleasure of editing one recently, and it was
      a rewarding experience.

      If you’re a decent writer, then crank out some articles for the industry rags
      (such as FoxTalk 2.0 and FoxPro
      Advisor
      ) or write a book.

      The action of creating, supporting, and ultimately cultivating Visual FoxPro internet
      resources has a direct impact on the visibility of Visual FoxPro and its perceived
      value. Unfortunately, the same cannot be said for the countless campaigns and posts
      cajoling or criticizing Microsoft.

      Language Improvements:
      Submit ideas to one of the many Visual FoxPro wish lists that are certainly
      seen by the MS Fox Team. Here is one such list: http://fox.wikis.com/wc.dll?Wiki~VFPVersion10WishList.

      If you have a penchant for C/C++, then create an FLL containing the new functions
      and thrust it into the Public Domain for use by Visual FoxPro developers everywhere.
      If you don’t have any ideas on what might make a good FLL function for Visual Foxpro,
      check the wish lists.

      If all else fails, then create ingenious Visual FoxPro functions and procedures in
      Visual FoxPro that can be reused by developers in their applications. All of these
      actions have had and will continue to have a direct, positive impact on Visual FoxPro.

      Integrated Design Environment Improvements:

      Create Visual FoxPro components that increase developer production and otherwise add
      value to the Visual FoxPro IDE. There is an immense amount of untapped potential in
      this area. More than a few of the components we use every day in Visual FoxPro are
      the result of hardworking Visual FoxPro developers that lived and breathed this solution.
      For a few examples see the following: http://fox.wikis.com/wc.dll?Wiki~VFPComponentAuthors.

      On a personal note, after having read about Craig Berntson’s idea for a Solution
      Manager
      , I’ve been giving this idea a lot of thought. I think something like
      the Solution Explorer in VS would serve Visual FoxPro developers well. Envision, for
      starters, the ability to access multiple projects with heirarchical drill-downs
      for programs/forms/classes, and having multiple design windows and program
      files open in seperate tabs, and the ability to expand/collapse function and procedure
      calls while editing them.

      However, I digress. The point is, that the action of creating Visual FoxPro components
      for Visual FoxPro has a direct impact on the IDE and increases Visual FoxPro’s overall
      usefulness.

      Improved Interop, Integration and Extensibility
      The MS Fox Team announced that Sedna will
      be highly focused on this area. But, this is no reason to rest on our laurels
      until 2007. Toss around ideas and make suggestions for Sedna on the Universal
      Thread
      in the Sedna category. The Microsoft Fox Team has committed to monitoring
      that category and if only a couple great ideas from there get implemented, it
      will have been well worth it.

      Create code and solutions that developers can use with .NET, Microsoft products such
      as Office, and even ways in which Visual FoxPro can consume and publish XML. These
      are all really big areas of interest to programmers the world over, and showing that
      Visual FoxPro is an excellent choice for these types of solutions is an action that
      will reap untold benefits for the product as a whole. Visual FoxPro is more than capable,
      and this is a huge, virtually untapped area.

      This action results in Visual FoxPro being seen and used as a development environment
      for solutions well outside the box. An increase in features and abilities garnered
      from outside sources is always a good thing. What is Visual FoxPro good for? A lot
      more than one might expect.

      Improve Visual FoxPro Applications
      Visual FoxPro is given a black-eye daily by poorly thought out and implemented
      solutions, applications that look like they are from the early 1990’s, and convoluted
      code that performs sub-standard. If you’re going to develop in Visual FoxPro, then
      do the language proud. Learn how to code and develop applications in an efficient
      and professional manner, avail yourself of the improvements in each successive version
      of Visual Foxpro, and take advantage of proven development/coding methodologies. While
      you’re at it, you might try a little spit and polish on those user interfaces.

      If you’re still having a hard time adjusting from the world of FP to the world of
      VFP, or if you’ve recently come over from another language, then buy a few books and
      make heavy use of the aforementioned online resources related to Visual FoxPro. Remember,
      the @Say is dead and there’s no excuse for creating yet another dated looking
      switch-board application running on spaghetti code that accesses a horribly denormalized
      database.

      This action not only does Visual Foxpro a favor, but your customers as well.

      Purchase or Upgrade to Visual FoxPro 9
      A no brainer. Unless you are strictly prohibited due to finances or job restrictions,
      you need to upgrade to Visual FoxPro 9 as soon as feasibly possible. There’s no greater
      argument you can make to Microsoft for continued Visual FoxPro support than a few
      of your hard earned dollars spent on this worthwhile product. Sign a petition, post
      as many pleas to, or disparaging remarks about, Microsoft as you want, but in
      the end, only this action ensures that Microsoft will extend the Visual FoxPro Roadmap
      come 2007.

      Anything Else that Actually Makes a Difference
      Here’s where I admit that I don’t have all the answers, but I know someone,
      somewhere does. If you’ve got an idea that could improve Visual FoxPro, then you owe
      it to yourself, the product, and the Visual FoxPro Community to take your best shot.
      If the bulk of the Visual FoxPro Community members can move towards a state of Action
      instead of the FUD (Fear, Uncertainty, and Doubt) Reaction, Visual FoxPro and
      the developers that rely on it (not to mention the customers that depend on it) will
      prosper. As a community, we can do more in 1 year than Microsoft could do in 10 to
      improve the state of our beloved product. That’s my two cents anyways.

      UPDATE: 07-27-2005 Fixed grammatical errors and improved some sentence structure
      that was bothering me


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050183

      RSS 2.0 and VFP (revisited)

      by craigaaa3 ·

      In reply to The SPS Weblog

      OK, I’ve tried a number of different ways to get around handling additional elements
      that aren’t in the RSS 2.0 specification (such as trackback:ping, wfw:rssComments,
      slash:comments, etc. – basically anything using QName).  First, I started with
      the way you are supposed to do it, referencing and importing namespaces, creating
      seperate xsd schemas and the using the ref attribute… that didn’t work. So
      then I started hacking the document by adding the namespace to the elements of the
      XML on the fly, that didn’t work either.

      I’ve created a paired down version of my earlier schema (for testing purposes) that
      will grab the RSS 2.0 feed from the SPS Blog, but the hack is atrocious (look at the
      UndeclaredNamespace procedure). No matter what I try, I can’t get MSXML4 and the XMLAdapter
      to behave and bring in those elements (with their content) without the hack.
      Anyone got any ideas, or better yet, solutions? I hope I’m missing something
      here and that it isn’t a problem with MSXML4 with no workaround.

      LOCAL loXMLAdapter, loBrowser, lcXSD, lcRSSContent,
      lcXMLHeader, lcXMLFooter

      lcXMLHeader = GetHeader()
      lcXSD = VFPRSS2Schema()
      lcRSSContent = RetrieveRSS(“
      http://www.sweetpotatosoftware.com/SPSBlog/SyndicationService.asmx/GetRss“)
      UndeclaredNamespace(@lcRSSContent)
      lcXMLFooter = GetFooter()

      oXMLAdapter = NEWOBJECT(‘XMLAdapter’)

      oXMLAdapter.LOADXML(lcXMLHeader + lcXSD+ lcRSSContent
      + lcXMLFooter)

      CLOSE DATABASES ALL
      oXMLAdapter.TABLES(1).TOCURSOR && Item
      oXMLAdapter.TABLES(2).TOCURSOR && Channel
      oXMLAdapter.TABLES(3).TOCURSOR && Rss
      SET

      *****************************
      FUNCTION GetHeader()
      *****************************
       LOCAL lcHeader
       TEXT TO lcHeader NOSHOW
      <?xml version=”1.0″ encoding=”utf-8″ ?>
      <VFPDataSet>
       ENDTEXT
       RETURN lcHeader
      ENDFUNC

      *****************************
      FUNCTION GetFooter()
      *****************************
       LOCAL lcFooter
       TEXT TO lcFooter NOSHOW
      </VFPDataSet>
       ENDTEXT
       RETURN lcFooter
      ENDFUNC

      *****************************
      PROCEDURE UndeclaredNamespace(tcRSSContent)
      *****************************
         *!* Workaround for MSXML4 – This needs to be worked on still, I can’t
      seem to get these elements even if
         *!* I split up the schemas and use imports and ref in element tag
         *!* However, this workaround at least ensures that it doesn’t blow up
      with “Undeclared Namespace Prefix” error
         *!* while still retrieving the contents. I hate hacks like this, especially
      in this case because these elements aren’t

         *!* part of the specification, but are on many blogs including mine.
         *!* Anyone got a better fix or know how to do this right?
         tcRSSContent = STRTRAN(tcRSSContent, “trackback:ping”, [trackbackping],
      -1, -1, 1)
         tcRSSContent = STRTRAN(tcRSSContent, “pingback:server”, [pingbackserver],
      -1, -1, 1)
         tcRSSContent = STRTRAN(tcRSSContent, “pingback:target”, [pingbacktarget],
      -1, -1, 1)
         tcRSSContent = STRTRAN(tcRSSContent, “wfw:commentRSS”, [wfwcommentRss],
      -1, -1, 1)
         tcRSSContent = STRTRAN(tcRSSContent, “wfw:comment”, [wfwcomment], -1,
      -1, 1)
         tcRSSContent = STRTRAN(tcRSSContent, “slash:comment>”, [slashcomments],
      -1, -1, 1)
      ENDPROC

      *****************************
      FUNCTION VFPRSS2Schema()
      *****************************
       LOCAL lcXML
       TEXT TO lcXML NOSHOW
      <xsd:schema xmlns:xsd=”
      http://www.w3.org/2001/XMLSchema
         xmlns:xsi=”
      http://www.w3.org/2001/XMLSchema-instance

         xmlns:trackback=”
      http://madskills.com/public/xml/rss/module/trackback/
         xmlns:wfw=”
      http://wellformedweb.org/CommentAPI/
         xmlns:slash=”
      http://purl.org/rss/1.0/modules/slash/
         xmlns:pingback=”
      http://madskills.com/public/xml/rss/module/pingback/
        attributeFormDefault=”qualified” elementFormDefault=”qualified” >
        <xsd:element name=”rss”>
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name=”channel”>
                <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element
      name=”title” type=”xsd:string” />
                    <xsd:element
      name=”link” type=”xsd:string” />
                    <xsd:element
      name=”description” type=”xsd:string” />
                    <xsd:element
      name=”copyright” type=”xsd:string” />
                    <xsd:element
      name=”lastBuildDate” type=”xsd:string” />
                    <xsd:element
      name=”generator” type=”xsd:string” />
                    <xsd:element
      name=”managingEditor” type=”xsd:string” />
                    <xsd:element
      name=”webMaster” type=”xsd:string” />
                    <xsd:element
      name=”item”>
                     
      <xsd:complexType>
                       
      <xsd:sequence>
                          
      <xsd:element name=”trackbackping” type=”xsd:string” maxOccurs=”unbounded” />
                          
      <xsd:element name=”pingserver” type=”xsd:string” />
                         
      <xsd:element name=”pingtarget” type=”xsd:string” />
                         
      <xsd:element name=”wfwcomment” type=”xsd:string” />
                         
      <xsd:element name=”wfwcommentRss” type=”xsd:string” />
                         
      <xsd:element name=”slashcomments” type=”xsd:string” />
                         
      <xsd:element name=”title” type=”xsd:string” />
                         
      <xsd:element name=”guid” type=”xsd:string” />
                         
      <xsd:element name=”link” type=”xsd:string” />
                         
      <xsd:element name=”pubDate” type=”xsd:string” />
                         
      <xsd:element name=”description” type=”xsd:string” />
                         
      <xsd:element name=”comments” type=”xsd:string” />
                         
      <xsd:element name=”category” type=”xsd:string” />
                       
      </xsd:sequence>
                     
      </xsd:complexType>
                    </xsd:element>
                  </xsd:sequence>
                </xsd:complexType>
              </xsd:element>
            </xsd:sequence>
            <xsd:attribute name=”version” type=”xsd:decimal”
      use=”required” />
          </xsd:complexType>
        </xsd:element>
      </xsd:schema>
      ENDTEXT
       RETURN lcXML
      ENDFUNC

      *****************************
      FUNCTION RetrieveRSS(tcURL)
      *****************************
       #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
       #DEFINE SYNCHRONOUS 0
       #DEFINE INTERNET_FLAG_RELOAD 2147483648

       DECLARE INTEGER InternetOpen IN WININET STRING
      Agent, ;
        INTEGER AccessType, STRING ProxyName, ;
        STRING ProxyBypass, INTEGER Flags

       DECLARE INTEGER InternetOpenUrl IN WININET ;
        INTEGER hInternetSession, STRING Url, STRING Header, ;
        INTEGER HeaderLength, INTEGER Flags, INTEGER Context

       DECLARE INTEGER InternetReadFile IN WININET
      INTEGER file, ;
        STRING @Buffer, INTEGER NumberOfBytesToRead, INTEGER @BytesRead

       DECLARE SHORT InternetCloseHandle IN WININET
      INTEGER hInst

       LOCAL lcAgent, lhInternetSession, lhFile, llOK,
      lnReturn, lcReadBuffer, lnBytesRead, lcRetVal

       lcAgent = “VFP RSS 2.0 Reader”
       lhInternetSession = InternetOpen(lcAgent, INTERNET_OPEN_TYPE_PRECONFIG, “”,
      “”, SYNCHRONOUS)

       IF lhInternetSession = 0
        ? “Problem Encountered: Internet session cannot be established”
       ELSE
        lhFile = InternetOpenUrl( lhInternetSession, tcURL, ”, 0, INTERNET_FLAG_RELOAD,
      0)
        IF lhFile = 0
         ? “Problem Encountered: URL cannot be opened”
        ELSE
         lcRetVal = “”
         llOK = .T.
         
         DO WHILE llOK
          lcReadBuffer = SPACE(1500)
          lnBytesRead = 0
          lnReturn = InternetReadFile(lhFile, @lcReadBuffer, LEN(lcReadBuffer),
      @lnBytesRead)
          IF (lnBytesRead > 0)
           lcRetVal = lcRetVal + LEFT(lcReadBuffer, lnBytesRead)
          ENDIF
          llOK = (lnReturn = 1 AND lnBytesRead > 0)
         ENDDO
         
         InternetCloseHandle(lhFile)
         InternetCloseHandle(lhInternetSession)
         lcRetVal = SUBSTR(lcRetVal, ATC(“<rss”, lcRetVal))
         
         RETURN LEFT(lcRetVal, ATC(“</rss>”, lcRetVal) + 9)
        ENDIF
       ENDIF
       RETURN “”
      ENDFUNC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050180

      FoxTalk 2.0 GDI+ Article Available Online

      by craigaaa3 ·

      In reply to The SPS Weblog

      Well, the first
      article in my GDI+ series
      for FoxTalk
      2.0
      is available online for free today. Thanks to FoxTalk 2.0 for everything they’ve
      done for me and the rest of the Visual FoxPro Community, especially David Stevenson
      my editor at FoxTalk 2.0. He put in a lot of hard work to make this article possible
      (as I am sure he has done for all the FoxTalk 2.0 articles).

      This first article will take the reader through the basics of drawing on Visual FoxPro
      forms with GDI+ using double-buffering and other techniques that make GDI+ more useable
      for Visual FoxPro developers. It’ll show you how to surmount many of the inherent
      problems developers encounter when rendering graphics on Visual FoxPro forms using
      GDI+.

      Stay tuned for the next articles in the series where I’ll build from this first article
      and delve even further into GDI+ and it’s many uses in Visual FoxPro.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050182

      BindEvent on Steroids

      by craigaaa3 ·

      In reply to The SPS Weblog

      The ability for BindEvent to hook into windows message events in Visual FoxPro 9 is
      great. It is no doubt wrapping the SetWindowLong API
      function somewhere in the source and facilitates the magic by subclassing
      the target window
      . My hat goes off to the Fox Team for coming up with this. But,
      what if you want to modify a messagebox before it appears (such as change the button
      captions and centering it with the form that called it) or what if you want to create
      a Global Keyboard Hook? Basically, what if, as a Visual FoxPro developer, you want
      to take advantage of the SetWindowsHookEx API
      function and all the doors it opens up? Maybe I’m missing something, but BindEvent
      doesn’t seem to be able to do this.

      I’ve got some ideas on things that I want Visual FoxPro to do long before Sedna gets
      here, and some of these ideas require that I am able to use the SetWindowsHookEx. So,
      today I decided to figure out how we (the Visual FoxPro Community) could do this.

      To start this show, here’s an FLL I’ve created using Visual C++ 7.0, that gives
      us two more functions for Visual FoxPro. BindEventEX and UnBindEventEx. Download
      the vfpex.fll here
      . These functions will give you indirect access to SetWindowsHookEx
      for your Visual FoxPro applications/code. There is more to be done, but this is a
      good start for now.

      Then, below are a couple of “cut-n-paste into a prg file and execute” examples
      I worked up in Visual FoxPro that use the vfpex.fll.

      ***************************************************
      *!* MODIFY MESSAGEBOX EXAMPLE
      *!*
      *!* Requires: vfpex.fll
      ***************************************************
      PUBLIC oform1

      oform1=NEWOBJECT(“form1”)
      oform1.Show
      RETURN

      DEFINE CLASS form1 AS form
       Top = 0
       Left = 0
       Height = 259
       Width = 373
       DoCreate = .T.
       Caption = “Using the New BindEventsEx – MessageBox Modification”
       WindowType = 1
       Name = “Form1”

       ADD OBJECT command1 AS commandbutton WITH ;
        Top = 216, ;
        Left = 144, ;
        Height = 27, ;
        Width = 132, ;
        Caption = “R\<un Example”, ;
        Name = “Command1”

       ADD OBJECT command2 AS commandbutton WITH ;
        Top = 216, ;
        Left = 276, ;
        Height = 27, ;
        Width = 84, ;
        Caption = “E\<xit”, ;
        Name = “Command2”

       PROCEDURE wineventhandler
        #DEFINE IDOK   1
        #DEFINE IDCANCEL  2
        #DEFINE IDABORT  3
        #DEFINE IDRETRY  4
        #DEFINE IDIGNORE  5
        #DEFINE IDYES   6
        #DEFINE IDNO   7
        #DEFINE IDCLOSE  8
        #DEFINE IDHELP   9
        #DEFINE IDTRYAGAIN 10
        #DEFINE IDCONTINUE 11
        #DEFINE IDPROMPT 65535

        IF nCode == 5
         SetWindowText(wParam, “VFP – WH_CBT HOOK”) && Title
         SetDlgItemText(wParam, IDPROMPT, “Visual FoxPro BindEventEx Example”)
      && Message
         SetDlgItemText(wParam, IDABORT, “VFP Rocks!”) && First Button
      Caption
         SetDlgItemText(wParam, IDRETRY, “Always Has”) && Second
      Button Caption
         SetDlgItemText(wParam, IDIGNORE, “Always Will”) && Third
      Button Caption

         Thisform.CenterMessageBox(wParam)

         CallNextHookEx(hHook, nCode, wParam, LPARAM) && all 4 variables
      exist
         UnBindEventEx()
         SET LIBRARY TO
        ELSE
         CallNextHookEx(hHook, nCode, wParam, LPARAM) && all 4 variables
      created by FLL
        ENDIF

        RELEASE nCode, wParam, LPARAM, hHook
       ENDPROC

       PROCEDURE buf2dword
        LPARAMETERS tcBuffer
        RETURN Asc(SUBSTR(tcBuffer, 1,1)) + ;

             Asc(SUBSTR(tcBuffer, 2,1)) * 2^8 +;

             Asc(SUBSTR(tcBuffer, 3,1)) * 2^16 +;

             Asc(SUBSTR(tcBuffer, 4,1)) * 2^24
       ENDPROC

       PROCEDURE centermessagebox
        LPARAMETERS tnwParam

        LOCAL lcBuffer, lnMsgLeft, lnMsgTop, lnMsgRight, lnMsgBottom, lnMsgWidth,
      lnMsgHeight

        lcBuffer = REPLI(CHR(0), 2^4)

        =GetWindowRect(tnwParam, @lcBuffer)

        lnMsgLeft = THISFORM.buf2dword(SUBSTR(lcBuffer, 1, 4))
        lnMsgTop = THISFORM.buf2dword(SUBSTR(lcBuffer, 5, 4))
        lnMsgRight = THISFORM.buf2dword(SUBSTR(lcBuffer, 9, 4))
        lnMsgBottom = THISFORM.buf2dword(SUBSTR(lcBuffer, 13, 4))
        lnMsgWidth = lnMsgRight – lnMsgLeft
        lnMsgHeight = lnMsgBottom – lnMsgTop
        lnMsgLeft = THISFORM.LEFT + (THISFORM.WIDTH – lnMsgWidth) / 2
        lnMsgTop = _screen.Top + THISFORM.TOP + (THISFORM.HEIGHT – lnMsgHeight)
      / 2

        MoveWindow(tnwParam, lnMsgLeft, lnMsgTop, lnMsgWidth, lnMsgHeight, .T.)
       ENDPROC

       PROCEDURE Load
        DECLARE INTEGER SetDlgItemText IN user32;
         LONG hDlg,;
         LONG nIDDlgItem,;
         STRING lpString

        DECLARE INTEGER SetWindowText IN user32;
         LONG HWND,;
         STRING  lpString

        DECLARE LONG CallNextHookEx IN user32;
         LONG, LONG, LONG, LONG

        DECLARE INTEGER MoveWindow IN user32;
         INTEGER HWND,;
         INTEGER X,;
         INTEGER Y,;
         INTEGER nWidth,;
         INTEGER nHeight,;
         INTEGER bRepaint

        DECLARE SHORT GetWindowRect IN user32 INTEGER HWND, STRING @ lpRect
       ENDPROC
       
       PROCEDURE command1.Click
        *!* Some of the various Windows Hook constants
        #define WH_MSGFILTER -1
        #define WH_JOURNALRECORD 0
        #define WH_JOURNALPLAYBACK 1
        #define WH_KEYBOARD 2
        #define WH_GETMESSAGE 3
        #define WH_CALLWNDPROC 4
        #define WH_CBT 5 && the one used here
        #define WH_SYSMSGFILTER 6
        #define WH_MOUSE 7
        #define WH_HARDWARE 8
        #define WH_DEBUG 9
        #define WH_SHELL 10
        #define WH_FOREGROUNDIDLE 11
        #define WH_CALLWNDPROCRET 12
        #define WH_KEYBOARD_LL 13
        #define WH_MOUSE_LL 14
        
        *!* Set library so BindEventEx and UnBindEventEx can be used
        *!* in VFP
        SET LIBRARY TO (LOCFILE(ADDBS(JUSTPATH(SYS(16))) + “vfpex.fll”))
        *!* You must have a Named reference to the form or object
        *!* as thisform or this cannot be used with BindEventEx
        BindEventEx(‘oform1.wineventhandler()’, WH_CBT) && SetWindowsHookEx
        *!* This messagebox will be modified before it is shown
        MESSAGEBOX(” “, 2, “”) && Just A Blank Messagebox with Abort,
      Retry, Ignore buttons
       ENDPROC

       PROCEDURE command2.Click
        Thisform.Release()
       ENDPROC

      ENDDEFINE

      ***************************************************
      *!* GLOBAL KEYBOARD HOOK EXAMPLE
      *!*
      *!* Requires: vfpex.fll
      ***************************************************
      PUBLIC oform1

      oform1=NEWOBJECT(“form1”)
      oform1.Show
      RETURN

      DEFINE CLASS form1 AS form

       Top = 0
       Left = 1
       Height = 256
       Width = 454
       DoCreate = .T.
       Caption = “Using the New BindEventsEx – Global Keyboard Hook”
       Name = “form1”

       ADD OBJECT command1 AS commandbutton WITH ;
        Top = 216, ;
        Left = 311, ;
        Height = 27, ;
        Width = 132, ;
        Caption = “R\<un Example”, ;
        Name = “Command1”

       ADD OBJECT edit1 AS editbox WITH ;
        Height = 193, ;
        Left = 11, ;
        ReadOnly = .T., ;
        Top = 12, ;
        Width = 432, ;
        Name = “Edit1”

       PROCEDURE wineventhandler
        LOCAL HookStruct
        *!* Real basic example, just to show it’s possible
        IF wParam = 256 && keydown
         HookStruct = REPLICATE(CHR(0), 20)
         CopyMemory(@Hookstruct, lParam, 20)
         thisform.edit1.value = thisform.edit1.value + Chr(thisform.buf2dword(Hookstruct))
        ENDIF
        CallNextHookEx(hHook, nCode, wParam, lParam) && all 4 variables
      created by FLL
        RELEASE nCode, wParam, LPARAM, hHook
       ENDPROC

       PROCEDURE buf2dword
        LPARAMETERS tcBuffer
        RETURN Asc(SUBSTR(tcBuffer, 1,1)) + ;

             Asc(SUBSTR(tcBuffer, 2,1)) * 2^8 +;

             Asc(SUBSTR(tcBuffer, 3,1)) * 2^16 +;

             Asc(SUBSTR(tcBuffer, 4,1)) * 2^24
       ENDPROC

       PROCEDURE Load         

        DECLARE LONG CallNextHookEx IN user32;
         LONG, LONG, LONG, LONG

        DECLARE RtlMoveMemory IN kernel32 As CopyMemory;

            STRING  @ Destination,;

            INTEGER   Source,;

            INTEGER   nLength 

        SET LIBRARY TO (LOCFILE(“vfpex.fll”, “FLL”))
       ENDPROC

       PROCEDURE Destroy
        *!* Unhook when form is destroyed
        UnBindEventEx()
        SET LIBRARY TO
       ENDPROC

       PROCEDURE command1.Click
        #define WH_MSGFILTER -1
        #define WH_JOURNALRECORD 0
        #define WH_JOURNALPLAYBACK 1
        #define WH_KEYBOARD 2
        #define WH_GETMESSAGE 3
        #define WH_CALLWNDPROC 4
        #define WH_CBT 5
        #define WH_SYSMSGFILTER 6
        #define WH_MOUSE 7
        #define WH_HARDWARE 8
        #define WH_DEBUG 9
        #define WH_SHELL 10
        #define WH_FOREGROUNDIDLE 11
        #define WH_CALLWNDPROCRET 12
        #define WH_KEYBOARD_LL 13 && this is the one used
        #define WH_MOUSE_LL 14

        this.Enabled = .F.
        WAIT “Go type in another application – your keystrokes will be recorded”
      WINDOW TIMEOUT 2
        *!* You must have a Named reference to the form or object
        *!* as thisform or this cannot be used with BindEventEx
        BINDEVENTEX(‘oform1.wineventhandler()’, WH_KEYBOARD_LL) && SetWindowsHookEx
       ENDPROC

      ENDDEFINE


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050181

      The SPS Blog Updated

      by craigaaa3 ·

      In reply to The SPS Weblog

      As my younger brother Daniel was reading my weblog tonight, he messaged me and told
      me that the “poker spam comments on your weblog are bogus”. One of the online casinos
      had obviously thought that my blog might make a good place to advertise. So, I’ve
      taken this opportunity to not only clean up the spam, but also update to the latest
      stable version
      of dasBlog (version 1.7.5016.2) since I was going to be in here
      messing around anyways.

      The upgrade was fairly painless. I followed (to the letter) the instructions given,
      ran the upgrader command line utility, copied the relevant pieces over the top of
      my old version and ran headlong into a known issue with the titleList macro. A quick
      Google search and a single line edit in the source made quick work of this problem.
      Total time to upgrade 15 minutes… not bad, especially considering that I’ve customized
      a few different areas of my blog. I haven’t been through it end-to-end, but on quick
      review everything appears to be working correctly.

      As for the spammers, while they can still post manually (there’s always a way for
      the determined) there are new security features and blacklists to help prevent
      as much as possible. And now, rather than having to edit the xml files (that make
      up the content of this blog) to remove comments, I can now delete any spam comments
      directly using the administrative functions (an obvious must for any serious
      blog engine). All in all it appears to be a pretty good release.

      I noticed that another new feature I could turn on is permalinks that use
      the title of the blog entry instead of a guid. However, with the number of blogs and
      websites pointing to different entries on this blog already, I think I will stay with
      the guids, even if they are considered a little long in the tooth by some.

      So, a big thank you to both my brother Daniel (for pointing out the spam) and the
      development community surrounding dasBlog (for another good release). I
      have something to say to the spammers as well, but decorum prevents me.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050179

      New Visual FoxPro Information Available

      by craigaaa3 ·

      In reply to The SPS Weblog

      A couple of recent blog entries, a letter from the Editor concerning Visual FoxPro,
      and a fairly hard-hitting interview… is today Christmas?

      First, I owe thanks to Alex
      Feldstein’s Blog
      for a heads up that Ken Levy’s August
      2005 – Letter from the Editor
      for Visual FoxPro has been published.

      Then reading a recent
      blog entry by David Stevenson
      , I found that he had done a an interview
      with Microsoft’s Alan Griver and Ken Levy
      . Nicely done Dave, and thanks for making
      it available to the Visual FoxPro Community.

      It’s on days like today that I marvel at the way blogs have changed the way in which
      I receive information. The quantity, quality, and timeliness of that information can’t
      be beat. If you haven’t done so yet, you owe it to yourself to get a decent news aggregator
      (there are plenty of free ones available – I use and recommend Sauce
      Reader
      ). Then, if you are as interested in Visual FoxPro related content
      as I am, subscribe to this blog and all of the blogs in my Blogroll (over there
      —>).  It really will open up a whole new world for you.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050178

      Spelling Checker and VFP

      by craigaaa3 ·

      In reply to The SPS Weblog

      Checking the spelling in a given string, such as the text in a control, is something
      that a lot of Visual FoxPro applications can use. There are many ways to accomplish
      this.  Some Visual FoxPro developers use Microsoft Word similar to the way I
      did in my FAQ about it. Others
      shell out between $250-500 in order to purchase a third-party tool or control that
      will get the job done. And some, just do without.

      Making a Contribution
      Well, a couple days ago I was looking for a way to put my
      recent blog
      about the Visual FoxPro Community into action at this end, and I decided
      to try my hand at creating a class with the ability to easily add spelling checks
      to Visual FoxPro applications. Here are some of the important steps I took, followed
      by a screen capture of spelling checker I created in Visual FoxPro and a
      couple of links, so you can download a copy of the project (all source code included),
      some runnable examples, and even an alternate dictionary table.

      Step 1:
      Find a way to recognize a misspelling. Obviously I needed a dictionary. Luckily
      there are plenty of open source dictionaries out there, and I soon I had compiled
      a dictionary table of 144,238 words. The words came from Kevin
      Atkinson’s Spell Checking Oriented Word Lists
      (SCOWL). I took English and American
      words up to level 70. Level 80 and 95 words are mostly obscure (scrabble players only),
      removed possessive words and duplicates, and gave it a few final tweaks. 140,000+
      words is a nice size dictionary for any spelling checker.

      Step 2:
      Give the user some choices of possible matches. Here again I was lucky in
      that I’ve worked on a number of sounds-like algorithms for Visual FoxPro in the past
      (including: Improved Soundex, Metaphone,
      and Double
      Metaphone
      ). In this case, because I was dealing with English words the Improved
      Soundex was all that was needed, and it is the fastest of the alternatives so that
      was a Win-Win. However, this only handled misspellings that sound like the actual
      spelling, if I ran into “thwrw” because the user’s finger had slipped
      to the “w” instead of the “e”, the Improved Soundex algorithm
      wasn’t going to do me much good.

      Well, it just so happened that I had run into a posting of a class method for
      computing the Levenshtein
      Distance in Visual FoxPro
      and I had rewritten it (see the bottom of the page I
      linked). The Levenshtein
      Distance
      is an excellent indicator of how closely matched two words are even though
      they don’t sound the same.

      Step 3:
      With the first two hurdles overcome, it was time to figure out what kind
      of design I would go for. I decided on doing the entire thing with classes and in
      such a way that new user interfaces could be created and hooked up. Now, bear in mind
      that this is just my first stab at it and less than two days have gone by, but I think
      you’ll see some things you like if you care enough to dig into it.

      Before I go any further let me say that I have not put the error handling into it
      yet. That will go in next. I find with projects of this size (and when there is a
      high potential for me to be changing my mind while coding) that it is easiest to put
      the error handling in once the design has stabilized. So please, no flames about the
      lack of any error handling… it’s on the way. Or, better yet, since it will be a
      couple of days before I can get back to this, how about you throw in some really nice
      Try…Catch…Finally commands in it and shoot it back to me? LOL.

      The guts of the spelling checker is in the spellcheck class in spellcheck.vcx and
      my first stab at an interface is the splchkdialog class in spellcheck.vcx.  Other
      than that the class library just holds a bunch of subclasses of the Visual FoxPro
      base classes. I want to encapsulate the logic even further, so interfaces are a complete
      snap to create and the spellcheck class is a black box engine (but it’s still pretty
      decent as it sits now).

      Step 4:

      Return a list of suggestions for the user to pick from as replacements for a given
      misspelling really fast. I had to figure out a way to tweak the returned suggestion
      list that would handle the size of the dictionary table. I decided on an SQL
      select statement because of its flexibility and speed when optimized. Then I defined
      the criteria for the SQL where clause. I also ordered the elements in the Where
      clause so that the criteria that would weed out the most entries came first and the
      most resource intensive operations (such as the Levenshtein Distance) would come last.

      This still wasn’t fast enough, so I created another field in the dictionary table
      to hold the Improved Soundex codes for the words and indexed it. And created an index
      on the LEN(ALLTRIM()) of the word as well. This dramatically improved the speed and
      after a few more tweaks I had a workable SQL for returning the results. See the getsuggestions
      method of the spellcheck class.

      Step 5:

      Logically order the results returned to the user. Alphabetical returns are anything
      but logical when returning suggestions for a spellchecker. I decided to add a weight
      field to the suggestions curosr and base it on different aspects of the
      matches between the word in question and the words in the dictionary table. In
      this case, I went with lower weights meaning better the matches. The weight made
      an excellent field to base the Order by clause on as well. The top 10 results
      were finally being returned in a logical order. To see the way the weight is figured,
      look in the figureweight method of the spellcheck class.

      Step 6:
      Test, tweak, test fix… drink more coffee and Red Bull energy drink… Test,
      tweak, test, fix. And finally, create two examples, write a README.txt, zip it all
      up, take a couple screen shots, and write this blog. The download link is provided
      below (look on the right-hand side), full source included, don’t forget to read the
      README.txt.

      Visual FoxPro Spelling Checker

       Download VFP Spelling Checker (2MB
      approx.)

      UPDATES: 07-31-2005 Created a new dictionary table based on the SCOWL so that copyright
      and redistribution rights were sure (removed previous two dictionaries). Optimized
      some code, fixed a couple of bugs, worked in the new dictionary and edited this blog
      entry to apply to the new dictionary table.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050177

      Skinning a Form in Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      Sometime ago I incorporated VFPSkin elements
      into a project I was working on. This was when VFPSkin had first come out (version
      1.0?) and was still free and open source. I was pretty impressed with VFPSkin
      as I had never seen skinning for Visual FoxPro applications prior to this. It was
      a little buggy and I made a lot of modifications, but overall the idea was sound and
      ingenious. (Just for the record, I made it a point not to look at VFPSkin’s source
      code while I created the example for this blog entry. I admit having been exposed
      to VFPSkin and thus influenced by it, but the code and parts of this example
      were created from scratch.)

      So, that was extent of my exposure to skins in Visual FoxPro… fast forward
      to today. I decided to take a look at creating a simplified way to skin Visual FoxPro
      screens. Why? Well, as with most of my ideas and side projects, sometimes it’s the
      challenge and other times I just have an idea for something that might be helpful
      to the Visual FoxPro Community and I want to explore it a little. In this case,
      as in most, it was a little of both. I call this project “Green Screen”.

      The idea was to take a single ordinary bitmap that has a unique background
      color (transparency key if you will), use it for the picture property of a form, and
      then carve out everything at runtime based on that unique color. In this case I chose
      green for the color — just like in the movies (that’s where I got the idea,
      though these days I think Hollywood uses mostly blue) — and I created a simple sample
      skin that I could use during development.



      Green Screen Skin Bmp

      Using some API calls (CreateRectRgn and CombineRgn in
      GDI32 and SetWindowRgn in USER32) the project quickly progressed and I soon had
      a form that displayed just the intended portion of the bitmap skin. Next it was time
      to create a routine that would allow Visual FoxPro developers to use their own bitmaps
      and create “skin definition files” based on them. I decided to incorporate this portion
      into my example form as well.

      This is just a quick initial stab at it… consider
      it a pretty decent proof of concept. My ultimate goal for this portion was to show
      Visual FoxPro developers how skinning can be accomplished in a simple, straightforward
      way. It took much less than a day to get this far, so imagine what can be done given
      time. Next up on my todo list will be the ability to resize the form (as well as maximize
      and minimize) and also the ability to skin/unskin on demand as well as the ability
      to change skins on the fly. I will be keeping an eye towards simplicity throughout,
      as I want this to be a very painless tool for Visual FoxPro developers to use.

      A couple of quick final notes: The two methods in
      the example form that you’ll want to take a look at are createskindefinition and readskindefinition.
      Though I chose green as the unique color, it can be anything. The readskindefinition
      method will look at a single pixel in the bottom left of your bitmap to determine
      the color that should be carved out of the form. All in all, I think you might be
      surprised at minimal amount of code it took to actually pull this off. Here’s a screen
      shot of the example and the customary download link.

      Download
      Green Screen Example
       (10 KB approx.)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050176

      Splitter Class for Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      A number of other languages have a splitter control of some sort, why not Visual FoxPro?
      To be fair, I have seen some splitter classes floating around from time to time, but
      I thought I’d try my hand at it. I was convinced it couldn’t be too difficult, and
      Visual FoxPro didn’t disappoint me. Below is a download link for the class library
      that I placed my splitter class in (based on shape) and an example form showing how
      the class is used (I’ve taken a screen shot of it so you can see what it looks
      like). Now, if you want to try the splitter class out before you go to the trouble
      of downloading it, I’ve also created a cut-n-paste/execute example that you’ll find
      directly beneath the screen shot. This splitter control is designed to work with Visual
      FoxPro 9.0. If you are using a previous version then you will need to modify/delete
      a few things.

      Download Splitter.vcx
      and Form Example
       (8 KB approx.)

      *!* Cut-N-Paste the code below into a prg file and execute it to see and try out a
      working example of the splitter class

      PUBLIC oform1

      oform1=NEWOBJECT(“form1”)
      oform1.Show
      RETURN

      ************************************
      DEFINE CLASS form1 AS form
      ************************************

       DoCreate = .T.
       Caption = “Splitter Example”
       Name = “Form1”
       MDIForm = .T.
       Autocenter = .T.
       
       ADD OBJECT text1 AS textbox WITH ;
        Anchor = 11, ;
        Height = 29, ;
        Left = 0, ;
        Top = 0, ;
        Width = 375, ;
        Name = “Text1”

       ADD OBJECT edit1 AS editbox WITH ;
        Anchor = 7, ;
        Height = 217, ;
        Left = 0, ;
        Top = 33, ;
        Width = 184, ;
        Name = “Edit1”

       ADD OBJECT edit2 AS editbox WITH ;
        Anchor = 15, ;
        Height = 217, ;
        Left = 188, ;
        Top = 33, ;
        Width = 187, ;
        Name = “Edit2”

       ADD OBJECT splitter1 AS splitter WITH ;
        Top = 32, ;
        Left = 183, ;
        Height = 219, ;
        Width = 6, ;
        Anchor = 7, ;
        Name = “Splitter1”

       ADD OBJECT splitter2 AS splitter WITH ;
        Top = 28, ;
        Left = 0, ;
        Height = 6, ;
        Width = 376, ;
        Anchor = 10, ;
        vertical = .F., ;
        minimumsize = 29, ;
        Name = “Splitter2”

       PROCEDURE Init
        This.text1.Value = “Visual FoxPro Rocks!”
        This.Edit1.Value = “Visual FoxPro is an extremely versatile development
      tool. ” + ;
          “Not only does it allow a developer to create great datacentric
      applications, ” + ;
          “it also allows the developer to extend the actual language
      with new classes, ” + ;
          “code libraries, and hooks. If you’re an avid Visual FoxPro
      developer like myself ” + ;
          “then good for you. And, if you’re not, then I encourage you
      to give Visual FoxPro ” + ;
          “a try. You won’t regret it”
        This.Edit2.Value = “This is an example of a splitter class for use in
      Visual FoxPro 9.0 forms. ” + ;
          “It is pure Visual FoxPro, so there aren’t any additional
      ActiveX or DLL dependencies ” + ;
          “to worry about when distributing your application. To see
      it in action move the ” + ;
          “horizontal and vertical splitters around on this form. Also,
      by resizing the form you ” + ;
          “can see that it handles the new Visual FoxPro 9.0 Anchors
      property with aplomb.”
       ENDPROC

      ENDDEFINE

      ************************************
      DEFINE CLASS splitter AS shape
      ************************************
       Height = 182
       Width = 8
       MousePointer = 9
       SpecialEffect = 0
       Style = 0
       mousedownat = 0 && Tracks mouse and allows class to ignore moves caused
      by resizing form
       vertical = .T. && Set to .F. for horizontal splitter
       minimumsize = 40 && This is how small (in pixels) the panels can get
      when moving the splitter
       Name = “splitter”

       PROCEDURE MouseLeave
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        This.mousedownat = 0
       ENDPROC

       PROCEDURE Move
        LPARAMETERS nLeft, nTop, nWidth, nHeight
        *!* If you want to move the splitter during runtime and have it move the
      other controls
        *!* then set mousedownat != 0 and call this move method of the splitter
        *!* remember to set mousedownat back to 0 when you are done moving the
      splitter

        LOCAL loControl, llLockScreenWas, lnMovement, llIsSplitter, lcUniqueTag,
      lnMarginOfError, lnAnchorWas
        IF this.MouseDownAt == 0
         DODEFAULT(m.nLeft, m.nTop, m.nWidth, m.nHeight)
         RETURN
        ENDIF

        m.loControl = NULL

        *!* The following tag can be placed in controls you don’t want moved as
      well
        m.lcUniqueTag = “DoN’t_MoVe_SpLiT” && Just something that is pretty
      well guaranteed to be unique
        THIS.TAG = m.lcUniqueTag
        m.llLockScreenWas = THISFORM.LOCKSCREEN && JIC the screen was
      already locked
        THISFORM.LOCKSCREEN = .T.

        m.lnMovementLeft =  m.nLeft – THIS.LEFT
        m.lnMovementTop =  m.nTop – THIS.Top

        FOR EACH m.loControl IN THIS.PARENT.CONTROLS
         IF m.loControl.TAG = lcUniqueTag && this splitter so just
      loop
          LOOP
         ENDIF
         IF PEMSTATUS(m.loControl,”Anchor”,5)
          m.lnAnchorWas = m.loControl.Anchor
          m.loControl.Anchor = 0
          m.llIsSplitter = m.loControl.CLASS = “Splitter”
          IF THIS.vertical && Vertical Splitter
           lnMarginOfError = INT(This.width/2) && JIC the
      developer got the splitter a little too close
           IF m.loControl.LEFT <= THIS.LEFT && Control
      is to the left of splitter
            IF (m.loControl.LEFT + m.loControl.WIDTH) <=
      (THIS.LEFT + lnMarginOfError) AND !m.llIsSplitter
             m.loControl.WIDTH = MAX(m.loControl.WIDTH
      + m.lnMovementLeft, 0)
            ENDIF
           ELSE  && Control is to the right of splitter
            IF !m.llIsSplitter
             m.loControl.WIDTH = MAX(m.loControl.WIDTH
      – m.lnMovementLeft, 0)
            ENDIF
            m.loControl.LEFT = m.loControl.LEFT + m.lnMovementLeft
           ENDIF
          ELSE && Horizontal Splitter
           lnMarginOfError = INT(This.Top/2) && JIC the
      developer got the splitter a little too close
           IF m.loControl.TOP <= THIS.TOP && Control
      is above the splitter
            IF (m.loControl.TOP + m.loControl.HEIGHT) <=
      (THIS.TOP + lnMarginOfError) AND !m.llIsSplitter
             m.loControl.HEIGHT = MAX(m.loControl.HEIGHT
      + m.lnMovementTop, 0)
            ENDIF
           ELSE  && Control is below the splitter
            IF !m.llIsSplitter
             m.loControl.HEIGHT = MAX(m.loControl.HEIGHT
      – m.lnMovementTop, 0)
            ENDIF
            m.loControl.TOP = m.loControl.TOP + m.lnMovementTop
           ENDIF
          ENDIF
          m.loControl.Anchor = m.lnAnchorWas
         ENDIF
        NEXT
        m.lnAnchorWas = This.Anchor
        This.Anchor = 0
        DODEFAULT(m.nLeft, m.nTop, m.nWidth, m.nHeight) && Finally move
      the splitter
        This.Anchor = m.lnAnchorWas
        THISFORM.LOCKSCREEN = m.llLockScreenWas
        THIS.TAG = “”
       ENDPROC

       PROCEDURE MouseMove
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        LOCAL lnMovement
        IF m.nButton = 1 AND !(this.mousedownat == 0)
         IF THIS.vertical
          IF m.nXCoord != THIS.mousedownat
           m.lnMovement = m.nXCoord – THIS.mousedownat
           IF BETWEEN(THIS.LEFT + m.lnMovement, This.minimumsize,
      THIS.PARENT.WIDTH – THIS.WIDTH – This.minimumsize)
            THIS.MOVE(THIS.LEFT + m.lnMovement, THIS.TOP,
      THIS.WIDTH, THIS.HEIGHT)
            THIS.mousedownat = m.nXCoord
           ENDIF
          ENDIF
         ELSE && Horizontal
          IF m.nYCoord != THIS.mousedownat
           m.lnMovement = m.nYCoord – THIS.mousedownat
           IF BETWEEN(THIS.TOP + m.lnMovement, This.minimumsize,
      THIS.PARENT.HEIGHT – THIS.HEIGHT – This.minimumsize)
            THIS.MOVE(THIS.LEFT, THIS.TOP + m.lnMovement,
      THIS.WIDTH, THIS.HEIGHT)
            THIS.mousedownat = m.nYCoord
           ENDIF
          ENDIF
         ENDIF
        ENDIF
       ENDPROC

       PROCEDURE MouseDown
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        IF THIS.vertical
         THIS.mousedownat = nXCoord
        ELSE
         THIS.mousedownat = nYCoord
        ENDIF
       ENDPROC

       PROCEDURE Init
        IF !THIS.vertical
         THIS.MOUSEPOINTER = 7 && NS
        ENDIF
       ENDPROC

       PROCEDURE MouseUp
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        This.mousedownat = 0
       ENDPROC
       
      ENDDEFINE


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050175

      New ReportPreview App for Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      The ReportPreview.app is a pretty good general preview application
      for Visual FoxPro 9. The look of it mimics the report preview screen we had prior
      to Visual FoxPro 9 and it provides much of the same functionality as well as some
      new features available in Visual FoxPro 9 thrown in for good measure. However, some
      Visual FoxPro developers are having problems with certain aspects of it.

      Running ReportPreview.app as a modal preview (report form command) in
      a TopLevel form application will cause the print preview toolbar to stop responding.
      That’s because the ReportPreview.app brings the preview form up in a modal state and
      toolbars are not accessible when a modal form is active. For the most part, this is
      as it should be and is in-line with Microsoft Windows conventions. The answer is to
      include the NOWAIT clause in the report form command or you can modify the ReportPreview.pjx
      to force it into a modeless state when this situation occurs. Easy enough right? Well,
      the problem with this approach is it usually defeats the very thing that the developer
      is attempting to do… mainly, bring up a modal preview window in a TopLevel application
      (I want the preview window to come up, then I want to wait until the user has released
      the preview window before continuing with my code execution).

      If you haven’t run into the aforementioned problem you can reproduce
      it by opening up the Taskpane in Visual FoxPro and go to the Solutions Samples
      area. Then expand the “New in Visual FoxPro 9.0” node and look for the “The typical
      multiple detail band report” sample. Over on the right-hand side of the sample there
      is a little report and magnifying glass button that says “Click here to view the code”
      in its tooltip, click that button. Next modify the ShowWindow property of the
      form that pops up (ShowWindow = 2 – As Top-Level Form). Close the form and save your
      changes, then run the sample. You’ll notice that the toolbar does not respond to user
      events. To close the sample you’ll have to close the report from the “X” in the top
      right corner of the preview window.

      Another thing about the ReportPreview.app is that it looks a little
      antiquated to me. I may be the only one that feels this way, but I suspect not. Now,
      before the flames start… I’m not saying that I don’t think the MS Fox Team didn’t
      do a good job. I’m all for having them just give us access and allow us, as seasoned
      Visual FoxPro developers, develop the rest. I don’t want them wasting time mocking
      up Visual FoxPro forms and applications that I can create myself. I feel like we are
      all well served by them opening the guts of Visual FoxPro up to us as developers,
      give a basic example of the new feature’s use, and then let us do the rest.

      So, last night I decided to rip into the ReportPreview.pjx and see
      what I could do. I made an exact copy of the entire Report Preview project folder
      from XSource and then began modifying it. Basically keeping the stuff I liked, deleting
      the stuff I didn’t, and modifying the rest. The result was a ReportPreviewEx.app that
      can be used in lieu of the ReportPreview.app. To use it you’ll need to set the _reportpreview
      system variable to the new application:

      _reportpreview

      = “reportpreviewex.app”>

      This will cause Visual FoxPro to use the new print
      preview application. To try it out run one of the report samples in the Solutions
      Samples area of the Taskpane underneath the “New in Visual FoxPro 9.0” node. The names
      of the samples are “A multiple detail band report used for calculations” and “The
      typical multiple detail band report”.

      This new application doesn’t suffer from some of the
      drawbacks the ReportPreview.app does. For instance, instead of toolbar, I placed the
      buttons and such directly on the frxpreviewform class. This fixes the problem with
      modal previews in a TopLevel application and is more in-line with print preview windows
      such as the one in Internet Explorer.

      I ran into more than a few issues while creating
      this, but almost all of them have been resolved successfully. However, one issue that
      is still plaguing me is the way the MS Fox Team failed to implement double-buffering
      correctly when rendering emf content in an image control. Emf file format is perfect
      for reports because meta-files scale better than anything else on the planet. But,
      when you are running the print preview you are going to see a slight flicker. Regrettably
      the MS Fox Team has not opened up the internal painting routines to us, so I am unable
      to insert the proper code that should be used when Visual FoxPro is repainting the
      image controls. That having been said, I added a property to the frxpreviewform form
      class of the frxpreview.vcx that allows you to try out all the other formats and their
      results. The property is “outputimagetype” and has the following possible values:
      tiff, bmp, png, jpeg, gif, emf. If you want to try another format that doesn’t have
      the flicker and still has perhaps acceptable quality, change the property to “png”.
      The drawback to this format is that it looks blurry at large zoom levels and Visual
      FoxPro turns into a bit of a performance hog with its internal painting routines.

      I posted a comment on Calvin
      Hsia’s blog
      recently asking him to pull the curtain back further on the internal
      painting routines for Visual FoxPro, and I’ve asked other members of the Fox Team
      in the past to please give us a little insight into this so we can address issues
      such as this effectively and help Microsoft out a little at the same time. Regrettably,
      they have ignored me so far. I wish that their new goal of transparency extended towards
      the Visual FoxPro core as well. I understand that they have trade secrets/intellectual
      property rights to consider, but I think they could use some help in this particular
      area.

      Now some of you are no doubt thinking, why didn’t Craig
      just use the outputpage method of the Report Listener class to render to a canvas
      object (shape or container control). The reason is that Visual FoxPro will paint right
      over the top of anything that gets in the way of the canvas object. So, if you have
      a bunch of canvas objects inside a container and you are allowing the canvas objects
      to be slid around inside the container so that portions of them are outside the dimensions
      of the visible container (left = -150 or top = -200 or whatever), the Report Listener
      doesn’t respect the container’s borders, so it starts rendering the report right over
      the top of other form elements. So, the answer is to use an image control and temporary
      off-screen bitmaps assigned to their picture property. Why not a container (it has
      a picture property)? Well with the image control I pick up a little more overhead,
      but it gives me some really good additional functionality for free (such as the stretch
      property that makes zooming in and out on print preview a breeze from a coding standpoint).
      There’s more to this whole sorted saga, but I think you get the general idea.

      So, here’s a screen capture of the new print preveiw,
      a link to download the ReportPreviewEx.app, and an additional link to download
      the entire source —
      IMPORTANT NOTE: I’ve just looked through
      the redist.txt that comes with Visual FoxPro and I cannot find anywhere that certain
      elements of the ReportPreview.pjx are on the allowable list – I will email Microsoft
      for clarification – until I hear back from them, I have removed the source code link.

      Download
      ReportPreviewEx Application
      (approx. 47 KB)

      ReportPreviewEx Application Screen Capture


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050174

      Fox Quotes for The FoxShow

      by craigaaa3 ·

      In reply to The SPS Weblog

      Andrew MacNeill of AKSEL Solutions has been doing a stellar job with The FoxShow podcast. If you’re a Visual FoxPro developer, you’ll find his podcasts informative and useful. The topics run the gamut and it’s one of the most ingenious forms of homegrown PR work for Visual FoxPro that I’ve seen in some time. It definitely deserves the Visual FoxPro Community’s support, and on that note, I provide the following snippet from a recent post Andrew made on ProFox:

      “… As some of you know, I’m hosting the Fox Show, a podcast about Visual FoxPro , software development, yada yada yada. (go to http://www.thefoxshow.com if you want to listen or subscribe in iTunes, etc)

      I’ve been retooling the show of late and what I’d love to have is little “Fox Quotes”, quotes from developers who use FoxPro, promoting their web site and themselves but mostly FoxPro. (if you do want to do an interview, skype me and we can set it up)

      If you can (or want to), just record a little MP3 (or WMA or whatever audio file) that essentially says:

      Hi. This is __________________, from ________________.
      I’ve been using FoxPro since __________ (version or year).
      My favorite FoxPro feature is _______________. (if you want to describe it go ahead).
      My biggest FoxPro gripe is ___.
      You can reach me at http://www._____________________.
      You’re listening to the FoxShow podcast!

      Your favorites or gripes can be as long or as short as you want. This is more for “fun” filler stuff as I’m hearing from a lot of listeners that they are “lone developers” and love to really hear others talk about their stuff.

      Email it to akselsoft at gmail dot com. Don’t worry if you feel it’s too long or whatever, I can edit it if need be.

      Also, if you have a product, topic, or anything at all you want to discuss, shoot me an email, skype me, whatever and we can arrange it.” — end quote

      I’ve changed his email address to obfuscate it somewhat from the spammers and hope that “akselsoft at gmail dot com“is easy enough to figure out. I don’t mind people posting my email craig@sweetpotatosoftware.com address without obfuscating it, but without prior permission or knowing the person’s preference, I try to be considerate.

      Well, if you haven’t sent Andrew a “Fox Quote” yet, I encourage you to do so (mine went out today). As I’ve said before, there are many ways to support the Visual FoxPro Community and our beloved product. Andrew, if you’re listening… Thank You!

    • #3050173

      Undocument SYS() Functions

      by craigaaa3 ·

      In reply to The SPS Weblog

      Most of what I’m about to show is more oddity than useful. There are a number of undocumented
      functions, commands, and other oddities (remember the mousewheel event being used
      to create a workable systray class?) in Visual FoxPro. From time to time developers
      will run into them while testing, or someone on the MS Fox Team will mention them,
      or Visual FoxPro enthusiasts will go looking for them.

      Here are some odd Sys() functions that appear to be undocumented. I’ve included the
      nValue as well as the eValue where applicable. So for..

      988: evalue .T. or .F. returned previous setting

      …I’m saying that you can either run ?SYS(988, .T.), or ?SYS(988, .F.) and that the
      return value will be whatever you sent as a parameter the last time. I hope that makes
      sense, if not, then just try a few out and I think what I’m posting will be more understandable.

      I realize that I didn’t organize this list very well, but I’m in a hurry and
      just wanted to throw this in a quick blog entry (sorry organization and a sorry excuse
      – what can I say?).  Whether any of these SYS() functions do anything useful
      I don’t know — definitely SYS(1079, 0) is not useful — handle that one with care.

      Just so you know, the criteria I used to decide whether a SYS() function did something
      undocumented was if it was checking the type of the eValue (parameter sent in) and/or
      returned a value when called.  I feel that the SYS(999) and SYS(2901) are pretty
      interesting (I’ve included some code so you can explore them) and some of
      the SYS() functions that returned numeric values intrigued me as well. I tried to
      figure out what those numeric values were pointing to, but was unable to decipher
      them. I feel that perhaps they are handles or pointers of some kind.  Anyone
      with any additional information, feel free to chime in (Calvin?).

      Lastly, I recall seeing a list like this years ago. I thought Steven Black had compiled
      it, but for the life of me I couldn’t find it on the net. So, if anyone knows where
      that list is, I’d appreciate it if you would comment with the link to it. Thanks.

      Here’s my compiled list…

      988: evalue .T. or .F. returned previous setting
      989: evalue 0 or 1 Returned previous setting
      999: evalue 1-4417 (accepts up to 4999 without error) brought up windows

      ***************************************
      *!* Program to show some example windows from 2901
      *!* Press tab to move to next window
      SYS(999, 26)
      SYS(999, 500)
      SYS(999, 2999)
      SYS(999, 4417)
      ***************************************

      1004: returned 10105192 (increments?)
      1005: returned 1220846 (increments?)
      1006: returned 1218880 (increments?)
      1011: returned 1967 (different at times)
      1012: returned 5901
      1013: returned 1063636632 (changes depending on a number sent in, otherwise same)
      1017: returned 11163028 (changes but same after being called… don’t know what changes
      it though)
      1018: returned “Hold Index Lock during TableUpdate: On”
      1021: evalue 0-65535 returned nothing
      1029: evalue 0-65535 returned nothing
      1039: evalue 0 to non-zero returned previous setting “ON” or “OFF” (zero was considered
      off)
      1079: C5 error everytime takes numeric parameter
      1101: returned 358875136
      1102: returned 1609982
      1103: returned 364798
      1105: returned 365622 (different depending on window it is run from)
      2050: evalue 0-10 returned parameter sent in
      2400: evalue 0-1 returned 0 when 0 or nothing was sent in otherwise blank
      2701: returned “{1:0, t:0, w:0, h:0}”
      2901: evalue 0-9727 returned VFP string table && there is more further up,
      but I stopped at 9727

      ***************************************
      *!* Program to show strings for 2901
      *!* The following parameters will cause buffer overflow errors that shut Visual FoxPro
      down
      *!* So we’ll avoid them
      ALINES(aryBufferOverflow, “604,801,802,835,2483,2489,2511,2533,2538,2556,2792,2811,”
      + ;
         “2832,2845,2961,2975,2985,2987,2988,3039,3120,3407,3433,3478,3516,3517,”
      + ;
         “3527,3532,3541,3546,3549,3550,4416,4673,4720,4795,4799,4812,4834,4882,4884,”
      + ;
         “4891,4979,4999,5005,5015,5098,5103,5571,5601,5882,6584,7427,7433,7434,”
      + ;
         “7437,7467,7482,7489,7493,7498,7511,7537,7551,7567,7578,7631,7634,7636,”
      + ;
         “7653,7662,7673,7675”, 1, “,”)
      IF FILE(“C:\VFPSys2901.txt”)
       ERASE(“C:\VFPSys2901Strings.txt”)
      ENDIF
      FOR lnCounter = 0 TO 9727
       WAIT WINDOW “One moment…  ” + PADL(TRANSFORM(INT(lncounter / 9727 * 100))
      + “%”, 4, ” “) NOWAIT
       IF ASCAN(aryBufferOverflow, TRANSFORM(lnCounter)) = 0
      *!*   ?lnCounter
        =STRTOFILE(“SYS(2901, ” + TRANSFORM(lnCounter) + “) = ” + SYS(2901, lnCounter)
      + CHR(13), “C:\VFPSys2901Strings.txt”, 1)
       ENDIF
      ENDFOR

      IF FILE(“C:\VFPSys2901.txt”)
       MODIFY FILE (“C:\VFPSys2901Strings.txt”)
      ENDIF
      *****************************************

      3090: evalue 0 or 1 Returned previous setting
      3100: evalue accepts positive integers returns nothing
      4000: to 4004 will error with “feature is not available”
      4010: will error with “feature is not available”
      4015: evalue accepts anything returns 0
      >4015: reutrns nothing, I checked up to 100,000,000
      -1: and below work same as sys(0)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3050172

      Rubberband Selections in Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      The day before yesterday I was surfing my blogroll and came across an interesting
      post by Calvin Hsia — “Enable
      crop and zooming in on your digital photograph display form
      “. It was using GDI+
      in a Visual FoxPro form and, since I am writing a series of articles for FoxTalk on
      the subject, it caught my eye. One of the things I liked the most about Calvin’s entry
      was the idea of using a shape in order to create a rubberband selection area; basically a
      rectangle with a dotted line border that you may have noticed once or twice in
      various Windows applications (still don’t know what I’m talking about? Go to your
      desktop and left click and drag a rubberband selection area around some icons — or
      just look at the screen shot below). I came away from Calvin’s entry thinking he had
      a great idea, so I’ve implemented my own and expanded on it.

      I created a class called “rubberband” that can be added through code to any form
      during runtime. It facilitates a rubberband selector when the user drags their mouse
      over the surface of the form. This class has several features that I thought would
      be useful to a developer.

      • The rubberband is reversible, meaning it can follow the mouse no matter which way
        the user maybe dragging their selection area.
      • It provides feedback when the selection is started, when the selection area is
        changed, and also when the selection has been completed.
      • It has an optional feature that will allow you to get a collection of the selected
        objects as well as a collection of objects that aren’t selected based on the selection
        area. This is turned on or off via a property of the class named “selectobjects”
      • Left or right mouse button can be specified as the active mouse button that creates
        the rubberband selection areas.
      • Optional keys (shift, alt, or ctrl) can also be specified as required during the selection
        (such as, the user must hold the alt key down while dragging with the left mouse button
        depressed).

      The class makes liberal use of Visual FoxPro’s Bindevent function to monitor the user’s
      activity on the form’s surface. And, the example form I’m including in the download
      uses bindevents as well to receive feedback from the rubberband class. All-in-all,
      it turned out to be a pretty workable solution and implementation of Calvin Hsia’s
      idea.

      One of the problems I ran into however, was when the mouse was over a particular object
      on the form, the form obviously didn’t receive the mouse events… so the rubberband
      just stops. The solution for this example was to send the mouse events up the chain
      to the parent form. However, in perhaps a future blog entry I will use the vfpex.fll
      with its BindEventEx/UnBindEventEx functions (if interested you can read my earlier
      blog post regarding vfpex.fll
      ) in order to create a mouse hook and keyboard hook in
      order to facilitate this without having to send mouseevents up to the parent
      object. I’m not sure if BindEventEx would be needed or not, perhaps Visual FoxPro
      9.0’s BindEvent would be enough… never hit something with a sledgehammer when a
      simple tap will do.

      Before I go, I just want to say that I highly recommend Calvin
      Hsia’s WebLog
      , there’s a lot of great content there… especially in the archives.
      Who knows, if enough people take an interest in his blog, he might give us more secrets.
      🙂 Now, without any further ado here’s the usual screen shot and download link. (oh,
      and by the way, that weird thing with the fonts getting bolder as the form repaints
      definitely needs to be fixed in Visual FoxPro 9.0 — I’ve left it in this example
      to maybe draw some more attention to it, see the checkboxes as you play with the example).

      Download Rubberband
      Selector Class and Example Form
      (9 KB approx.)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3047932

      Have a Blog? Consider having it copied on TechRepublic

      by craigaaa3 ·

      In reply to The SPS Weblog

      TechRepublic offers to mirror blogs
      William Sanders of Electronic Filing Group posted on the ProFox yesterday that TechRepublic was offering a blog mirror service. It sounded like an interesting idea so I’ve given it a try.

      How does it work?
      Basically TechRepublic will poll your blog every 4 hours for new content and copy it entry-for-entry into the blog mirror up on their site.

      Why would you want to do this?
      First, Visual FoxPro related content will be given a higher profile. TechRepublic is a fairly respected source for IT related content on the web. Many developers, IT personnel, and computer enthusiasts read TechRepublic on a regular basis and having them run into a little Visual FoxPro from time to time would be a good thing.

      Second, it increases the visibility of your blog/website. This can increase traffic and even possibly up your PageRank (PR). In my case this is a very real possibility given that each of my blog entries have “This weblog is sponsored by SweetPotato Software, Inc.” at the bottom of them. TechRepublic has a current PR of 8 out of 10, so unless your site has a ranking of 9 or 10 (unlikely) it is a good thing to have links back to your site from TechRepublic. If you’d like to see what your PageRank is, you can surf on over to http://rankwhere.com/google-pagerank.php

      Third, there is very little downside. A TechRepublic membership is free. The blog mirror service is free. The question becomes, why not do it? The only thing that I can think of is perhaps a sense of loss of control by some, but the content comes directly from your blog, and you can delete your blog out on TechRepublic at any time.

      What is my experience so far?
      Admittedly I’ve only been up there since yesterday. But, I found the process rather painless and the content was copied as advertised. I have noticed that some of my images are a little wide for the fixed-width format of the TechRepublic website, but other than that I am pleased with the results so far. Which is the reason behind this blog entry.

      Where to go to get your blog mirrored?
      Just venture out to http://www.techrepublic.com and, after signing in or creating a new membership account, click on the Blogs area and then click on the “My Blog” link. (There is also a “My Blog” link at the very top right of TechRepublic, but I’m not sure if that was there before I created my blog mirror out there or not). Once you’re on the page for creating your blog, put in the name and description of your blog and then check the provided “Import your existing blog into TechRepublic” checkbox and type the URL to your RSS feed in the provided text field. Finally click “Save My Settings” to submit, and within 4 hours your blog entries should show up on TechRepublic.

      As a community, I think it’s important for us to find ways to promote Visual FoxPro… this is just one example where we can perhaps make a difference. Thank you William for bring this to my attention.

      PS As of this writing the SPS Blog is the most popular blog on TechRepublic. LOL! Here is the link to my blog out there: http://techrepublic.com.com/5247-6257-0.html?id=4031312


      This weblog is sponsored by SweetPotato Software, Inc.

    • #3066346

      Visual FoxPro Grid – A Tip and a Calendar Class

      by craigaaa3 ·

      In reply to The SPS Weblog

      Visual FoxPro’s Grid
      It is my opinion that the Visual FoxPro grid has gotten a bum rap at times.
      Though it does possess it’s share of eccentricities, it is probably one of the most
      powerful and useful controls I have ever had the pleasure of working with. The things
      that it is capable of doing are simply amazing. Heck, you can have multiple controls
      in a column or even put a grid inside a grid, so you essentially have a row/column
      intersect (cell) representing many records.

      In this entry, I want to show you a little known feature of the grid control. If you
      know about this feature, then you are one of a handful. When the grid is refreshing or
      otherwise repainting it will access the backstyle for every control the columns
      contain, and anything you do in there will stick for the individual controls shown
      in the grid.

      Some help from the MS Fox Team
      Allow me to try and clarify… let’s say you have a grid with a single column
      and that column contains Textbox1. If you set the backcolor of the Textbox1 through
      code to, let’s say, the color Red, then every cell shown in column1 will turn red.
      So, how to get dynamic colors (individual cells colored differently within the same
      column)? Well, the MS Fox Team provides us with some dynamic properties of the column
      object that will act on individual cells (DynamicAlignment, DynamicBackColor,
      DynamicCurrentControl, DynamicFontBold, DynamicFontItalic, DynamicFontName, DynamicFontOutline,
      DynamicFontShadow, DynamicFontSize, DynamicFontStrikeThru, DynamicFontUnderline, DynamicForeColor,
      and DynamicInputMask). These are all very useful, and in the scenario I provided the
      DynamicBackColor will work nicely to change the backcolor of individual cells within
      a column of the grid. But what if you wanted to do something more complex? What if
      you had a container in the column and that container contained multiple objects and
      you wanted to set their forecolors and backcolors to completely different colors dynamically
      or what if you wanted to display different pictures within the grid cells?

      Developers’ usual and ingenious solutions
      One approach to these problems is to use multiple controls within the
      column of the grid and then use DynamicCurrentControl to decide which to display.
      Such as one textbox that has a red background and another that has a white background,
      or different image controls all set to different pictures.

      Another ingenious method some Visual FoxPro developers imploy when solving this problem
      is to subclass the column object and then “hook” into a non-used dynamic property
      of the column to use it for other purposes (Such as DynamicForeColor) If the ForeColor
      is being set to 1 then do this, if the forecolor is being set to 2 do something else,
      if the forecolor is 3… and so on. While this approach and the preceding one are
      both valid way of doing this, there is another way.

      Another way
      As previously noted, the backstyle is accessed for the currentcontrol in
      a column, and it’s not accessed just once, it is accessed for every visible cell
      in the grid. So, using this we can do nearly whatever we want as far as dynamic formatting
      and display. Want different images displayed? Just subclass a container and put an
      image control within it and place it in the column. Then, in the backstyle_access
      method (you’ll need to add this access method to the subclassed container) set the
      value of the contained image’s picture property to a field in the recordsource
      that holds all the different paths in the image’s backstyle_access method.

      this.picture = crsImages.Paths

      There’s an example of doing this included in the download. When you run the example
      it will ask you for a directory containing images. If one is not readily available
      to you, you can select the folder the project is in because I have included
      the below screen shots in it. This solution is more efficient than having an
      image control in the column for each image you want displayed in the grid… 100 images
      = 100 image controls? I’d rather just deal with one.

      Calendar class and real world example
      OK, but what about something a little more real world? What kinds of things
      is being able to dynamically alter items within a container using the backstyle_access good
      for? All sorts of stuff. In order to demonstrate the just one useful example
      of this, I put together some quick calendar demos. I’ve created an advanced calendar
      class using the grid control. This should demonstrate well the power of utilizing
      backstyle_access in a grid, not to mention the power of Visual FoxPro. Below is
      the download link for the project source and some screen shots (so you can know what
      to expect). There is an executable provided in the source folder for running the examples,
      or if you prefer you can run the forms individually. The examples were created using
      Visual FoxPro 9.0, so if you’re using an earlier version you will have to modify the
      code or better yet, upgrade! There are more great things to come, Visual FoxPro Rocks!

      Download VFP Calendar
      Examples and Source



      Just a simple calendar



      Demonstrates some of the advanced display features of the calendar
      class



      Improved Date and DateTime controls created using the calendar
      class


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3066268

      Visual FoxPro Progress Bar Class

      by craigaaa3 ·

      In reply to The SPS Weblog

      Progress bars everywhere you look

      I’ve created Visual FoxPro progress bars before (who among us hasn’t right?).
      The last time I developed one, I posted it over in the download section of Universal
      Thread
      . It is a COM server progress bar that allows progress indication to
      smoothly continue even when Visual FoxPro is busy churning away on a single line of
      code. But in today’s project, I set out to create a simpler progress bar that could
      be placed in a container (form or whatever).


      Another progress bar class


      I wanted this progress bar to look really professional. I also wanted it to handle
      being resized to any length or width by the developer during design. I then wanted
      it to either do a solid bar or create individual blocks like we see in the standard Windows
      XP progress bar and I wanted it to have the ability to show the percentage complete
      with a label that would change color as the progress bar went over the top of it (so
      at 50%, half of the 50% is one color and the other half another). Finally it had to
      be able to display different colors (green as in Windows XP, as well as red and
      blue). These are all features I’ve seen in other progress bars, and felt that Visual
      FoxPro could use one too.


      Progressbar properties of note


      barcolor = The color you want the progress
      bar to be: 1 = Red, 2 = Green, 3 = Blue (defaults to 2)
      min = The value to be considered 0% (defaults
      to 0)
      max = The value to be considered 100%
      (defaults to 100)
      percentage = The percentage complete based
      on the current value assigned (defaults to 0)
      showpercentage = Whether the percentage
      should be displayed to the user (defaults to .F.; best used when solidbar is .T.)
      solidbar = Whether progress bar should
      be shown as a solid as opposed to blocks (defaults to .F.)
      value = The current value of the progress
      (defaults to 0; should fall within the min and max range)

      Other development notes
      The gradient look of the progress bar was created by dynamically adding lines
      of varying degrees of color. The percentage showing through the progress bar was facilitated
      by setting the drawmode property of the lines to 14 – Merge Pen Not.

      Download the project
      You can either run the progressbarex.exe or you can open the project and
      run the example.scx. Everything is included in the download. Here is the download
      link and a screen shot of the included example…

      Download ProgressbarEx
      Example and Source
      (26 KB approx.)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3068452

      SPS Weblog Upgraded

      by craigaaa3 ·

      In reply to The SPS Weblog

      Well, not too long ago I posted an entry saying that I had upgraded to the latest
      release of dasBlog, but then shortly after that they came out with another new version.
      I was late to upgrade the last time, and instead of getting behind again, I downloaded dasBlog
      1.8 Gold
       (version 1.8.5223.0) today and set about the job of upgrading my
      blog once again.

      The upgrade wasn’t quite as smooth this time as it was last time, but I did finally
      get everything figured out after about an hour (most of the problems I experience
      in upgrading have to do with bringing forward custom modifications I’ve made, not
      necessarily that there is anything inherently wrong with the dasBlog upgrade process).
      I haven’t had an opportunity to go through everything yet, but I’m trusting it’s operational
      given the fact that they put “Gold” in the name of the version. The number one thing
      I liked about this upgrade was that it got rid of the Spam trackbacks I was seeing
      from all those online casinos.

      I’m a big fan of dasBlog and have been very pleased with their product so far.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3066653

      Andrew MacNeill on Screencasting

      by craigaaa3 ·

      In reply to The SPS Weblog

      I’ve just finished reading a wonderful article on creating screencasts by Andrew MacNeill
      — “Show It and
      Support It
      “. Information regarding Windows Media Encoder, Windows Movie Maker,
      Microsoft Producer, Automation of SnagIt in Visual FoxPro, and Camtasia Studio (my
      personal favorite) is included.

      Andrew says that the article was originally slated for FoxPro Advisor, but missed
      the cut. I can understand why FoxPro Advisor passed on the article given the material
      is not specifically targetting Visual FoxPro developers, but this is definitely a
      worthwhile article for Visual FoxPro developers to read. Nothing explains or sells
      a product like a screencast. And, if you are an independent developer, you may find
      by knowing how to screencast effectively you can provide another beneficial service
      to your clients.

      Thanks for the great article Andrew!


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3053709

      Visual FoxPro Scrollbar Classes

      by craigaaa3 ·

      In reply to The SPS Weblog

      New Found Respect for Scrollbar Creation

      Earlier this evening I decided to create a scrollbar class for use with Visual
      FoxPro. My requirements were that it was created purely with Visual FoxPro (didn’t
      have any ActiveX dependecies) and that it was professional enough for use in
      a real world Visual FoxPro application. It is now five hours later… the
      class is complete and I have a new found respect for anyone who successfully creates
      scrollbars. This turned out to be one of the more difficult challenges I have given
      myself.

      New VFPScrollBar Class Library
      I created my scrollbar classes in a class library called vfpscrollbar.vcx.
      The three classes that are of note are the scrollbarhorizontal, scrollbarvertical,
      and the sbscrollablecontainer. The sbscrollablecontainer is an example of the types
      of classes that can be built using the scrollbars.

      Properties and Events
      The following is a list of notable properties and methods for the scrollbars:
      Min – Specifies the minimum value for the scrollbar (defaults to
      0)
      Max – Specifies the maximum value for the scrollbar (defaults to
      500)
      Value – The current value of the scrollbar based on the position
      of the thumb/scroll box
      LargeChange – The amount that is added or deducted from the scrollbar’s
      value when the area between the thumb/scroll box and the scroll arrows is clicked
      SmallChange – The amount that is added or deducted from the scrollbar’s
      value when the scroll arrows are clicked
      Change() – This event/method is fired whenever the value of the scrollbar
      changes
      Scroll() – This event/method is fired whenever the user is moving
      the thumb/scroll box

      When placing the scrollbar classes in a container (form or whatever), you can resize
      the scrollbar making it wider and/or longer. The result at design time may look a
      little odd (since the scroll arrows and thumb/scroll box don’t resize or reposition
      themselves at design time, but everything will shape up at runtime. The point is,
      that you needn’t spend a bunch of time making the scrollbars look good at design time.
      Just place them, resize and position the main container and run it.

      Future Work and Colors
      Currently the scrollbars are blue (to match Windows XP theme), but I have
      my eye towards eventually allowing the scrollbar classes color to be changed either
      with a single property setting or by checking the user’s current system settings and
      pulling the color from there. I painstakingly created these scrollbar classes without
      using any image so that the colors could be easily changed on the fly without additional
      image resources.

      I’ll also be revisiting the code and refactoring portions of it. As it is now, I am
      burnt out on it (it was a rough five hours to get this thing to work and look right).
      So, don’t expect a code clinic with this class… I mean it’s not horrible, but I
      do need to take another pass through it before I will be happy with it.

      Suggestions and Bug Reports Welcome
      I also want to mention that a few members of the Visual FoxPro Community
      have started to provide me with feedback, bug fixes and enhancements for the stuff
      I am posting here on the SPS Weblog. I want you all to know that collaboration, help,
      feedback, and/or ideas are not only welcomed and appreciated, but are exactly the
      reason why I post these entries. I don’t want fame or your money… I just want
      to see the Visual FoxPro Community improve the state of Visual FoxPro and the overall
      experience for developers that are working in it or companies that may be considering
      it as a viable option. It is my belief that one of the greatest data-centric development
      tools ever created deserves nothing less.

      Here is the download link for the example project and vfpscrollbar.vcx source as well
      as a screen shot of the example that shows the scrollbars being used in the scrollable
      container class.

      Download VFP Scrollbars
      Example and Source
       (46 KB approx.)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3054883

      Visual FoxPro and Blowfish Encryption

      by craigaaa3 ·

      In reply to The SPS Weblog

      As security concerns mount, developers and clients are looking at ways to encrypt/decrypt
      sensitive data and files. Visual FoxPro comes with a Crypto API example in the Solution
      Samples, but more than a few Visual FoxPro developers have been bitten when using
      this in distributed applications. I felt there were too many gotchas and, after running
      into my fair share of client systems that it didn’t work on, I eventually gave up
      on it.>

      What I wanted was something extremely secure and reliable
      that was also very simple to use. So, I sat down and wrote an FLL that gives
      Visual FoxPro developers access to the Blowfish cipher (this is not a mini version
      of Blowfish, this is fullblown 16-Round based on work by Bruce
      Schneier
      & Jim Conge). Some good information is available at the links below for
      those of you that might not be familiar with Blowfish…

      http://en.wikipedia.org/wiki/Blowfish_(cipher)

      http://www.schneier.com/paper-blowfish-oneyear.html

      >16-round Blowfish is very secure, extremely fast when
      handling large amounts of data, and I like the idea of only having to write a
      few lines of code to get reliable encryption and decryption for my Visual FoxPro
      applications.
      >

         SET LIBRARY TO LOCFILE(“vfpencryption.fll”)
         cEncryptedString = BFEncrypt(“Credit Card #35823908523105009”, “My_SeCuRe_PaSsWoRd_kEY”)
         ? “Encrypted As: ” + cEncryptedString
         cDecryptedString = BFDecrypt(cEncryptedString, “My_SeCuRe_PaSsWoRd_kEY”)
         ? “Decrypted As: ” + cDecryptedString

      Files can also be encrypted, simply use STRTOFILE() and FILETOSTR()
      in conjunction with the above functions. I’ll be adding native file encryption/decryption
      and more encryption algorithms to this FLL in the coming months. The eventual goal
      is to provide a number of security enhancements for Visual FoxPro, this FLL is just
      the humble beginning of a much bigger plan. Here’s the download link where you
      can get the vfpencryption.fll and try out the example code above.

      Download
      the vfpencryption.fll
      (9 KB approx.)

      >


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3054818

      Visual FoxPro and AES Encryption

      by craigaaa3 ·

      In reply to The SPS Weblog

      Advanced Encryption Standard (AES) For Visual FoxPro
      If you read my
      last blog entry
      , then you know I’m working on putting together a comprehensive
      set of encryption/decryption functions for Visual FoxPro via an FLL. Building on that,
      I decided the next cipher I would implement was AES (a.k.a. Rijndael). The Visual
      C++ code is based on earlier work by Szymon Stefanek, Vincent Rijmen, and K.U.Leuven
      that is in the public domain. The AES encryption standard is good enough that it is
      approved by the US government (among others) for encrypting Classified and Top Secret
      information. This is arguably one of the best ciphers currently being used, and I
      wouldn’t be surprised if some of you readying this have had AES be a security requirement
      on some of your projects. For additional information regarding AES you can see the
      following link:

      http://en.wikipedia.org/wiki/AES

      Description of the new Visual FoxPro AES Encryption Functions

      Function Signatures
      AesEncrypt(cString, cKey, [nMode,
      [nKeySize]])
      AesDecrypt(cString, cKey, [nMode, [nKeySize]])

      Parameters
      cString: String to encrypt/decrypt
      cKey: Encryption Key to use (16, 24, or
      32 characters depending on nKeySize)*

      nMode: AES Mode (1 = ECB 2 = CBC)
      nKeySize: Size of Key in bits (128, 192,
      256)

      * The cKey parameter will
      accept keys that aren’t the right size and either pad or truncate them in order to
      provide the internal FLL function with the correct key length, however this weakens
      the overall security of the AES encryption and is strongly discouraged.

      Download the FLL and Start Using AES in Visual FoxPro
      Here is the download link and some cut-paste-and-execute sample code
      so you can try it out. NOTE: I will be overwriting prior versions of the fll so the
      links always point to the latest version. Also, should you want to see a specific
      cipher or hash implemented in this FLL, or if you have some other suggestions/ideas,
      please feel free to leave me a comment about it and I will see what I can do.

      Download the
      VFP Encryption FLL
      (22 KB approx.)

      Example of Use

      CLEAR
      SET LIBRARY TO LOCFILE(“vfpencryption.fll”)
      #DEFINE ASECRET256BITKEY “LVE*(zz}}’rr)`P%wDq@lc8WWbGw0[77” && Example only,
      make your own 32 character key
      ? “__________________________”
      ? “EXAMPLE #1 (simplest): USES DEFAULT AES – CBC MODE 256-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET256BITKEY)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET256BITKEY)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      ? “EXAMPLE #2: USES AES – ECB MODE 256-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET256BITKEY, 1, 256)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET256BITKEY, 1, 256)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      ? “EXAMPLE #3: USES AES – CBC MODE 256-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET256BITKEY, 2, 256)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET256BITKEY, 2, 256)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      #DEFINE ASECRET192BITKEY “!rPrrj<t!fr7$7L?1#\\;lAV” && Example only, make
      your own 24 character key
      ? “EXAMPLE #4: USES AES – ECB MODE 192-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET192BITKEY, 1, 192)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET192BITKEY, 1, 192)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      ? “EXAMPLE #5: USES AES – CBC MODE 192-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET192BITKEY, 2, 192)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET192BITKEY, 2, 192)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      #DEFINE ASECRET128BITKEY “!rPrrj<t!fr7$7L?1#\\;lAV” && Example only, make
      your own 16 character key
      ? “EXAMPLE #6: USES AES – ECB MODE 128-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET128BITKEY, 1, 128)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET128BITKEY, 1, 128)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString
      ? “__________________________”
      ? “EXAMPLE #7: USES AES – CBC MODE 128-BIT KEY”
      cEncryptedString = AesEncrypt(“Visual FoxPro Rocks!”, ASECRET128BITKEY, 2, 128)
      cDecryptedString = AesDecrypt(cEncryptedString, ASECRET128BITKEY, 2, 128)
      ? “Encrypted: ” + cEncryptedString
      ? “Decrypted: ” + cDecryptedString


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3046959

      Visual FoxPro and Hash Functions

      by craigaaa3 ·

      In reply to The SPS Weblog

      Hashing in Visual FoxPro
      There are a few popular hash functions that I thought made good candidates
      for the VFP Encryption FLL. So, by modifying and adding to some earlier Visual C++
      work by George Anescu I
      implemented the following hashing functions: SHA1, SHA256, SHA384, SHA512, MD5, RIPEMD128,
      and RIPEMD160. They are now all accessible from in Visual FoxPro using a very
      simple Hash() function.

      Bigger but still relatively small
      The hash functions added some size to the FLL that now weighs in at about
      (108 KB), but I think with everything this FLL offers in the way of encryption and
      hashing that it is still a pretty respectable size.

      Additional information on the implemented hash functions
      For additional information on the hash functions now accessible to Visual
      FoxPro refer to the following links:

      http://en.wikipedia.org/wiki/SHA_hash_functions

      http://en.wikipedia.org/wiki/MD5

      http://en.wikipedia.org/wiki/RIPEMD-160

      ReadMe.txt
      I’ve included a ReadMe.txt with the download that shows all of the different
      functions now available in the vfpencryption.fll. I thought this might be a good thing
      to have with the FLL should someone stumble acrossed it in the future and not know
      about this blog. Also, it gives me a place to stick George Anescue’s disclaimer (he’s
      certainly entitled as the work he’s done is great and I appreciate him allowing other
      developers such as myself to use and modify it freely). Here is some information from
      the ReadMe.txt about the Hash() function:

      Function Signature
      Hash(cStringtoHash[, nHashType])

      Parameters
      cString: String to return hash for
      nHashType: (possible values and corresponding hash)
      1 = SHA1 (a.k.a SHA160)  – 160 bit Digest
      2 = SHA256    – 256 bit Digest
      3 = SHA384    – 384 bit Digest
      4 = SHA512 (default hash type)  – 512 bit Digest
      5 = MD5    – 128 bit Digest
      6 = RIPEMD128    – 128 bit Digest
      7 = RIPEMD256    – 256 bit Digest

      Though not always true, it can be generally said of these hash algorithms that the
      longer the Digest is the more secure the hash is. It would be extremely difficult
      to find a collision for a string hashed with SHA512, which is the default for this
      Visual FoxPro Hash() function. A collision, simply put, is when you find another string
      that would produce the same hash.

      In order to represent hashes in the most common form of hexBinary use Visual FoxPro’s
      STRCONV() function. For example:
      ?STRCONV(Hash(“Some String”), 15)

      Download and Code Sample
      As I am adding to this FLL, my examples are designed to just give you enough
      so you know how to use the new functions being implemented. I will be back at a later
      time with blog entries that detail the use of this FLL in real world situations
      for Visual FoxPro. Here is the download link for the FLL and an example of its use:

      Download the
      VFP Encryption FLL
      (50 KB approx.)

      *!* Example of Use *!*
      DIMENSION aryHashTypes(7) && used just for this example, not necessary in
      production code
      aryHashTypes(1) = “SHA1”
      aryHashTypes(2) = “SHA256”
      aryHashTypes(3) = “SHA384”
      aryHashTypes(4) = “SHA512 (default hash type)”
      aryHashTypes(5) = “MD5”
      aryHashTypes(6) = “RIPEMD128”
      aryHashTypes(7) = “RIPEMD256”

      CLEAR
      SET LIBRARY TO LOCFILE(“vfpencryption.fll”)

      LOCAL lnCounter, lcHashDigest
      FOR lnCounter = 1 TO 7 && iterate through all available hashes
       ?aryHashTypes(lnCounter)
       lcHashDigest = Hash(“Visual FoxPro Rocks!”, lnCounter) && here is the
      actual function in use
       ?”Binary Characters:”
       ?lcHashDigest
       ?”hexBinary Equivalent:”
       ?STRCONV(lcHashDigest, 15) && Easy way to get the hexBinary equivalent
       ?
      ENDFOR


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3046935

      Visual FoxPro Random License/Serial Generator

      by craigaaa3 ·

      In reply to The SPS Weblog

      Real World Examples
      In my
      last blog entry
      I mentioned being able to use the vfpencryption.fll in some real
      world ways. While encrypting passwords and sensitve data using the ciphers, or checking
      passwords and files for authenticity using hash functions are pretty well known
      examples, there are others.

      Generating CD Licenses
      What about creating software serial numbers for an application
      you have developed? While I highly recommend a product like Armadillo when
      you need top-notch security, a more simplified approach that is still fairly secure
      can be had using a hashing function such as MD5.

      Phil Fresle’s Earlier Work
      I remembered seeing an example
      of this
      a few years back by a developer named Phil Fresle (back then his example
      was simpler than it is now). And, since the vfpencryption.fll now supports MD5, I
      thought I would revisit his example and see whether something of this nature could
      be created for Visual FoxPro using the vfpencryption.fll.

      Here is the download link and screen shot of what I came up with.

      Download VFP Key
      Generator Example
      – source code included (80 KB approx)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3047287

      Encryption FLL – A Fix, A Simplification, and an Additional Cipher

      by craigaaa3 ·

      In reply to The SPS Weblog

      Important Fixes
      It’s 4:00 AM and I have some pressing stuff that I need to get done for a
      UK client. However, I did dive into the FLL again and I have fixed a couple problems
      that I was alerted to by Glenn Domeracki (by the way, great job Glenn – I really appreciated
      the feedback and repro code). All known issues with the FLL have been fixed.

      Important Changes
      Also, I felt that the Hash function was so simple and elegant, that I would
      try and do the same with the encryption functions. So now there are only two encryption
      functions Encrypt() and Decrypt(). I will make future changes backward compatible,
      but this change had to be made (it makes it far more maintainable and understandable).
      The FLL has only been available on this blog for a couple of days, so I felt if I
      was going to change the function signatures, now was the time.

      I’ve also added another encryption algorithm… Tiny Encryption Algorithm
      (TEA). It’s a secure, blazingly fast, encryption algorithm. So now the FLL gives
      access to: AES128, AES192, AES256, Blowfish, and TEA. And each of them is provided
      in ECB, CBC, and CFB modes. So, that is basically 15 different ways to encrypt strings.

      Still to Come
      I’m still working on the EncryptFile() and DecryptFile()
      functions… should be fully functional and debugged soon. But as I’ve mentioned in
      earlier blog entries, using the STRTOFILE() and FILETOSTR() Visual Foxpro functions
      in conjunction with the FLL functions will give you a way to encrypt files
      until I finish the file manipulation portion.

      OK, I don’t have a lot of time to document the new functions or
      go into them in detail (I’ll be back later), for now here is the download link for
      the VFP Encryption FLL and some sample code (I hope the sample code gives you the
      general idea until I can come back and detail this further).

      Special Thanks to George Anescu
      But before I go… I can’t say enough good stuff about the encryption and
      hashing classes that George Anescu created. This entire project would have been 10
      times as hard without the awesome amount of work he put into his C++ projects. Thanks
      George, and know that it is very much appreciated that you have placed this information
      into the public domain – it has allowed me to create a great derivative work for Visual
      FoxPro. Make sure to read George’s disclaimer that I have been including in the readme.txt
      that comes with the download.

      Download
      the VFP Encryption FLL
       (58 KB approx.)

      *!* Sample Code *!*

      SET LIBRARY TO LOCFILE(“vfpencryption.fll”) && contains encryption and has
      functions for use in Visual FoxPro

      *!* Example Keys – make your own unique keys
      #DEFINE A128BITKEY “!`/_b}B#JXRp}Bsn”
      #DEFINE A192BITKEY “fGSoTa3M?{#NOsOBGqmEd>e'”
      #DEFINE A256BITKEY “LVE*(zz}}’rr)`P%wDq@lc8WWbGw0[77”
      #DEFINE A448BITKEY “:E9}$6+a7ifN)#G’)/&[ZpM$4Z.JOy@M&{^%JFOd2Ew{A?=dxB]RB9un”

      *!* There are three modes for these ciphers
      DIMENSION aryModes(3)
      aryModes(1) = “ECB MODE” && Electronic Code Book
      aryModes(2) = “CBC MODE” && Cipher Block Chaining
      aryModes(3) = “CFB MODE” && Cipher Feedback

      *!* AES (a.k.a. Rijndael) is the king of encryption
      currently – extremely secure
      *!* Blowfish is popular, good mix of security and speed
      *!* Tiny Encryption Algorithm (TEA) is secure and extremely fast

      LOCAL lcStringToEncrypt, lcEncrypted
      lcStringToEncrypt = “Visual FoxPro Rocks!”
      CLEAR
      FOR lnCounter = 0 TO 2 && lets loop through all the available ways to encrypt
      a string (15 in all)
       ?”AES128:(” + aryModes(lnCounter + 1) + “)”
       lcEncrypted = Encrypt(lcStringToEncrypt, A128BITKEY, 0, lnCounter)
       ?lcEncrypted
       ?Decrypt(lcEncrypted, A128BITKEY, 0, lnCounter)
       ?
       ?”AES192:(” + aryModes(lnCounter + 1) + “)”
       lcEncrypted = Encrypt(lcStringToEncrypt, A192BITKEY, 1, lnCounter)
       ?lcEncrypted
       ?Decrypt(lcEncrypted, A192BITKEY, 1, lnCounter)
       ?
       ?”AES256:(” + aryModes(lnCounter + 1) + “)”
       lcEncrypted = Encrypt(lcStringToEncrypt, A256BITKEY, 2, lnCounter)
       ?lcEncrypted
       ?Decrypt(lcEncrypted, A256BITKEY, 2, lnCounter)
       ?
       ?”Blowfish448 – 16 round:(” + aryModes(lnCounter + 1) + “)”
       lcEncrypted = Encrypt(lcStringToEncrypt, A448BITKEY, 4, lnCounter)
       ?lcEncrypted
       ?Decrypt(lcEncrypted, A448BITKEY, 4, lnCounter)
       ?
       ?”TEA128:(” + aryModes(lnCounter + 1) + “)”
       lcEncrypted = Encrypt(lcStringToEncrypt, A128BITKEY, 8, lnCounter)
       ?lcEncrypted
       ?Decrypt(lcEncrypted, A128BITKEY, 8, lnCounter)
       ?
      ENDFOR

      >


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3055458

      Southwest Fox – Speaking and Reporting

      by craigaaa3 ·

      In reply to The SPS Weblog

      As Andy Kramek said in his
      most recent blog entry
      , the conference season is upon us. I couldn’t agree more
      that Southwest Fox is THE conference to go
      to this year.

      I’ll be there and though I’m not up on the speaker’s
      list yet
      , I will be speaking/presenting. I’ll also be covering the confererence
      for the Universal Thread,
      so look for good daily reports by myself and Burt
      Rosen
      .

      If you can find a way to attend this conference, you should. I found some great rates
      on Expedia for flight, hotel, and car packages.
      That’s where I got mine anyways, and I am an avid bargain hunter.

      Make no mistake, Southwest Fox is going to be huge! There is going to be a much
      larger than usual Microsoft presence, the speaker list is packed with the best
      of the best, and I am really looking forward to meeting everyone. Make it a point
      to attend if you can. The Red Bull energy drinks and late night hotel coding/collaboration
      sessions will be on me!

      Hope to see you there


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3055408

      Visual FoxPro – Encrypt and Decrypt Files

      by craigaaa3 ·

      In reply to The SPS Weblog

      Work on the vfpencryption.fll continues at a steady pace (whenever a minute or two
      presents itself). I’ve finished fixing a couple more bugs that were reported to me
      and I’ve finished the EncryptFile() and DecryptFile() functions. Here is the download
      link and some additional information regarding the FLL that will be of use to developers
      who are using it.

      Download the
      Latest Version of the VFP Encryption FLL
      (58 KB approx.)


      Function ENCRYPT()

      Signature: Encrypt(cStringtoEncrypt, cSecretKey[, nEncryptionType[,
      nEncryptionMode]])

      Parameters:

      cStringtoEncrypt – A plain text string that you want
      to have encrypted, such as “Hello World!”

      cSecretKey – A plain text string that is the Key you want
      used during encryption, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of encryption.
      Refer below for more information.

      nEncryptionType – There are currently 5 types of encryption
      available. The value of this parameter determines that type of encryption used and
      how long your Secret Key should be. A single character in Visual FoxPro is  equal
      to 1 byte or 8 bits. So an encryption algorithm requiring a 128-bit key would need
      a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)

      nEncryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      Character data type – the encrypted form of cStringtoEncrypt.

      Remarks:

      When saving the return value of Encrypt() function to a field in a table, remember
      that Visual FoxPro will append blanks to the end of the string in order to fill the
      character field to its designated length. This can cause problems when decrypting
      the data as the spaces will be considered part of the encrypted string. To work around
      this, I suggest placing a single CHR(0) at the end of the encrypted string when saving
      it to the table. Then when decrypting the data just the portion prior to the CHR(0)
      can be sent into the Decrypt() function.


      Function DECRYPT()

      Signature: Decrypt(cEncryptString, cSecretKey[, nDecryptionType[,
      nDecryptionMode]])

      Parameters:

      cEncryptedString – A string that has been encrypted
      using the Encrypt() function.

      cSecretKey – A plain text string that is the same Key that
      you used when you encrypted the data using the Encrypt function, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of decryption.
      Refer below for more information.

      nDecryptionType – There are currently 5 types of decryption
      available and they correspond to the same ones available in Encrypt(). A single character
      in Visual FoxPro is  equal to 1 byte or 8 bits. So an decryption algorithm
      requiring a 128-bit key would need a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)

      nDecryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      Character data type – the decrypted form of cEncryptedString followed by a variable
      number of CHR(0)s. See Remarks below for further clarification

      Remarks:

      IMPORTANT: Decryption is done on blocks of memory, so when
      the decrypt function returns the encrypted string it will be followed by a variable
      number of CHR(0)s unless the decrypted string just happens to end at exactly the same
      location as the last block decrypted. These extraneous CHR(0)’s can be removed using
      a number of Visual FoxPro functions, such as STRTRAN(), CHRTRAN(), or a combination
      of LEFT() and AT().


      Function ENCRYPTFILE()

      Signature: EncryptFile(cFiletoEncrypt, cDestinationFile, cSecretKey[,
      nEncryptionType[, nEncryptionMode]])

      Parameters:

      cFiletoEncrypt – A plain text string that is the fullpath
      to the file you wish to be encrypted, such as “C:\SensitiveInfo.doc”

      cDestinationFile – A plain text string that is the
      fullpath to an encrypted file you wish to have created on disk, such as “C:\EncryptedInfo.doc”.
      If this file doesn’t exist then it will be created for you.

      cSecretKey – A plain text string that is the Key you want
      used during encryption, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of encryption.
      Refer below for more information.

      nEncryptionType – There are currently 5 types of encryption
      available. The value of this parameter determines that type of encryption used and
      how long your Secret Key should be. A single character in Visual FoxPro is  equal
      to 1 byte or 8 bits. So an encryption algorithm requiring a 128-bit key would need
      a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)

      nEncryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      None

      Remarks:

      Currently the cFiletoEncrypt and cDestinationFile parameters cannot point to the same
      file. This may be revised in a future version. But for safety sake, this function
      requires that the original file be left untouched.


      Function DECRYPTFILE()

      Signature: DecryptFile(cEncryptedFile, cDestinationFile, cSecretKey[,
      nDecryptionType[, nDecryptionMode]])

      Parameters:

      cEncyptedFile – A plain text string that is the fullpath
      to the file you wish to be decrypted, such as “C:\EncryptedInfo.doc”

      cDestinationFile – A plain text string that is the
      fullpath to a decrypted file you wish to have created on disk, such as “C:\SensitiveInfo.doc”.
      If this file doesn’t exist then it will be created for you.

      cSecretKey – A plain text string that is the same Key that
      you used when you encrypted the data using the Encrypt function, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of decryption.
      Refer below for more information.

      nDecryptionType – There are currently 5 types of decryption
      available and they correspond to the same ones available in Encrypt(). A single character
      in Visual FoxPro is  equal to 1 byte or 8 bits. So an decryption algorithm
      requiring a 128-bit key would need a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)

      nDecryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      None

      Remarks:

      As with EncryptFile(), the cFiletoEncrypt and cDestinationFile parameters cannot point
      to the same file.


      Function HASH()

      Signature: Hash(cStringtoHash[, nHashType])

      Parameters:

      cStringtoHash – A plain text string
      you wish to have hashed

      nHashType – The type of hash function to generate. There
      are currently 7 different hash functions supported

      1 = SHA1 (a.k.a SHA160)
      2 = SHA256
      3 = SHA384
      4 = SHA512 *Default
      5 = MD5
      6 = RIPEMD128
      7 = RIPEMD256

      Return Value:

      Binary Character Data – the hash for cStringtoHash.

      Remarks:

      The hash is returned as a series of binary characters. However, it is more
      common to see hashes in a hexBinary format. This can be accomplished in Visual FoxPro
      by taking the return of the Hash() function and sending it in as a parameter to the
      STRCONV() function. For example:

      ?STRCONV(Hash(“Some String”), 15) && hexBinary Hash


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3054267

      Encrypt/Decrypt File Fix

      by craigaaa3 ·

      In reply to The SPS Weblog

      Steve Tootill reported that the DecryptFile() function was not working for dbf’s.
      On closer inspection, I found there was a problem with the original Visual C++ code
      that was written by George Anescu from which the encryption and decryption features
      of the vfpencryption.fll is derived.

      The problem is that basically George just returned entire decrypted blocks and didn’t
      take into consideration the original file size. To fix this I have added a single
      byte to the end of the file before it is encrypted that tells the decryption functions
      how long the original file is. This byte is read into memory and the decrypted file
      is sized appropriately… thus eliminating the extraneous padding characters from
      the end of the file. For more detailed information regarding this FLL please refer
      to my earlier post:

      Visual
      FoxPro – Encrypt and Decrypt Files

      Here is the latest download for the VFP Encryption FLL (NOTE: all downloads on this
      weblog for the VFP Encryption FLL point to the latest version)

      Download VFP
      Encryption FLL
      (58 KB approx.)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3054037

      VFP Random Password/Key Generator

      by craigaaa3 ·

      In reply to The SPS Weblog

      Today I’m working on the Encryption/Decryption session I will give at Southwest
      Fox
      . And, while I was on the subject, I thought it would be nice if there was
      a simple way to produce random cryptography keys of a required bit length for certain
      encryption algorithms. So, I decided to create one in Visual FoxPro 9.0. It took all
      of about 10 minutes from start to finish and provides a pretty decent way to create
      random keys. Here is the download link and the customary screen shot.

      Download VFP Password/Key
      Generator Example and Source
      (29 KB approx.)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3065612

      Learning Visual FoxPro Videos

      by craigaaa3 ·

      In reply to The SPS Weblog

      Not enough time
      It’s been a week since my last entry into my blog. Between billable work,
      articles that I’m writing, and getting ready for the Southwest
      Fox
      conference, time has been an extremely precious commodity. If someone finds
      a way to increase the number of hours in a day to 48 using an undocumented API call,
      please let me know.

      Increasing interest in Visual FoxPro
      As interest in Visual FoxPro increases (and it is increasing), there are
      a number of developers out on the forums looking for beginner books for Visual FoxPro.
      I’ve even seen a few people looking for a demo of Visual FoxPro that they can try
      out before making a decision on whether to purchase it (other than an occasional public
      beta, this just doesn’t happen). And regrettably, there just aren’t as many books
      and resources for Visual FoxPro 9.0 as there are for some of the previous versions
      of the product, and few of the books that are out there are geared toward the beginner
      (KiloFox gets
      my vote for the greatest VFP book ever written, but regrettably it’s not the kind
      of text a beginner would find easy to understand and follow).

      Book idea Scrapped
      I started toying with the idea of writing a book on Visual FoxPro for beginners,
      but that would require an extensive commitment in time, and as I’ve said, I don’t
      have a lot of time on my hands these days. I also realized that I didn’t just want
      to provide information for beginners, but also for intermediate and advanced Visual
      FoxPro developers. The book idea was starting to look as if it would be at least 1200
      pages… so, the book idea was obviously not feasible, but that didn’t quench my desire
      to provide something to the Visual FoxPro community that would perhaps be considered
      useful.

      Screencast to the rescue
      I’ve taken an interest in the videos provided at FoxCast,
      and found many of them very informative and useful. There’s something about being
      able to see and hear another developer make a presentation via screencast that
      can’t be duplicated in a book or through a podcast.
      I’m not saying that a screencast is superior in every way, it has its place just as
      the other types of medium do, but what appealed to me most was the ability to relay
      a large amount of information in a short amount of time.

      Learning Visual FoxPro is born
      I’ve also listened to Andrew MacNeill talk about screencasting on the
      FoxShow
      , as well as in an
      article he wrote
      , and I’ve created a number of screencast for application that
      I’ve developed. I’ve found it to be an incredibly easy way to train users and also
      provide perspective users with a way to look at a product before they buy it. And,
      Visual FoxPro is essentially just a software product like any other with developers
      (especially those involved in data centric application development) as its target
      audience.

      So, I’ve begun creating a library of videos that will not only show off Visual FoxPro’s
      abilities, but will hopefully provide viewers with some useful information and insight
      that can help them become better Visual FoxPro developers. The videos will
      be broken down into 3 series. The 100 series (101, 102, 103…) will be for beginner-level
      Visual FoxPro developers. The 200 series will be for intermediate-level Visual
      FoxPro developers. And finally, the 300 series will be for advanced-level Visual
      FoxPro developers.

      Unscripted content
      The narrative for the videos is not scripted. I just have a short outline
      of the subject matter I want to screencast about, open up Visual FoxPro and Go. This
      provides the viewer with a raw look at how I develop in Visual FoxPro which I believe
      is useful. It also allows me to create videos in the shortest amount of time possible.
      It’s sort of like watching a demo
      Ken Levy has done
      for Channel 9, except
      that it’s just my screen and voice.

      In any event, the first video is “101: Creating a Project”. As it is in the 100 series,
      it is targeted toward beginners, but some intermediate developers may still find some
      of the content useful. It will walk the viewer through creating a relatively simple
      Visual FoxPro project from scratch to compile. It is nearly an hour long, so I’ve
      busted it up into 3 seperate .swf files. Each .swf file is about 13 MB give or take
      and the loader you’ll see at the beginning will stay up until 30% of the .swf has
      been loaded. In other words, if you are on Dial-up, forget it. (I did initially create
      a .wmv of the video, but at an acceptable bit-rate the images and audio
      were unacceptably degraded. The .swf was still smaller, with crisp images and
      audio.). Below are the links to the 3 parts as well as a download link for the
      source code that goes along with it. I’ll be back with more videos, including the
      200 and 300 series, and feedback both positive and negative is greatly appreciated.
      I have no doubt that changes will be made in certain areas as I produce more videos,
      so you’re feedback is important and can help me improve the overall usefulness of
      what I’m trying to accomplish here.

      Learning Visual FoxPro
      101: Creating a Project

      Part
      I
       (19:33)

      Part
      II
       (21:06)

      Part
      III
       (18:15)

      Download
      101 Source Code
       (621 KB approx.)


      This weblog is sponsored by SweetPotato
      Software, Inc.

      • #3130337

        Learning Visual FoxPro Videos

        by yehuda ·

        In reply to Learning Visual FoxPro Videos

        Well Done.

        I am a foxpro 2.5 programmer supporting clients still in dos. and this video courses of yours realy gave me a jump start in my training.

        a must see for anyone interested in foxpro.

        waiting for the 200 AND 300 SERIES

         

    • #3065594

      Recent Visual FoxPro Articles

      by craigaaa3 ·

      In reply to The SPS Weblog

      Shameless plug
      As I’ve said in a couple of my past entries, I’ve been writing articles for
      FoxTalk 2.0 and FoxPro Advisor. I think as a community it’s important that we support
      these publications by subscribing to them and/or writing articles for them. They provide
      a lot of bang for the buck and the quality of the Visual FoxPro material they present
      is top-notch; written by some of the greatest Visual FoxPro developers in the world.

      GDI+ series in FoxTalk 2.0
      For FoxTalk 2.0,
      I’ve been doing a series on GDI+ and in the latest article, “GDI+ on VFP9
      Forms: Working with Images”, I show a number of advanced techniques for manipulating
      and displaying images and for rendering content directly on a Visual FoxPro form without
      painting over the controls. This article builds on the techniques presented in the
      first article, and I can tell you, modesty aside, that this second article blows the
      lid off. And, I’m just getting started… so if you’re a FoxTalk 2.0 subscriber look
      forward to more articles on GDI+ and its use in Visual FoxPro. And if you’re not a
      subscriber, I urge you to consider it.

      Dave Stevenson is my editor at FoxTalk 2.0, and he works long and hard on these articles to
      make sure that they are not only grammatically correct, but technically sound as well.
      More than a few of the good ideas that have been presented in my articles came from
      suggestions Dave made.

      One of the things I like best about FoxTalk 2.0 is their willingness to provide
      some of the really valuable content to the Visual FoxPro Community for free online
      (it’s usually the issue’s feature article). For instance, last month they provided
      my article, “GDI+
      on VFP 9 Forms: Solving the Paint Problem
      “, and then this month they freely provided

      Extending the Report Builder’s Multiple Selection Dialog
      ” by Colin Nichols.
      You can find even more free FoxTalk articles from months and years past by doing
      an online search (Google, MSN, Yahoo,
      etc.). FoxTalk has been doing this for a long time, and
      I really feel they deserve our support. Enough said.

      FLL series in FoxPro Advisor
      For FoxPro Advisor (FPA) I’ve
      been doing a series on FLL creation and use. FLLs are Dynamic-Link Libraries written
      in C\C++ that access the Visual FoxPro API (180 + functions). You can do some absolutely
      amazing things with FLLs in Visual FoxPro and hopefully a few of the FLLs I’ve provided
      here on the SPS Blog (such as the vfpencryption.fll) bear that out.

      My first article, “Create and Use FLLs”, is in this month’s issue of FPA, and
      I show the reader how to create an FLL in 10 easy steps using Visual C++ 6 or
      7. I’m prevented from going into further details about upcoming articles by a NDA,
      but they’re intense and as a subscriber you definitely get your money’s worth with
      FPA. As with FoxTalk 2.0, FPA has some of the best and brightest writing for them.

      As a writer it’s fun to write for FPA because they sometimes pass your article on
      to the likes of Tamar Granor and/or Christof Wollenhaupt for editing. There’s nothing
      like having those two critique your article, ask questions, or offer suggestions.
      In case you’re wondering, I held my own. 🙂

      Worth the price of Admission
      FoxTalk 2.0 is a bargain at $139 for print
      and online subscriptions
      and $79 for an online
      only subscription
      . To get an idea of the kind of content you can expect, there
      is a Sample Issue pdf
      online, as well as the free online articles they’ve provided that I mentioned
      above.

      A subscription to FoxPro Advisor is
      $99 per year and they offer a discount if you subscribe for two years ($90 per
      year). They also provide some free articles from time to time, but those articles
      are very seldom indicative of the level of information you will receive in the
      articles available to subscribers only.

      With both of these industry rags, FoxTalk 2.0 and FPA, it’s not just the current
      issues that make subscriptions valuable, it’s also having access to all of the archives.
      The Visual FoxPro resources and code that are in the back issues far outweigh
      the subscription price for a single year any way you slice it.

      If you’re already a subscriber to these magazines, then you know what I’m saying is
      true. And if you’re not yet a subscriber, I hope that I’ve perhaps piqued your interest,
      and that you may decide to subscribe to one or both. You won’t regret it. Free online
      resources are great, but sometimes a product or service is well-worth the price
      of admission.

      PS There’s also the Universal Thread
      Magazine
      and CoDe Magazine, which
      both contain Visual FoxPro content, but I haven’t written articles for either of them.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3058386

      Project LINQ – Can it be done in VFP?

      by craigaaa3 ·

      In reply to The SPS Weblog

      Yag’s blog entry on LINQ
      I was reading some blogs earlier today and I saw that Yag had posted an entry
      out on the VS Data Teams Weblog entitled “Project
      LINQ – Language INtegrated Query (by yag)
      “. Interesting stuff coming out of the
      PDC for sure. He shows a query that is essentially dimensioning a Visual Basic variable
      as a collection using a SQL statement.

      I haven’t seen LINQ yet or been able to play around with it, but I think I get the
      gist of it pretty well from yag’s description. So, that got me to thinking how hard
      would something like that be to do in Visual FoxPro? There are some interesting aspects
      to what yag’s example…

      Dim SmallCountries = Select Country
      _
      From Country In Countries _
      Where Country.Population < 1000000

      …and his description of LINQ show. Being able to use SQL to access objects, data,
      and XML (still just data) and return collections of objects or perhaps other constructs
      is interesting to me anyways. But implementing something similar in Visual FoxPro doesn’t
      strike me as terribly difficult (here again, bear in mind that I have not seen LINQ
      and I could be talking out of my proverbial back-side right now… I’ll know more
      when I get my hands on it), in fact, given Visual FoxPro’s ability to manipulate data,
      XML, and objects, it is a perfect fit for this sort of extension. I don’t
      wish to take anything away from the hard work that MS did to come up with LINQ. I
      merely wish to take that idea and run with it for a little bit in Visual FoxPro. Can
      you blame me?

      A few disclaimers
      Now the SQL Parsing engine they are using in LINQ is surely heads and shoulders
      above what I’m about to show you, please remember that I’ve spent a total of about
      1 hour on this and part of that time was spent getting a list of countries and stats
      for the example. I just wanted to show a proof-of-concept for now. I’ll let it roll
      around in my head for a few days, and also look for feedback from the VFP Community, before
      I decide whether I want to get down to some serious code writing with this thing or
      not. And, this example only shows running queries against a collection. Data and XML
      will come later, but I don’t perceive any real stumbling blocks there either… some
      tedious work perhaps, but no show-stoppers.

      VOSQL, a proof-of-concept
      I call this thing “Visual FoxPro Object-Oriented SQL (VOSQL)”. Copy-n-paste
      the code below into a PRG and execute it from within VFP. There’s a lot of code, but
      most of it is just creating the extensive cursor of countries that I use to populate
      the countries collection. If you look, the VOSQL class is rather short (almost laughable
      for the amount of functionality it already gives). I’ve made this example a little
      more difficult then Yag’s, by adding an additional World collection to hold the countries
      and showing some more complex SQL statements (I couldn’t let the .NET family have
      all the fun). Here’s the code (be sure and try some of your own SQL statements as
      well)…

      *!* Cut-N-Paste the following code into a PRG and
      execute it
      PRIVATE oWorld AS world
      LOCAL loVOSQL AS VOSQL, loCountry as country

      DO CreateCountryCursor && This is just to
      give us some sample data from which to pull our countries

      *!* Fill the World Collection
      oWorld = CREATEOBJECT(“world”)
      SELECT crsCountry
      SCAN ALL
       oWorld.countries.ADD(CREATEOBJECT(“Country”, ALLTRIM(crsCountry.country), 
      ALLTRIM(crsCountry.capital), crsCountry.area, crsCountry.population))
      ENDSCAN

      USE IN SELECT(“crsCountry”) && close it now
      that we’re done

      ************************************
      *!* Example Queries using the VOSQL object
      ************************************
      loVOSQL = CREATEOBJECT(“VOSQL”)

      *!* Query #1
      colCountries = loVOSQL.ObjectQuery(“SELECT Country FROM oWorld.Countries WHERE Population
      < 1000000”)
      FOR EACH loCountry IN colCountries
       ?loCountry.cName + [ – ] + TRANSFORM(loCountry.population)
      ENDFOR
      ?

      *!* Query #2
      colCountries = loVOSQL.ObjectQuery(“Select Country from oWorld.Countries Where 2500000
      < Area AND (Population > 20000000 or alltrim(cName) = [Kazakhstan])”)
      FOR EACH loCountry IN colCountries
       ?loCountry.cName
      ENDFOR
      ?

      *!* Query #3
      colCountries = loVOSQL.ObjectQuery(“SELECT Country FROM oWorld.Countries WHERE 2500000
      < Area AND (Population > 20000000 or alltrim(cName) = [Kazakhstan])  ORDER
      BY Capital”)
      FOR EACH loCountry IN colCountries
       ?loCountry.cName
      ENDFOR
      ?

      ************************************
      *!* Classes we are querying against
      ************************************
      DEFINE CLASS country AS CUSTOM
       cName = “Unknown”
       capital = “Unknown”
       area = 0
       population = 0
       PROCEDURE INIT (tcName, tcCapital, tnArea, tnPopulation)
        WITH THIS
         .cName = tcName
         .capital = tcCapital
         .area = tnArea
         .population = tnPopulation
        ENDWITH
       ENDPROC
      ENDDEFINE

      DEFINE CLASS world AS CUSTOM
       Name = “Earth”
       ADD OBJECT countries AS countries
      ENDDEFINE

      DEFINE CLASS countries AS COLLECTION
      ENDDEFINE

      ************************************
      *!* This is the actual object that does the work
      ************************************
      DEFINE CLASS VOSQL AS CUSTOM
       PROCEDURE ObjectQuery (tcOSQL)
        LOCAL lcSelect, lcFrom, loFrom, lcWhere, lcOrderBy, lnDescending, lnAscending,
      loReturn, loItem, lcReturnName, ;
         lnCounter, lnPropCount, llWhereProcessed
        lcFrom = STREXTRACT(tcOSQL, ” FROM ” , ” WHERE “, 1, 3)
        loReturn = CREATEOBJECT(“Collection”)
        loFrom = &lcFrom
        IF loFrom.COUNT > 1
         llWhereProcessed = .F.
         lcSelect = UPPER(STREXTRACT(tcOSQL, “SELECT ” , ” FROM “, 1, 1))
         lcWhere = ” ” + STREXTRACT(tcOSQL, ” WHERE ” , ” ORDER BY “, 1,
      3)
         lcOrderBy = STREXTRACT(tcOSQL, ” ORDER BY ” , “”, 1, 3)
         lnDescending = ATC(” DESC”, lcOrderBy)
         IF lnDescending > 0
          lcOrderBy = LEFT(lcOrderBy, lnDescending – 1)
         ENDIF
         lnAscending = ATC(” ASC”, lcOrderBy)
         IF lnAscending > 0
          lcOrderBy = LEFT(lcOrderBy, lnAscending – 1)
         ENDIF
         
         FOR lnCounter = 1 TO loFrom.COUNT
          loItem = loFrom.ITEM(lnCounter)
          IF UPPER(loItem.CLASS) == lcSelect
           IF !llWhereProcessed
            THIS.processwhereclause(@lcWhere, loItem)
            llWhereProcessed = .T.
           ENDIF
           IF EMPTY(lcWhere) OR EVALUATE(lcWhere)
            IF EMPTY(lcOrderby)
             loReturn.ADD(loItem)
            ELSE
             loReturn.ADD(loItem, TRANSFORM(EVALUATE(“loItem.”
      + lcOrderby)))
            ENDIF
           ENDIF
          ENDIF
         ENDFOR
        ENDIF
        IF !EMPTY(lcOrderby)
         IF lnDescending > 0
          loReturn.Keysort = 3
         ELSE
          loReturn.Keysort = 2
         ENDIF
        ENDIF
        RETURN loReturn
       ENDPROC

       PROCEDURE processwhereclause (tcWhere, toItem)
        LOCAL lnCounter, lnMax
        lnMax = AMEMBERS(aryProps, toItem, 0)
        FOR lnCounter = 1 TO lnMax
         tcWhere = STRTRAN(tcWhere, ” ” + ALLTRIM(aryProps(lnCounter)), ”
      loItem.” + aryProps(lnCounter), 1, -1, 1)
         tcWhere = STRTRAN(tcWhere, “(” + ALLTRIM(aryProps(lnCounter)), “(loItem.”
      + aryProps(lnCounter), 1, -1, 1)
        ENDFOR
       ENDPROC
      ENDDEFINE

      ************************************
      *!* This is just to produce data for this sample
      ************************************
      PROCEDURE CreateCountryCursor
       CREATE CURSOR crsCountry(country c(21), capital c(19), area I, population I)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Afghanistan”,
      “Kabul”, 647500, 29928987)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Albania”,
      “Tirane”, 28748, 3563112)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Algeria”,
      “Algiers”, 2381740, 32531853)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Andorra”,
      “Andorra la Vella”, 468, 70549)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Angola”,
      “Luanda”, 1246700, 11190786)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Antigua
      and Bar”, “St. John’s”, 443, 68722)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Argentina”,
      “Buenos Aires”, 2766890, 39537943)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Armenia”,
      “Yerevan”, 29800, 2982904)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Australia”,
      “Canberra”, 7686850, 20090437)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Austria”,
      “Vienna”, 83858, 8184691)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Azerbaijan”,
      “Baku”, 86600, 7911974)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bahamas,
      The”, “Nassau”, 13940, 301790)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bahrain”,
      “Al-Manamah”, 665, 688345)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bangladesh”,
      “Dhaka”, 144000, 144319628)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Barbados”,
      “Bridgetown”, 431, 279254)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Belarus”,
      “Mensk (Minsk)”, 207600, 10300483)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Belgium”,
      “Brussels”, 30510, 10364388)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Belize”,
      “Belmopan”, 22966, 279457)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Benin”,
      “Porto-Novo”, 112620, 7460025)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bhutan”,
      “Thimphu”, 47000, 2232291)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bolivia”,
      “La Paz”, 1098580, 8857870)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bosnia and
      Herz”, “Sarajevo”, 51129, 4025476)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Botswana”,
      “Gaborone”, 600370, 1640115)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Brazil”,
      “Bras?lia”, 8511965, 186112794)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Brunei”,
      “Bandar Seri Begawan”, 5770, 372361)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Bulgaria”,
      “Sofia”, 110910, 7450349)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Burkina
      Faso”, “Ouagadougou”, 274200, 13925313)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Burundi”,
      “Bujumbura”, 27830, 6370609)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cambodia”,
      “Phnom Penh”, 181040, 13607069)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cameroon”,
      “Yaounde”, 475440, 16380005)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Canada”,
      “Ottawa”, 9984670, 32805041)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cape Verde”,
      “Praia”, 4033, 418224)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Central
      African”, “Bangui”, 622984, 3799897)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Chad”, “N’Djamena”,
      1284000, 9826419)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Chile”,
      “Santiago”, 756950, 15980912)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“China”,
      “Beijing”, 9596960, 1306313812)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Colombia”,
      “Bogat “, 1138910, 42954279)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Comoros”,
      “Moroni”, 2170, 671247)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Congo, Republic”,
      “Brazzaville”, 342000, 3039126)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Congo, Democrat”,
      “Kinshasa”, 2345410, 60085004)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Costa Rica”,
      “San Jose”, 51100, 4016173)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cote d’Ivoire”,
      “Yamoussoukro”, 322460, 17298040)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Croatia”,
      “Zagreb”, 56542, 4495904)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cuba”, “Havana”,
      110860, 11346670)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Cyprus”,
      “Nicosia”, 9250, 780133)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Czech Republic”,
      “Prague”, 78866, 10241138)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Denmark”,
      “Copenhagen”, 43094, 5432335)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Djibouti”,
      “Djibouti”, 23000, 476703)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Dominica”,
      “Roseau”, 754, 69029)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Dominican
      Repub”, “Santo Domingo”, 48730, 8950034)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“East Timor”,
      “Dili”, 15007, 1040880)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Ecuador”,
      “Quito”, 283560, 13363593)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Egypt”,
      “Cairo”, 1001450, 77505756)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“El Salvador”,
      “San Salvador”, 21040, 6704932)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Equatorial
      Guin”, “Malabo”, 28051, 535881)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Eritrea”,
      “Asmara”, 121320, 4561599)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Estonia”,
      “Tallinn”, 45226, 1332893)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Ethiopia”,
      “Addis Ababa”, 1127127, 73053286)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Fiji”, “Suva”,
      18270, 893354)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Finland”,
      “Helsinki”, 337030, 5223442)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“France”,
      “Paris”, 547030, 60656178)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Gabon”,
      “Libreville”, 267667, 1389201)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Gambia,
      The”, “Banjul”, 11300, 1593256)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Georgia”,
      “Tbilisi”, 69700, 4677401)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Germany”,
      “Berlin”, 357021, 82431390)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Ghana”,
      “Accra”, 239460, 21029853)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Greece”,
      “Athens”, 131940, 10668354)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Grenada”,
      “St. George’s”, 344, 89502)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Guatemala”,
      “Guatemala City”, 108890, 14655189)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Guinea”,
      “Conakry”, 245857, 9467866)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Guinea-Bissau”,
      “Bissau”, 36120, 1416027)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Guyana”,
      “Georgetown”, 214970, 765283)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Haiti”,
      “Port-au-Prince”, 27750, 8121622)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Honduras”,
      “Tegucigalpa”, 112090, 6975204)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Hungary”,
      “Budapest”, 93030, 10006835)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Iceland”,
      “Reykjavik”, 103000, 296737)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“India”,
      “New Delhi”, 3287590, 1080264388)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Indonesia”,
      “Jakarta”, 1919440, 241973879)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Iran”, “Tehran”,
      1648000, 68017860)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Iraq”, “Baghdad”,
      437072, 26074906)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Ireland”,
      “Dublin”, 70280, 4015676)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Israel”,
      “Jerusalem”, 20770, 6276883)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Italy”,
      “Rome”, 301230, 58103033)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Jamaica”,
      “Kingston”, 10991, 2731832)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Japan”,
      “Tokyo”, 377835, 127417244)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Jordan”,
      “Amman”, 92300, 5759732)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Kazakhstan”,
      “Almaty”, 2717300, 15185844)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Kenya”,
      “Nairobi”, 582650, 33829590)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Kiribati”,
      “Tarawa”, 811, 103092)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Korea, North”,
      “Pyongyang”, 120540, 22912177)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Korea, South”,
      “Seoul”, 98480, 48422644)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Kuwait”,
      “Kuwait City”, 17820, 2335648)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Kyrgyzstan”,
      “Bishkek”, 198500, 5146281)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Laos”, “Vientiane”,
      236800, 6217141)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Latvia”,
      “Riga”, 64589, 2290237)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Lebanon”,
      “Beirut”, 10400, 3826018)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Lesotho”,
      “Maseru”, 30355, 1867035)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Liberia”,
      “Monrovia”, 111370, 3482211)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Libya”,
      “Tripoli”, 1759540, 5765563)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Liechtenstein”,
      “Vaduz”, 160, 33717)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Lithuania”,
      “Vilnius”, 65200, 3596617)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Luxembourg”,
      “Luxembourg”, 2586, 468571)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Macedonia”,
      “Skopje”, 25333, 2045262)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Madagascar”,
      “Antananarivo”, 587040, 18040341)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Malawi”,
      “Lilongwe”, 118480, 12158924)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Malaysia”,
      “Kuala Lumpur”, 329750, 23953136)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Maldives”,
      “Male”, 300, 349106)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mali”, “Bamako”,
      1240000, 12291529)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Malta”,
      “Valletta”, 316, 398534)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Marshall
      Island”, “Majuro”, 181, 59071)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mauritania”,
      “Nouakchott”, 1030700, 3086859)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mauritius”,
      “Port Louis”, 2040, 1230602)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mexico”,
      “Mexico City”, 1972550, 106202903)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Micronesia,
      Fed”, “Palikir”, 702, 108105)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Moldova”,
      “Chisinau”, 33843, 4455421)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Monaco”,
      “Monaco”, 2, 32409)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mongolia”,
      “Ulan Bator”, 1565000, 2791272)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Morocco”,
      “Rabat”, 446550, 32725847)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Mozambique”,
      “Maputo”, 801590, 19406703)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Myanmar
      (Burma)”, “Rangoon”, 678500, 42909464)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Namibia”,
      “Windhoek”, 825418, 2030692)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Nauru”,
      “Yaren”, 21, 13048)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Nepal”,
      “Kathmandu”, 140800, 27676547)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Netherlands”,
      “Amsterdam”, 41526, 16407491)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“New Zealand”,
      “Wellington”, 268680, 4035461)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Nicaragua”,
      “Managua”, 129494, 5465100)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Niger”,
      “Niamey”, 1267000, 11665937)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Nigeria”,
      “Abuja”, 923768, 128771988)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Norway”,
      “Oslo”, 324220, 4593041)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Oman”, “Muscat”,
      212460, 3001583)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Pakistan”,
      “Islamabad”, 803940, 162419946)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Palau”,
      “Koror”, 458, 20303)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Panama”,
      “Panama City”, 78200, 3039150)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Papua New
      Guine”, “Port Moresby”, 462840, 5545268)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Paraguay”,
      “Asuncion”, 406750, 6347884)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Peru”, “Lima”,
      1285220, 27925628)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Philippines”,
      “Manila”, 300000, 87857473)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Poland”,
      “Warsaw”, 312685, 38635144)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Portugal”,
      “Lisbon”, 92391, 10566212)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Qatar”,
      “Doha”, 11437, 863051)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Romania”,
      “Bucharest”, 237500, 22329977)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Russia”,
      “Moscow”, 17075200, 143420309)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Rwanda”,
      “Kigali”, 26338, 8440820)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“St. Kitts
      and N”, “Basseterre”, 261, 38958)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“St. Lucia”,
      “Castries”, 616, 166312)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“St. Vincent
      and”, “Kingstown”, 389, 117534)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Samoa”,
      “Apia”, 2944, 177287)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“San Marino”,
      “San Marino”, 61, 28880)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Sao Tome
      and Principe”, “Sao Tome”, 1001, 187410)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Saudi Arabia”,
      “Riyadh”, 1960582, 26417599)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Senegal”,
      “Dakar”, 196190, 11126832)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Serbia and
      Mont”, “Belgrade”, 102350, 10829175)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Seychelles”,
      “Victoria”, 455, 81188)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Sierra Leone”,
      “Freetown”, 71740, 6017643)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Singapore”,
      “Singapore”, 693, 4425720)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Slovakia”,
      “Bratislava”, 48845, 5431363)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Slovenia”,
      “Ljubljana”, 20273, 2011070)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Solomon
      Islands”, “Honiara”, 28450, 538032)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Somalia”,
      “Mogadishu”, 637657, 8591629)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“South Africa”,
      “Pretoria”, 1219912, 44344136)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Spain”,
      “Madrid”, 504782, 40341462)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Sri Lanka”,
      “Colombo”, 65610, 20064776)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Sudan”,
      “Khartoum”, 2505810, 40187486)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Suriname”,
      “Paramaribo”, 163270, 438144)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Swaziland”,
      “Mbabane”, 17363, 1173900)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Sweden”,
      “Stockholm”, 449964, 9001774)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Switzerland”,
      “Bern”, 41290, 7489370)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Syria”,
      “Damascus”, 185180, 18448752)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Taiwan”,
      “Taipei”, 35980, 22894384)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Tajikistan”,
      “Dushanbe”, 143100, 7163506)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Tanzania”,
      “Dar es Salaam”, 945087, 36766356)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Thailand”,
      “Bangkok”, 514000, 65444371)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Togo”, “Lome”,
      56785, 5681519)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Tonga”,
      “Nuku’alofa”, 748, 112422)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Trinidad
      and To”, “Port-of-Spain”, 5128, 1088644)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Tunisia”,
      “Tunis”, 163610, 10074951)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Turkey”,
      “Ankara”, 780580, 69660559)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Turkmenistan”,
      “Ashgabat”, 488100, 4952081)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Tuvalu”,
      “Funafuti”, 26, 11636)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Uganda”,
      “Kampala”, 236040, 27269482)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Ukraine”,
      “Kyiv (Kiev)”, 603700, 47425336)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“United Arab
      Emi”, “Abu Dhabi”, 82880, 2563212)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“United Kingdom”,
      “London”, 244820, 60441457)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“United States”,
      “Washington, D.C.”, 9629091, 295734134)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Uruguay”,
      “Montevideo”, 176220, 3415920)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Uzbekistan”,
      “Tashkent”, 447400, 26851195)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Vanuatu”,
      “Vila”, 12200, 205754)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Vatican
      City”, “”, 0, 921)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Venezuela”,
      “Caracas”, 912050, 25375281)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Vietnam”,
      “Hanoi”, 329560, 83535576)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Western
      Sahara”, “”, 266000, 273008)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Yemen”,
      “Sana “, 527970, 20727063)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Zambia”,
      “Lusaka”, 752614, 11261795)
       INSERT INTO crsCountry(country, capital, area, population) VALUES (“Zimbabwe”,
      “Harare”, 390580, 12746990)
      ENDPROC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3059522

      Goodbye Drew

      by craigaaa3 ·

      In reply to The SPS Weblog

      I offer my sincerest
      condolences to Drew’s family and friends for their loss. I wish there were more that
      I could say or do. Truly a sad day. – Craig


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3062205

      Visual FoxPro SP1 Available via Public Beta

      by craigaaa3 ·

      In reply to The SPS Weblog

      Here’s a chance for community members to pitch in and improve our beloved product.
      Get your copy of the Visual
      FoxPro SP1 Beta
      and post your bug findings on the Universal
      Thread
      . The actual service pack is due out in early December of this year, so
      there isn’t much time to make sure that bugs that are still in the product get addressed.
      I encourage every member of the VFP Community to at least make an effort to find and
      report bugs based on their findings in the SP1 beta. Not only will your efforts potentially
      help improve the product, but they can also serve to show MS that Public Betas are
      the way to go with Visual FoxPro. I’ll be over here doing my part.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3072674

      October 2005 – Letter from the Editor

      by craigaaa3 ·

      In reply to The SPS Weblog

      The latest Letter from the Editor has
      been posted by Ken Levy. They’ve put the What’s
      New in Nine
      book online, and it seems I’ve been made a Visual FoxPro MVP.
      Sorry I don’t have longer to bore you all with an overly egotistical acceptance speech,
      but I’m up to my neck in alligators at this end and as I recently told Bob
      Kocher, if I don’t stay buried in code I am liable to be eatin. Thanks to MS and the
      VFP Community for the increasing prevalence of Visual FoxPro-related content
      and resources online, and to whoever put my name in the hat and ultimately voted me
      into the MVP fold. Now, if you’ll excuse me I gotta go tend to some gators.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3060266

      SPS Blog Referral Links Fixed

      by craigaaa3 ·

      In reply to The SPS Weblog

      To anyone who was having problems accessing this site via a hyperlink, my apologies.
      An errant referral blacklist was causing dasBlog to generate 404 errors when accessed
      via a referral link on another site. Basically all hyperlinks, including the ones
      from the SweetPotato Software site were down.

      I first became aware of this problem by a post Vincent made over on the Universal
      Thread
      and I spent a portion of yesterday tweaking this Blog and the server
      trying to figure out what the problem was (which is why those of you that are using
      news aggregators probably ended up with double entries for all the previous blog entries
      – sorry about that). I was nearly to the point of reinstalling IIS on the server when
      I decided to post a question regarding my problems over on Tek-Tips.
      Wullie, a Tek-Tips member, pointed out that the only thing that would be different
      when using a hyperlink as opposed to accessing it via a news aggregator or putting
      the URL in the address bar directly (both of which still worked) would be the referral.
      So based on Wullie’s suggestion I played with the settings for the referral blacklists
      and the problem was solved in a matter of minutes. Wullie saved me countless hours
      of work and left me wondering why I hadn’t thought of that.

      In any event, the SPS Blog referral links are now working, and my sincerest apologies
      to any readers who experienced a problem accessing the site. Once again the online
      forums have proved invaluable to me.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3069823

      Alex Feldstein awarded MVP 5th year in a row

      by craigaaa3 ·

      In reply to The SPS Weblog

      Alex Feldstein has received the MVP
      Award for a 5th consecutive year
      . Congratulations Alex! You definitely deserve
      this award and please know that your contributions to the Visual FoxPro Community
      are appreciated by far more than just Microsoft. Thank you for all your contributions
      over the years and keep up the great work.

      For anyone who may be unfamiliar with Alex (doubt there are many who haven’t heard
      of him or seen his work somewhere online) head on over to http://www.feldstein.net/


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3059982

      Southwest Fox 2005

      by craigaaa3 ·

      In reply to The SPS Weblog

      Other than having to run across the entire breadth of the Denver airport in ten
      minutes to make my final connection to Phoenix, the trip down here was good. Though a
      few other hurdles and minor inconveniences were waiting for me when I got here…
      I won’t bore you with the details of a car reservation debacle or the withdrawals
      I was going through due to a lack of internet connectivity, I’ll just say that I am
      glad to be here, that the lobby of the Sheraton hotel has excellent wifi which they
      are kindly allowing me to use at less than $10 per day and that I almost feel settled
      in and ready for the festivities to start.

      I’m not exactly sure yet how this whole thing is going to unfold but I will be reporting
      for the Universal Thread
      starting tomorrow. So, please look there for my comments
      and good Southwest Fox conference information as well as pictures (I brought my digital
      camera and may even record some video if the mood strikes me). This will probably
      be my only blog entry while down here as I don’t want to take away from the value
      of the content that I will be posting on the UT and I probably won’t have much left
      to say about the goings on down here once I am done typing up my daily report anyways.
      Anything I posted here would be redundant I guess.

      In any event, I am here and I expect to have my socks blown off by some of the other
      presenters and the MS representatives that are attending… and hopefully I can do
      the same. I am really fired up about this conference, about the content that is going
      to be presented, and about the attendees/speaker list that has been created for it…
      this conference should be awesome and perhaps a bit of a kick-off for things to come
      in the next couple years for VFP. Have you ever had that feeling that things were
      just about to get really interesting? If so, you know how I feel.

      Well, I got a lot of stuff to do and get done now that I am online, so if you’ll excuse
      me. I’ll be back on that UT page tomorrow with my first report from Southwest Fox
      2005!


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3072289

      Want to invent VFP’s future?

      by craigaaa3 ·

      In reply to The SPS Weblog

      http://codegallery.gotdotnet.com/sednax

      “You can?t predict the future . . . but you can invent it” – Dennis Gabor

      I have long since tired of the endless conjecture and distorted perception by some
      that MS is the one holding all the cards or that MS has a secret plan to end VFP.
      With the extensibility that is in Visual FoxPro already, VFP developers could make
      versions 10, 11, 12, and 13 all on their own. And now Sedna is in the works which
      has Extensibility as one of its two central goals. So, things are going to be opened
      up even further in the not too distant future. We get the greatest version of the
      product since the beginning of time, a road map laying out the future plans and core
      tenets for future enhancements, MS is showing up at the Southwest Fox Conference in
      force (I count 3 representatives and Randy Brown), demos of VFP running on Windows
      Vista and some early examples of proposed Sedna enhancements, an approved budget and
      support through 2014 and that is somehow MS’s way of killing VFP? At the risk of being
      impolite and perhaps less than my usual diplomatic self… Get real.

      The future or demise of Visual FoxPro has way more to do with the Visual FoxPro Community
      than anything the folks in Redmond are doing or will do. If you’re looking for an
      example of a community effort, Firefox is a wonderful example of what a community
      is capable of. We’ve got the community, and the core (VFP 9), to make almost anything
      possible. With access and compatibility being added for Windows Vista, the new Windows
      API, Windows Presentation Foundation (Avalon), Windows Communication Foundation (Indigo),
      and the .NET Framework. There will be plenty of new versions of Visual FoxPro. The
      VFP model that the roadmap lays out is exactly the kind of model that works these
      days and project after project has been coming out showing that this model works best
      and ecclipses anything else it is put up against. Open it up and let developers improve
      on it and create add-ons for it.

      We’re not short on brilliant and talented individuals in this community either – some
      people act like all the greats have gone to either open source or .NET – that’s nothing
      short of nonsense. And more than a few of the individuals that are cited as having
      left the VFP Community and MS behind still make a significant portion of their bread
      and butter with VFP and MS products (though they are hard pressed to admit it at times).
      People have even started touting incomplete, extremely marginal development tools
      and languages as the answer to all of these fictional problems they say exist for
      Visual FoxPro and the developers that work in it. Throw it all out and start using
      something that cannot begin to match the longevity, the functionality, or the supportive
      customer base that Visual FoxPro has? More nonsense. Wanna make a good living, do
      some good for your customers, and continue to build on what you and your customers
      know? Then stick with Visual FoxPro and MS.

      Do I like every decision that MS makes? No. Do I blindly follow them around and spout
      there marketing rhetoric every chance I get? Absolutely not. Do I think that Visual
      FoxPro is going to end up bigger than Visual Studio sometime tomorrow? No. I’m just
      saying that Visual FoxPro is very viable – it has been and WILL BE for a long time
      to come. And for all of the faults MS has, that’s where most customers are and most
      of the jobs are, and where they’re gonna be for many years to come. MS knows how to
      win, whether you like it or not. And their products appeal to most of the customers
      on the face of this earth, whether you like it or not. And they employ some of the
      most talented IT people on the face of the earth, but for some reason along comes
      a few naysayers and a significant portion of the VFP Community is freaking out. MS
      is fine, VFP is fine and it is time that cooler more pragmatic heads should prevail.

      Rather than being scared and worrying needlessly about the future, isn’t it time we
      all did something to improve it? Great things are coming and this ride is just getting
      started. I sincerely urge every VFP developer to hang on to their hats cause it is
      really going to get intense in the next few years! And if you’ve come to the conclusion
      that MS and a significant portion of the VFP Community are convinced that VFP is all
      but done… I’m afraid you’re living in a bubble. I just cannot figure how those given
      to fear, uncertainty, and doubt are so unable to see the potential and reality of
      what lies ahead. I guess we could all just keep touting facts, incidents, and even
      fairy tales that prove things one way or the other, but there’s not a whole lot of
      benefit in that. I’d much rather we spent the day and implemented XML Serialization
      for Visual FoxPro, or finished the GDI+ class library for VFP, or worked on an improved
      CursorAdapter class, or created some cool data presentation classes, or came out with
      a suite of Report Preview applications and add-ons, implemented something similar
      to LINQ, or took out an ad in the New York Times. 🙂 All of those things would serve
      us, the Community (and ultimately Visual FoxPro) a thousand times better than whatever
      ship jumping evacuation plan has been proposed to ensure that you and your customers
      end up drowning as quickly as possible.

      Join me and many other VFP Community members in the SednaX project that was launched
      at the Southwest Fox conference. Anyone who is tired of developers who lack vision,
      strength, and the fortitude to change the future… Anyone who has a great idea for
      improving Visual FoxPro… Anyone who isn’t scared to jump in with both feet and fight
      for a goal larger than life… Anyone who thinks open source initiatives for Visual
      FoxPro rock… Anyone who is tired of seeing VFP components tucked away in a million
      different pockets on the web with very little documentation and very little support…
      Anyone who truly wants to make a VFP difference… is STRONGLY encouraged to immediately
      sign-up for the SednaX project. This is not my project, or Microsoft’s project, this
      is the VFP Community’s project. It’s time we show everyone what a bunch of experienced
      developers working with a mature, battle tested, data centric tool can do. The ball
      is in our court. We can make a difference, we can invent our future. Here’s the link:

      http://codegallery.gotdotnet.com/sednax

      “You can?t predict the future . . . but you can invent it” – Dennis Gabor


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3046099

      Ken Levy’s Blog gets active – KenX is Alive!

      by craigaaa3 ·

      In reply to The SPS Weblog

      Well, after months of just a post or two (usually regarding the Letter from the Editor
      being online) and the occasional blitz of entries on what the greatest headphones
      on earth are (Ultimate Ears in case you’re wondering), Ken Levy is beginning to post
      more VFP content. Heck, there was even
      an entry that showed up a moment ago
      that contains some VFP code in it. Looks
      like the VFP Community aren’t the only ones that are getting excited about Sedna, SednaX,
      and the possibilities for the future. I am really psyched about this recent activity
      on Ken’s blog and looking forward to more. Blogs are playing an ever increasing role
      in providing the VFP Community with timely information and great VFP content, not
      to mention raising VFP awareness among other IT communities. No one is in a better
      position to lead the charge than Ken, so I am very pleased to see the recent activity
      on his blog and to have his promise that more is on the way.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3113945

      Breakfast with Ken and Rod

      by craigaaa3 ·

      In reply to The SPS Weblog

      The day before yesterday I received a call from Ken
      Levy
      and Rod Paddock. They were
      in Sioux Falls and wanted to know if I wanted to hook up for breakfast at Perkins
      at 6:30 the following morning. I said I’d love to and the following morning there
      we all were, in perhaps the most unlikely place on earth having breakfast.

      I hadn’t met Rod before, but knew of him as the Editor-in Chief of Code
      Magazine
       and had just read his Sept./Oct. Code Magazine article “Security
      Is Job One!” a few weeks prior. It was good to finally meet him in person and have
      an opportunity to size him up. For those of you wondering, Rod struck me as a no-nonsense
      developer with a clear vision of his future. He also seems like the kind of guy that
      would own all the latest tailgate party equipment and makes liberal use of face paint
      prior to the big game. Go Seahawks! I don’t know if Rod likes football or not, but
      I do know he likes poker, so him and I may have to venture over to a local casino
      I know of on his next trip in. In any event, he was personable and came across as
      a developer that knows his stuff. As Rod makes several trips up this way every year,
      I am looking forward to getting together with him on occasion.

      Ken was in rare form… he had finished downing what looked like a chocolate shake
      before I came in, so between his usual energy and that added by the chocolate and
      sugar he was really on fire. We talked at length about Sedna and
      how excited everyone was by the things being done and worked on for it. We also talked
      about SednaX and the Visual
      FoxPro Community. It was all very positive. Visual FoxPro is on the move and between
      now and 2007 it is going to be a very exciting time for us all. I’m psyched, Ken Levy
      is jazzed, the VFP Community is on fire and Rod Paddock has a straight-flush at the
      turn and just checked to the bidder.

      Some of you may have been thinking that I had fallen off the planet (given the lack
      of blog postings), but nothing could be further from the truth. I am working on GDI+
      stuff (with Bo Durban) and LINQ stuff for Visual FoxPro (this stuff is guaranteed
      to blow doors off). I have also been handling a lot of administrative duties
      for SednaX (working with Doug Hennig and Rick Schummer to get everything in place
      so we can start working on all the projects that will be covered by SednaX). Administrative
      stuff isn’t as much fun or as glamorous as producing cool VFP examples, but it is
      a necessary evil if SednaX is to become what was envisioned. In the end, SednaX will
      be far more valuable to the VFP Community than anything I could produce on my own.
      I really appreciate Doug and Rick helping out… I don’t think I could manage this
      entire thing in my spare time alone.

      One final note, I’ve scheduled some time in to heat this blog back up. So, thank you
      for your patience and know that the SPS Weblog will return to its former-self shortly.

      Oh, and Rod… I fold.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3043939

      VFPEncryption.FLL Update

      by craigaaa3 ·

      In reply to The SPS Weblog

      The free vfpencryption.fll has been updated. Changes include:

      • Converted the vfpencryption project to Visual Studio 2005 (VC++ 8.0)
      • Added an RC4 Stream Cipher
      • Fixed a bug in the Hash() function that would truncate hashes if NULLs were returned
        anywhere in the message digest

      The RC4 stream cipher that has been added is very useful in encrypting/decrypting
      fields in a table. Because it is a stream cipher, the resulting ciphertext (encrypted
      data) is the same length as the plaintext. Unlike a block cipher (which comprises
      all of the other ciphers that vfpencryption.fll provides), a stream cipher does not
      pad the results with extra characters. This means that RC4 can be used to encrypt
      and decrypt a field with a simple Replace command. No additional machinations are
      required. In any event, give it a try and see what you think.

      Special thanks to Tom?s Can? out of Santiago, Chile for the heads up regarding the
      bug in the Hash() function that was causing certain message digests (hash codes) to
      be truncated. This bug has been fixed.

      Here is the link for the latest version of the vfpencryption.fll

      Download the
      Latest Version of the VFP Encryption FLL
      (57 KB approx.)

      I’ve also decided to offer a download of Microsoft’s redistributable installer for
      the VC++ 8.0 runtimes to ease the problems some were encountering during deployment
      of the FLL. If you “SET LIBRARY TO vfpencryption.fll” in Visual FoxPro and get an
      error saying that the FLL is invalid, then you (or your client) don’t have the
      required C runtimes installed. The installer available at the link below will solve
      this problem.

      Download the Microsoft’s
      installer for the VC++ 8.0 runtimes
       (2.5 MB approx.)

      I hope that the documentation I am providing below is clear to everyone. If there
      is something further that I could do in order to make this FLL more useful or understandable,
      please let me know. I will be putting together some Visual FoxPro samples of use for
      this FLL in the near future to be included as a separate download.


       vfpencryption.fll Documentation…


      Function ENCRYPT()

      Signature: Encrypt(cStringtoEncrypt, cSecretKey[, nEncryptionType[,
      nEncryptionMode]])

      Parameters:

      cStringtoEncrypt – A plain text string that you want
      to have encrypted, such as “Hello World!”

      cSecretKey – A plain text string that is the Key you want
      used during encryption, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of encryption.
      Refer below for more information.

      nEncryptionType – There are currently 5 types of encryption
      available. The value of this parameter determines that type of encryption used and
      how long your Secret Key should be. A single character in Visual FoxPro is  equal
      to 1 byte or 8 bits. So an encryption algorithm requiring a 128-bit key would need
      a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)
         1024 = RC4 (Key can be any length)

      nEncryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB). The
      nEncryptionMode parameter does not apply to RC4 encryption (nEncryptionType = 1024).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      Character data type – the encrypted form of cStringtoEncrypt.

      Remarks:

      When saving the return value of Encrypt() function to a field in a table, remember
      that Visual FoxPro will append blanks to the end of the string in order to fill the
      character field to its designated length. This can cause problems when decrypting
      the data as the spaces will be considered part of the encrypted string. To work around
      this, I suggest placing a single CHR(0) at the end of the encrypted string when saving
      it to the table. Then when decrypting the data just the portion prior to the CHR(0)
      can be sent into the Decrypt() function. This does not apply when
      using RC4 encryption (nEncryptionType = 1024).


      Function DECRYPT()

      Signature: Decrypt(cEncryptString, cSecretKey[, nDecryptionType[,
      nDecryptionMode]])

      Parameters:

      cEncryptedString – A string that has been encrypted
      using the Encrypt() function.

      cSecretKey – A plain text string that is the same Key that
      you used when you encrypted the data using the Encrypt function, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of decryption.
      Refer below for more information.

      nDecryptionType – There are currently 5 types of decryption
      available and they correspond to the same ones available in Encrypt(). A single character
      in Visual FoxPro is  equal to 1 byte or 8 bits. So an decryption algorithm
      requiring a 128-bit key would need a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)
         1024 = RC4 (Key can be any length)

      nDecryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB). The
      nDecryptionMode parameter does not apply to RC4 decryption (nDecryptionType = 1024).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      Character data type – the decrypted form of cEncryptedString followed by a variable
      number of CHR(0)s. See Remarks below for further clarification

      Remarks:

      IMPORTANT: Decryption is done on blocks of memory, so when
      the decrypt function returns the encrypted string it will be followed by a variable
      number of CHR(0)s unless the decrypted string just happens to end at exactly the same
      location as the last block decrypted. These extraneous CHR(0)’s can be removed using
      a number of Visual FoxPro functions, such as STRTRAN(), CHRTRAN(), or a combination
      of LEFT() and AT(). This does not apply when using RC4 decryption
      (nDecryptionType = 1024).


      Function ENCRYPTFILE()

      Signature: EncryptFile(cFiletoEncrypt, cDestinationFile, cSecretKey[,
      nEncryptionType[, nEncryptionMode]])

      Parameters:

      cFiletoEncrypt – A plain text string that is the fullpath
      to the file you wish to be encrypted, such as “C:\SensitiveInfo.doc”

      cDestinationFile – A plain text string that is the
      fullpath to an encrypted file you wish to have created on disk, such as “C:\EncryptedInfo.doc”.
      If this file doesn’t exist then it will be created for you.

      cSecretKey – A plain text string that is the Key you want
      used during encryption, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of encryption.
      Refer below for more information.

      nEncryptionType – There are currently 5 types of encryption
      available. The value of this parameter determines that type of encryption used and
      how long your Secret Key should be. A single character in Visual FoxPro is  equal
      to 1 byte or 8 bits. So an encryption algorithm requiring a 128-bit key would need
      a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)
         1024 = RC4 (Key can be any length)

      nEncryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB). This
      does not apply when using RC4 encryption (nEncryptionType = 1024).

      >

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      None

      Remarks:

      Currently the cFiletoEncrypt and cDestinationFile parameters cannot point to the same
      file. This may be revised in a future version. But for safety sake, this function
      requires that the original file be left untouched.


      Function DECRYPTFILE()

      Signature: DecryptFile(cEncryptedFile, cDestinationFile, cSecretKey[,
      nDecryptionType[, nDecryptionMode]])

      Parameters:

      cEncyptedFile – A plain text string that is the fullpath
      to the file you wish to be decrypted, such as “C:\EncryptedInfo.doc”

      cDestinationFile – A plain text string that is the
      fullpath to a decrypted file you wish to have created on disk, such as “C:\SensitiveInfo.doc”.
      If this file doesn’t exist then it will be created for you.

      cSecretKey – A plain text string that is the same Key that
      you used when you encrypted the data using the Encrypt function, such as “My_SeCrEt_KeY”.
      Please note that keys may need to be of a particular length for certain types of decryption.
      Refer below for more information.

      nDecryptionType – There are currently 5 types of decryption
      available and they correspond to the same ones available in Encrypt(). A single character
      in Visual FoxPro is  equal to 1 byte or 8 bits. So an decryption algorithm
      requiring a 128-bit key would need a Secret Key of 16 characters (16 x 8 = 128).

         0 = AES128 (requires a 16 character Key)
         1 = AES192 (requires a 24 character Key)
         2 = AES256 (requires a 32 character Key) *Default
         4 = Blowfish (requires a 56 character Key)
         8 = TEA (requires a 16 character Key)
         1024 = RC4 (Key can be any length)

      nDecryptionMode – There are three different modes
      available for the each of the encryption types listed above. They include: Electronic
      Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB). This
      does not apply when using RC4 decryption (nDecryptionType = 1024).

         0 = ECB *Default
         1 = CBC
         2 = CFB

      Return Value:

      None

      Remarks:

      As with EncryptFile(), the cFiletoEncrypt and cDestinationFile parameters cannot point
      to the same file.


      Function HASH()

      Signature: Hash(cStringtoHash[, nHashType])

      Parameters:

      cStringtoHash – A plain text string
      you wish to have hashed

      nHashType – The type of hash function to generate. There
      are currently 7 different hash functions supported

      1 = SHA1 (a.k.a SHA160)
      2 = SHA256
      3 = SHA384
      4 = SHA512 *Default
      5 = MD5
      6 = RIPEMD128
      7 = RIPEMD256

      Return Value:

      Binary Character Data – the hash for cStringtoHash.

      Remarks:

      The hash is returned as a series of binary characters. However, it is more
      common to see hashes in a hexBinary format. This can be accomplished in Visual FoxPro
      by taking the return of the Hash() function and sending it in as a parameter to the
      STRCONV() function. For example:

      ?STRCONV(Hash(“Some String”), 15) && hexBinary Hash


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3121972

      VFP System Tasks-like Panels

      by craigaaa3 ·

      In reply to The SPS Weblog

      Proof of concept
      The following is just a quick proof of concept, so please don’t expect coding
      brilliance or even real great encapsulation in the class library. With that having
      been said, I decided yesterday that I would like to create something similar to the
      System Tasks panel that is shown on the left-hand side of Windows Explorer (when the
      folders panel isn’t open). Now, that System Tasks panel uses a bunch of cool gradients,
      handles XP Theme colors and even fades the panels out when they are collapsing…
      none of which is in this proof of concept. Never-the-less, I like what I was able
      to come up with in a very short amount of time using pure Visual FoxPro.

      Data driven
      The content area of the panels in my creation is actually a grid, so the
      panels can be data driven. I create a cursor with the following structure…

      CREATE CURSOR

      crsPanel1 (imgfile c(254),
      capt c(75),
      selected L, command c(254))>

      The imgfile field is the name of an image file that has been compiled
      into the exe, though you could use a fullpath for that if you have an images directory
      that you distribute. The next field, capt is used to designate what the caption should
      be for a particular item in the panel. Selected is just a boolean field that I use
      to control the underlining (via the column’s DynamicFontUnderline) of the items as
      the mouse passes over them. And, finally there is a command field that will hold the
      VFP script to be executed (via the ExecScript function) when the user clicks on an
      item. You can find where I have built the cursors that data drive the 3 panels for
      the example I’ve included in the download in the Example form’s load event. Pretty
      straight-forward stuff.

      Possible use for the scrollable container
      One of the improvements to this that I’ve been thinking of is using the Scrollable
      Container
      I created for an earlier blog entry to allow the container that is holding
      the panels (cparentpanel class) to provide a scrollbar when the stacked panels exceed
      the length of the form. But, I figure that it is good enough as is to at least put
      it out there and get some feedback. I recevied an email from Jonathan Clark some weeks
      back suggesting that something like the interface that is used at
      http://www.live.com/ would
      be a pretty cool thing to do with VFP. Eventually, I will encapsulate the expand
      and collapse functionality and some of the other features that most panels have these
      days so that it is seperate from the UI portion of this. Once that is done, creating
      controls and interfaces that provide this sort of look and feel will be a piece of
      cake.

      XP Themes – possible
      future project
      While I’m on the subject of things I’d like to do, I’d also like to get a
      handle on XP Themes as well. Though the gradients that themes use are difficult to
      mimic, it would be nice to get closer to the ability to implement some form of XP
      Themes on most the controls and custom classes we are creating. VFP’s out-of-the-box
      UI already looks antiquated, and since the MS Fox Team doesn’t appear to have this
      sort of thing on their radar at the moment, I think it would serve us well to do something
      about it. I can certainly draw most anything using GDI+, so maybe there is some things
      we can do to shore this up a little.

      Download and screen shot
      I’ll stop myself with that lest I ramble for an hour or two… Here’s the
      download link and a screen shot of VFP Panels in action.
      NOTE: When
      you run the example you’ll notice that I allow the panels to be hidden (click the
      X in the top right-hand corner of the panel you want to hide). In order to re-show
      a hidden panel, right-click on the dark blue container and select the hidden panel
      from the Show context menu.

      Download
      VFPPanels.vcx Source and Example
      (220 KB approx.)

      vfppanels.jpg

      >>


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3123204

      VFPConversion – Huh?

      by craigaaa3 ·

      In reply to The SPS Weblog

      Disappointing blog entry
      I’m not sure which of the developers at VFPConversion posted the following
      blog entry…

      Custom
      Types in .NET

      …so I will just refer to them as VFPConversion (though the entire staff may not
      feel the same way). Here are a few of the more telling quotes from the entry that
      pretty much sum up what the blog entry is trying to say:

      “What could we do in VFP to ease the pain? Well, we could
      provide objects with methods that take away the implementation complexity. Conversion
      methods would be useful. The ability to parse a string such as “5m 6cm 13mm” might
      be useful. “

      “In .NET, there really is no difference between types and
      classes. In VFP, things are different. The system provides a number of default data
      types that are used to store information, and classes are a bit of a different animal
      altogether. In .NET on the other hand, there is no difference between a String data
      type, and a custom class or object. The solution to this problem therefore is the
      creation of a custom data type (which is the same as creating a new class)…”

      “…This is quite a different way of thinking about data than
      we find it in VFP. In VFP, if we were to store the coordinates of a point in 3D space,
      we would use 3 numbers. And everyone who used that piece of information would have
      to know how to handle those three numbers.”

      VFP is such a pain
      So, basically VFPConversion is asserting that it is foreign (painful even) to
      use custom classes in Visual FoxPro to represent data and that somehow .NET makes
      this easier. That’s where I start to think, “Huh?”. The veracity of that premise is
      completely lacking, especially given the examples they’ve used. While .NET’s data
      types are certainly implemented as classes, that doesn’t make it a better fit for
      creating a custom 3D class or preclude a Visual FoxPro developer from creating a custom
      3D class replete with PEMs. Visual FoxPro, the first language in MS’s arsenal to offer
      Object-Oriented Programming (OOP), is quite capable of creating custom classes that
      represent data types.

      On the contrary, VFP does OOP
      If the project justified the additional overhead, classes for data types
      could easily be created in Visual FoxPro. That highlights one of the real difference
      between .NET and Visual FoxPro. (note the following is an over simplification to make
      a point) In Visual FoxPro, if it isn’t available somewhere then you’ll need to
      roll your own. With .NET it is already rolled for you in a lot of cases, which might
      justify the use of .NET (you don’t want to spend all your client’s time and money
      rolling your own). So, Visual FoxPro is inferior right? Wrong. That’s just the kind
      of nonsense that comes from some .NET proponents. With so many good arguments and
      benefits that could be pointed out for .NET (especially when comparing it to VFP),
      they invariably pick the wrong arguments and harm their credibility in the process
      (.NET does classes the best, .NET does data the best, Visual FoxPro doesn’t do OOP,
      etc., etc. ad nauseam).

      Choice is not a bad thing
      The fact is that Visual FoxPro allows you, as a developer, to choose. We
      could represent the 3D spacial information as 3 numeric values, as an array,
      as an object, as collection of points, as a cursor, as a string, etc. We aren’t constrained
      to 3 numeric values, or somehow in pain if we have to create a 3D class to represent
      the data. Those assertions are simply not true. If it wasn’t for the fact that
      I have an immense amount of respect for the abilities of those who are on the
      VFPConversion crew, I would accuse the author of either ignorance or an attempt to
      mislead.

      The .NET framework recreated in VFP
      Case in point… Bo Durban and I have been working on an implementation of
      the .NET
      Drawing namespace
      for Visual FoxPro. For those of you that are unfamiliar with
      that namespace in .NET it consists of 5 other namespaces and quite a few classes in
      Drawing and the other namespaces. In any event we’re doing it in pure Visual FoxPro
      and we have been extremely hardpressed to find anything that we can’t implement (recreate) in
      Visual FoxPro easily. Before long Visual FoxPro developers will be typing in System.Drawing.Graphics
      with the best of them (replete with Intellisense). In any event, there are plenty
      of complex data types and such… no problem, no pain, no wild machinations. It’s
      just OOP and Visual FoxPro is a very capable OOP language. When Bo and I are
      done with it, not only will the VFP Community have a complete GDI+ implementation,
      but they’ll also have the source code to it. (I’m also working on implementing LINQ in
      pure VFP… no problems encountered there either… in fact I would say that
      I am having a better go of it, because VFP is made for this sort of thing. I doubt
      MS is doing LINQ with a single developer.)

      I love Visual Studio 8
      Please don’t misunderstand me, I’m not a .NET basher in any way shape or
      form. Nor an I trying to throw the gauntlet down with VFPConversion (I’m hoping to
      have an opportunity to
      see and talk to Rod Paddock
      on a semi-regular basis in Sioux Falls). VFPConversion
      has a very talented cast of developers on the payroll and I love Visual Studio 8.
      I also think that there are lots of projects that a .NET language should be considered
      for over Visual FoxPro. That’s right, Visual FoxPro is not the panacea that some Visual
      FoxPro purists make it out to be.

      .NET is a good framework, and the
      latest IDE from MS
      is pretty awesome (and I can’t wait to see Cider when
      it is released). I’ve always loved data binding controls to more than just the
      value/text property (controlsource in Visual FoxPro). I love the UIs that can be created
      with it, the new controls that were added, the designers and its web capabilities
      can’t be touched if you ask me. I could go on for pages about what I like better about
      .NET than VFP, or about what can be done in .NET that can’t be done in VFP. But I
      could also do the same for VFP versus .NET.

      They are different tools and have different strengths and weaknesses (and wouldn’t
      even be compared so often if it wasn’t for the bevy of VFP developers that have gone
      over to .NET – when was the last time you heard someone compare Access or SQL Server
      with Visual Studio? Perhaps the comparisons have more to do with the fact that Visual
      FoxPro is such a great frontend for SQL Server and Visual Studio can also create frontends
      for SQL Server?). If you are adept at both, then all the better. You have two wonderful
      tools to better implement your customers’ visions and solutions.

      You’re better than that
      I am all for a good language getting the good press that it deserves, whether
      it is .NET or VFP. But, how about a little love for the Fox? Or, at the very least
      put those keystrokes to good use on an honest, unbiased, straight-forward synopsis
      of Visual FoxPro’s strengths and weaknesses, especially when you are comparing
      it to .NET. You’ll at least sound like you know what you’re talking about to your
      readers.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3129370

      Learning VFP 102: Scope

      by craigaaa3 ·

      In reply to The SPS Weblog

      New Learning VFP video
      I’m finally back into the swing of things, and have produced a new video
      for the Learning Visual FoxPro series. In this video I explore SCOPE as it exists
      in Visual FoxPro for variables, arrays, parameters, constants, procedures, and object
      members. I also discuss certain Visual FoxPro commands that are scoped to the current
      datasession. This video is 102, so it is in the beginners series, however I have tried
      to be thorough enough in my examination of scope in Visual FoxPro that intermediates
      may also come away with something of value.

      Upcoming Videos
      Before I post the links to this new 3 part video, I thought I would take
      a moment and share with you a list of things that I am considering doing videos on
      in the near future. So, here they are in no particular order:

      • Error Handling (On Error and Try…Catch…Finally)
      • Modal vs Modeless
      • Reports
      • Database creation
      • SQL
      • Views (Remote, local, Createoffline()/Use Online, etc.)
      • Transactions (MAKETRANSACTABLE included)
      • XML
      • HTML
      • Web Services
      • Debugging
      • Coverage Profiler
      • CONFIG.FPW
      • String Parsing
      • Indexes (including how to effectively reindex)
      • SET Commands
      • Project Hooks
      • Using Windows APIs
      • Intellisense
      • Different Controls (grid,listbox, combobox, etc.)
      • Foundation classes (xmladapter, cursoradapter, reportlistener, etc.)
      • Drag and Drop
      • BITwise functions (bitset, bitclear, bitand, etc.)
      • Bindevent
      • Compiler Directives

      Feedback and ideas are important
      If there are items in the list above that you would like to see done first,
      or if you have an idea for some Visual FoxPro subject matter that should be convered
      that is not in the list, please let me know. I welcome any and all feedback regarding
      the videos that I do as well as the proposed videos to be done in the near future.
      I want to make sure that the subjects that the Visual FoxPro Community would like
      to see covered are the ones I do first.

      Learning Visual FoxPro 102: Scope

      For Online Viewing:
      Part
      I
       (14:15)
      Part
      II
       (17:57)
      Part
      III
       (15:43)

      For Offline Viewing:

      Download Part1 SWF File
       (6.5 MB approx.)

      Download
      Part2 SWF File
       (11.5 MB approx.)

      Download
      Part3 SWF File
       (11 MB approx.)

      Source Code used in the video:
      Download
      102 Source Code
       (5 KB approx.)

      If you have any problems understanding any of the concepts presented in this video,
      be sure to try out the source code that accompanies this video. While a screencast
      works pretty good for imparting information, nothing can beat trying a few things
      on your own and stepping through some code when trying to understand scope in Visual
      FoxPro. The procedural files for this video should make it easier for you to explore
      all the different aspects to this.

      For those of you that haven’t ever used the FoxPro Frame debugger as I did in the
      video, it is available as a debug setting. Go to the Tools menu, click on Options,
      and then look in the Debug page (tab). You should see a dropdown box on that page that
      allows you to select it.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3128023

      Visual FoxPro Not an Endangered Species

      by craigaaa3 ·

      In reply to The SPS Weblog

      Interesting column on Visual FoxPro
      Mary Jo Foley, the editor of Microsoft Watch, has been covering Microsoft
      for about 20 years. Seemingly out of nowhere she posted a column
      on Visual FoxPro
      . Here are a few quotes from the column:

      “Visual FoxPro is the Rodney Dangerfield of Microsoft. It doesn’t get a lot of
      respect. But I think this situation may soon change.”

      “I think FoxPro is about to get a lot more relevant to Microsoft and its customers,
      and not just because Microsoft exec Eric Rudder (who some claim is Chairman Bill Gates’
      heir apparent) served as the architect of Visual FoxPro 3.0.”

      “It seems like Microsoft is bending over backwards to keep FoxPro from ending
      up as part of a musty fur coat. I can’t help but wonder if it has shown Microsoft
      that there’s value still in non-.Net-based products. In the same way that the success
      of Ajax applications led Microsoft to reevaluate its “smart-client-or-nothing? strategy,
      the hardiness of FoxPro and its users has led the Redmondites to give the Fox a second
      look.”

      Email Mary Jo
      In the column, Mary Jo also encourages the FoxPro faithful to email her with
      their thoughts regarding Visual FoxPro and the recent upsurge in activity and interest
      surrounding it. She provides her email address and some questions she’d like to see
      addressed at the bottom of the column.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3126643

      Saving and restoring settings in VFP applications

      by craigaaa3 ·

      In reply to The SPS Weblog

      The problem
      Often in code Visual FoxPro developers will find themselves having to save
      the previous state of something in order to be able to restore it once some code has
      run. The usual culprits are:

      • SET command (such as SET SAFETY, SET DELETED, etc.)
      • ON command (ON ERROR, ON ESCAPE, etc.)
      • Record Pointer position
      • Selected Work Area

      The solution
      Rather than writing the same lines of code over and over again in our programs,
      we could create a class that will handle this. The following is a SettingHandler class
      I’ve written and some examples of use. You’ll note that when I instantiate the class
      I send it the command that I’m about to execute (such as SET SAFETY OFF) as a string
      parameter. The class will save the current Safety setting for me and then set it to
      OFF. When I want the previous Safety setting restored, I release the instance of SettingHandler
      and the class will restore Safety to whatever it was prior to my setting it off.

      Drawbacks and possible improvements
      The only drawback I’ve found to this approach is that intellisense doesn’t
      work when I am typing in the command as a string parameter. As for improvements, most
      of the ones I can think of would have to do with table operations. Code could be added
      to allow you to save the current datasession id and restore to that
      datasession (there are probably other settings that could be provided for as well
      – Captions, ForeColor, BackColor, Tag, or whatever). Also, some logic could be added
      to handle if a developer switched work areas, but hadn’t specified the work area in the
      GOTO command.

      Here’s a runnable example and class definition (Cut-n-paste the code
      below into a prg file and execute it)

      *************************
      *!* EXAMPLES OF USE
      *************************
      CLEAR
      LOCAL loSetting
      ? “SET COMMANDS:”
      SET SAFETY ON
      ?SET(“SAFETY”)
      loSetting = CREATEOBJECT(“SettingHandler”, “SET SAFETY OFF”) && Safety setting
      is saved and changed
      ?SET(“SAFETY”)
      RELEASE loSetting && Previous Safety setting is restored
      ?SET(“SAFETY”)
      ?
      ? “ON COMMANDS:”
      ON ERROR ?”Previous Error Handler”
      ?ON(“ERROR”)
      loSetting = CREATEOBJECT(“SettingHandler”, “ON ERROR ?’New Error Handler'”) &&
      Error handler is saved and changed
      ?ON(“ERROR”)
      RELEASE loSetting && Previous Error handler is restored
      ?ON(“ERROR”)
      ?
      ? “RECORD NUMBER:”
      IF !USED(“customers”)
       USE (HOME(2) + “northwind\customers.dbf”) IN 0 SHARED
      ENDIF
      GOTO 5 IN “customers”
      ?RECNO(“customers”)
      loSetting = CREATEOBJECT(“SettingHandler”, “GO 12 in [customers]”) && record
      pointer position is saved and changed
      ?RECNO(“customers”)
      RELEASE loSetting && record pointer position is restored
      ?RECNO(“customers”)
      ?
      ? “SELECT:”
      IF !USED(“orders”)
       USE (HOME(2) + “northwind\orders.dbf”) IN 0 SHARED
      ENDIF
      SELECT “Orders”
      ?ALIAS()
      loSetting = CREATEOBJECT(“SettingHandler”, “Select Customers”) && Selected
      Alias is saved and changed
      ?ALIAS()
      RELEASE loSetting && Previous selected Alias is restored
      ?ALIAS()
      USE IN SELECT(“Customers”)
      USE IN SELECT(“Orders”)
      *********End of Examples************

      ************************************
      *!* CLASS DEFINITION
      ************************************
      DEFINE CLASS SettingHandler as custom
       PROTECTED PreviousValue
       PreviousValue = .NULL.
       
       PROTECTED SettingCommand
       SettingCommand = “”
       
       PROTECTED SettingType && 0 = SET/ON, 1 = RECNO
       SettingType = -1
       
       #DEFINE SETTINGDELIMITERS [(‘” ] + “[])”
       
       PROCEDURE Init (tcCommand)
        This.Setup(tcCommand)
       ENDPROC
       
       PROTECTED PROCEDURE Destroy
        This.RevertSetting()
       ENDPROC

       PROCEDURE Setup (tcCommand)
        This.SettingCommand = ALLTRIM(tcCommand)
        This.SaveSetting()
        This.UpdateSetting()
       ENDPROC
       
       PROTECTED PROCEDURE SaveSetting
        LOCAL lcFirstPart, lcSecondPart, lnSecondPosition, lcCommand
        lcFirstPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand, 1, SETTINGDELIMITERS)))
        DO Case
         CASE INLIST(lcFirstPart, “SET”, “ON”)
          lcSecondPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand,
      2, SETTINGDELIMITERS)))
          lcCommand = lcFirstPart + [(“] + lcSecondPart + [“)]
          This.SettingType = 0
         CASE INLIST(lcFirstPart, “GOTO”, “GO”)
          lnSecondPosition = ATC(” IN “, this.SettingCommand)
          IF lnSecondPosition > 0
           lcSecondPart = SUBSTR(this.settingcommand, lnSecondPosition
      + 4)
          ELSE
           lcSecondPart = “”
          ENDIF
          lcCommand = [RECNO(] + lcSecondPart + [)]
          This.SettingType = 1
         CASE lcFirstPart = “SELECT”
          lcSecondPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand,
      2, SETTINGDELIMITERS)))
          lcCommand = [ALIAS()]
          This.SettingType = 2
        ENDCASE
        IF !EMPTY(lcCommand)
         This.PreviousValue = EVALUATE(lcCommand)
        ENDIF
       ENDPROC
       
       PROTECTED PROCEDURE UpdateSetting
        EXECSCRIPT(This.SettingCommand) && Change the setting
       ENDPROC
       
       PROTECTED PROCEDURE RevertSetting
        LOCAL lcCommand, lnStuffPosition, lnStuffLength, lcAliasWas
        DO CASE
         CASE This.SettingType = 0 && SET/ON
          lnStuffPosition = AT(” “, this.Settingcommand, 2) + 1
          lnStuffLength = LEN(this.settingcommand) – lnStuffPosition
      + 1
         CASE This.SettingType = 1 && GOTO/GO
          lnStuffPosition = AT(” RECORD “, UPPER(this.Settingcommand),
      1) + 8
          IF lnStuffPosition < 9
           lnStuffPosition = AT(” “, this.Settingcommand, 1) +
      1
           lnStuffLength = AT(” “, this.Settingcommand, 2)
           IF lnStuffLength > 0
            lnStuffLength = lnStuffLength – lnStuffPosition
      + 1
           ELSE
            lnStuffLength = LEN(this.settingcommand) – lnStuffPosition
      + 1
           ENDIF
          ELSE
           lnStuffLength = LEN(this.settingcommand) – lnStuffPosition
      + 1
          ENDIF
         CASE This.SettingType = 2 && SELECT
          lnStuffPosition = AT(” “, this.Settingcommand, 1) + 1
          lnStuffLength = LEN(this.settingcommand) – lnStuffPosition
      + 1
        ENDCASE
        IF !EMPTY(lnStuffPosition)
         lcCommand = STUFF(This.SettingCommand, lnStuffPosition, lnStuffLength,
      TRANSFORM(this.PreviousValue))
         EXECSCRIPT(lcCommand) && Put things back the way they were
      before class was instantiated
        ENDIF
       ENDPROC
      ENDDEFINE


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3124328

      Simple Bar Graphs via Grid and Backstyle_Access

      by craigaaa3 ·

      In reply to The SPS Weblog

      Email arrives
      Sue Cunningham emailed me earlier this evening and told me about a cool use
      she had found for the backstyle_access technique I had explained
      in an earlier blog entry
      . If you don’t have time to wade through that blog entry
      here’s the condensed version: I showed that by using the backstyle_access method of
      a control contained in a grid’s column you can do just about anything you want since
      that method will fire as each visible row in the grid is painted. There really isn’t
      even a need for all those DynamicWhatever methods that the MS Fox Team added to the
      column object when you use backstyle_access. It allows for much more complex operations
      and visual effects to be performed within the grid rows as well. Anyways, Sue emailed
      me and said that she had devised a relatively simple way to produce bar graphs. Something
      that looks a lot like the recent gradient bars that Calvin
      Hsia
      blogged about (see screen
      shot on Andrew MacNeill’s blog
      ), but much simpler (no need for GDI+) and minus
      the gradient.

      I decided to give it a try
      Sue didn’t provide the code to her solution, but based on the explanation
      she had given in her email, I felt I had the basic idea and decided to try my hand
      at it and see what I could create. The result (see screen shot below) was as
      pleasing as it was easy. Sue also said that she was encountering some unpredictable
      results when placing the grid within a container control, so I also produced an example
      (Example2 form in the source that can be downloaded below) that also uses this technique
      to display graphs on two separate pages of a pageframe. I didn’t run into any of the
      inconsistent results (using VFP 9.0 SP1 here) that Sue did, so I’m not sure what is
      happening for her there. The technique appears to work flawlessly (Note: the bars
      will get truncated and/or have paint problems if I allow the grid to show both panels
      at the same time and the left panel is a CHANGE panel. The Change panel is the
      only place I saw this unwanted behavior, other than that all is right).

      What all is involved
      I have a grid subclass that contains two columns. The first column is used
      for the description of whatever the item is I am graphing… you can think of it as
      the axis label I guess. The second column contains a pretty simple container subclass
      that contains a shape and a label subclass. The shape is used to produce the bars
      and the label is used to show the value that was graphed. The magic for all of this
      is in the container control (that is in column2) backstyle_access method. Here’s the
      actual code which is quite short…

      LOCAL lnTotalTicks, lnValue, lnWidth
      lnTotalTicks = (this.Parent.Parent.MaxValue – This.Parent.Parent.MinValue)
      lnValue = EVALUATE(this.Parent.Parent.recordsource + “.value”)
      lnWidth = (This.Parent.Width – 35) * (lnValue/lnTotalTicks) && – 35 to leave
      room for the value caption
      This.cshape1.Width = lnWidth
      This.clabel1.Caption = TRANSFORM(lnValue)
      This.cLabel1.Left = lnWidth + 5 && leave a five pixel margin
      RETURN THIS.BackStyle

      That’s basically all there is to it. The bars will be whatever color the shape is
      in the container. You could admittedly improve on what I am providing here by adding
      a barcolor property for the grid or perhaps showing the bars in different rows in
      different colors based on some criteria, or by calling a method of the grid from the
      container’s backstyle_access so that bit of code above isn’t so hidden. I am just
      providing the basic premise here, this is certainly not a finished product with all
      the bells and whistles that are possible. Also, as you’re looking at the examples
      you may notice that there are MinValue and MaxValue properties that have been
      added to grid subclass. These are so we don’t have to always graph on 0 – 100 or whatever
      (see code above). The values graphed could be anything, say 1000-10000 or whatever.

      Finally, to see the very simple cursors that the bar graph grids run off of, look
      in the example forms’ load events where you’ll find something like thfollowing code…

      LOCAL lnCounter
      CREATE CURSOR crsValues (Descript c(25), Value I)
      =RAND(-1)
      FOR lnCounter = 1 TO 100
       INSERT INTO crsValues (Descript, Value) VALUES (“Item ” + TRANSFORM(lnCounter),
      INT(100 * RAND( ) + 1))
      ENDFOR
      GO TOP IN crsValues

      As you can see the cursor that is needed for this is extremely simple, just two fields
      in fact, one for the description and the other for the values. In any event, this
      just once again shows the value of Visual FoxPro’s grid class when coupled with the
      backstyle_access method. With very few lines of code we are able to produce a pretty
      useful class for visually displaying data to our users. Thanks for the emailed tip Sue
      and it was a pleasure meeting you at Southwest Fox 2005!

      Source Code and Screen Shot
      When you get the zip file downloaded, extract the contents. Open the project
      in Visual FoxPro and run the Example and Example2 forms.

      Download Grid Graph
      Source Code with Examples
      (23 KB approx.)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3121158

      Bar Graphs – Part II

      by craigaaa3 ·

      In reply to The SPS Weblog

      Improving on yesterday
      In yesterday’s
      blog entry
      I showed a technique that could be used to create simple bar graphs.
      There was one thing missing from the bars on the graphs however, gradients. In
      any event, I decided to try my hand at a solution similar to the
      one shown by Calvin Hsia
      , but without all the quirky behavior that renders Calvin’s
      example fairly unusable in a real-world application (to be fair, his was more
      of a proof-of-concept than anything).

      Gradient Bars
      If you want gradients in your Visual FoxPro applications and don’t want to
      have to go through some of the machinations that I did for the progressbar control
      I showed in an
      earlier blog entry
      , then you are going to have to use GDI+. The combination of
      GDI+ and the backstyle_access method of an object contained in a grid’s column gives
      us everything we need to produce some first-class results.

      In the solution that I am showing here I use a grid subclass and an image subclass
      to display the bars. That’s it as far as the classlib is concerned, but if you look
      in the grid’s Init event and its Drawbar and Drawtext methods you’ll see that
      there is some fairly heavy reliance on GDI+ and subsequently the _gdiplus.vcx class
      library that is shipped with Visual FoxPro 9.0. Given the complexity of GDI+ code
      to those who may be unfamiliar with it, I have heavily commented the code for this
      solution. I encourage you to read through it. I am hoping that it will be clear what
      I am doing and why.

      Annoying Picture property behavior
      One thing I’ve run into when working with GDI+ in Visual FoxPro is the fact
      that Visual FoxPro will bring up a busy cursor (hourglass) when the picture property
      of a container or image is set (perhaps other classes as well). This means that when
      I am using an off-screen bitmap to draw to and I set that bitmap’s fullpath as the
      Picture property that the mouse cursor will change back and forth from an arrow to
      an hourglass to an arrow to an…. you get the idea. In a perfect world the Microsoft
      Fox Team would let us as developers determine when a mouse cursor should show busy,
      or at the very least allow us a way to shut off this helpful “feature”, but that’s
      not the case here. Luckily they didn’t do the same thing when they implemented the
      PictureVal property of the image control. So, in order to get rid of this flickering
      mouse, I use an image control and after I have written the bitmap to disk I convert
      it to a string with FILETOSTR() and use it for the PictureVal. Works like a charm,
      even if there is no doubt some additional overhead with this approach.

      Improved grid subclass
      I spruced up the grid subclass a bit and provided additional properties that
      can be set to change the gradient colors (Gradientcolor1 and Gradientcolor2 properties),
      as well as a GradientDirection property that can be set to change the direction in
      which the gradient is drawn (Horizontal = 0, Vertical = 1, Forward Diagonal
      = 2, Backward Diagonal  = 3). I’ve also placed the code that is used to
      draw the bars in a Drawbar method of the grid subclass. This Drawbar method is called
      by the image subclass (that is contained in column2) backstyle_access method. And
      finally, since I was already using GDI+, I decided to forego an additional label object
      and instead I draw the value text at the end of each bar using GDI+. The font that
      is used for the value text is the same as has been set for the column1 descriptions,
      so if you change column1’s font it will change the font used to render the
      value text as well.

      Additional improvements possible

      There are a number of improvements/enhancements that could no doubt be made to this
      solution. Some that I can think of would be to allow the developer to define the fields
      that are to be used for the descriptions and values rather than hardcoding it to a
      particular cursor/table structure. Another improvement would be to allow for drill-downs
      in some fashion so the user could double-click on a particular row and be presented
      with the group of data that made up that particular value. Given that this is using
      pure GDI+ to draw the bar nearly anything could be drawn there and if the rows had
      a tall enough height individual pie slices could be shown. This might look really
      good on a form where the grid is shown next to the entire pie chart.

      I also cut some corners when it came to the rendering of the value text. The height
      of that text for centering is determined from the form’s textheight method which could
      lead to erroneous results. I also didn’t completely duplicate the font being used
      by column1, things such as bold or underline or strikethru have been ignored. However,
      to my credit I did provide the additional constants and such that are needed should
      you wish to go further with this. I felt that what I had was good enough for this
      blog posting and I don’t know if I would want the value text to be underlined or whatever
      even if the developer decided to do that themselves. I guess if I was thinking I would
      have taken all the values from column2’s font settings (the column that the bars are
      actually rendered in) and used that… it would have provided a simple and intuitive
      way for the developer to determine the font used for the value text that is rendered
      at the end of each bar. I guess I wasn’t thinking, but hopefully you get the idea
      here which is what I’m striving for.

      Future ideas
      Sue Cunningham is at it again and has emailed me about the next phase of
      her solution which will be to provide the users with a way to print the bar graph
      that is shown in the grid. I’ll let that roll around in my head for a day and see
      what occurs to me. I’m thinking that task just got a lot easier with this solution
      since I’m using GDI+ and the _reportlistener is kind enough to expose the GDI+ Graphics
      object(s) it is using when it renders a report. Seems like I’ve already got most of
      the pieces… just need to move it from a grid subclass to a _reportlistener subclass.
      Thanks again Sue, I think you’ve given me another future topic with your email.

      Source Code and Screen Shots
      When you get the zip file downloaded, extract the contents. Open the project
      in Visual FoxPro and run the Example and Example2 forms.

      Download the Gradient
      Graph and Examples
      (63 KB approx.)



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3125740

      Visual FoxPro is a Rising Star!

      by craigaaa3 ·

      In reply to The SPS Weblog

      Thank you Andy
      I was reading through new entries in the blogs I subscribe to tonght
      and I came across a post
      by Andy Kramek
       that points out the TIOBE
      Programming Community Index for December 2005
      (sometimes referred to simply as
      the TPC Index). If you look at the bottom of the Top 20 languages in the list you’ll
      see Visual FoxPro which has made a serious leap in the last year. Here’s a quote from
      that page…

      “Rising star this month is Visual FoxPro. It jumped in one year time from position
      51 to 20! It is interesting to see that there is a whole bunch of “new” programming
      languages (such as Visual FoxPro, ColdFusion, Ruby, D, and ActionScript) trying to
      get in the major league, but none of them is capable of holding a top 20 position
      for more than a couple of months.”

      Why the increase?
      I attribute much of the increase to the explosion of online activity
      by the Visual FoxPro Community. If you look over the last year at the blogs, forums,
      screencasts, podcasts, etc. that the Visual FoxPro Community has produced, it is little
      wonder that an index that is calculated using popular search engines would show Visual
      FoxPro as a rising star. Couple that with a few mentions of FoxPro by Microsoft around
      the time they were announcing LINQ and a few new third party vendors that
      have come on the scene in the last year and voila! We have a significant increase
      in Visual FoxPro exposure online.

      New Years Resolution
      OK, so we’ve managed to get our beloved tool into the top 20, but the TPC
      analysts are fairly convinced that we’ll only be there for a couple of months. So,
      as Visual FoxPro and the Visual FoxPro Community has done so many times, I think
      we should prove the naysayers wrong again. As I was in need of a good New Years
      Resolution, mine is going to be to do my part to move us up another 5 spots in the
      coming year (take a look at what language is number 15 in the list). I know it’s a
      lofty goal, and that it will take a concerted effort on the part of the entire Visual
      FoxPro Community, but I don’t see why it can’t be done.

      Isn’t it about time?
      Isn’t it about time to believe that a significant difference can be made
      by the Visual FoxPro Community? There’s absolutely no reason that Visual FoxPro should
      have to play second fiddle to inferior development tools for the market we serve.
      Visual FoxPro is the best Microsoft has to offer when it comes to datacentric applications
      for the small to medium-sized business. As more of them begin to look for
      cost-conscious, lightning-fast alternatives it would be nice if Visual FoxPro was
      front and center. We’ve generated some good momentum over the past year, and I’d like
      to see us capitalize on that. Please join me in making a difference in 2006. Today
      position 20, tomorrow the world! Why not, Right?


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3198078

      Learning VFP 104: Error Handling

      by craigaaa3 ·

      In reply to The SPS Weblog

      New Learning VFP video
      This video is on the topic of Error Handling. A far too often overlooked
      aspect of software development that is absolutely critical to creating great applications.
      Error handling in Visual FoxPro runs the gamut, from the familiar ON ERROR command
      used for procedural error handling, to the fairly new Try…Catch…Finally structured
      error handling. Visual FoxPro offers a surprising number of choices and solutions
      when it comes to error handling. Find out the strengths and weaknesses of each through
      this 3 part video. Beginners can expect to get a handle on the basics and intermediates
      might learn a few things about some of the more obscure stuff such as the COMRETURNERROR
      function for use in COM servers.

      Video Timeline
      A suggestion was made after my
      last video
      that I provide a timeline detailing the contents of the Learning VFP
      videos so that viewers can quickly find what they are looking for. I also think it
      helps viewers know what they can expect to learn in the videos, so here is the timeline/guide
      for this 3 part video series on error handling…

      Part1 – Total Length 25:05
      00:00 Introduction
      01:05 Basic ON ERROR command use
      05:47 Conditional error handling with ON ERROR command
      08:33 Use of RETRY
      10:38 Use of AERROR() to retrieve error info
      15:00 Throwing an exception using ERROR command
      19:53 Use of ASTACKINFO() to retrieve call stack info

      Part2 – Total Length 33:20
      00:00 Basic Try…Catch…Finally use
      07:55 Conditional error handling with Try…Catch
      12:10 User-defined errors and exception subclassing
      21:42 Nesting Try…Catch…Finally blocks
      25:20 Exception escalation using Throw

      Part3 – Total Length 29:32
      00:00 Creating a user-friendly error form and emailing errors
      10:48 The Error Event and overall error handling priority
      17:48 Using the COMRETURNERROR command in COM Servers
      28:40 Wrap-up

      Learning Visual FoxPro 104: Error Handling

      For Online Viewing (same content as offline version):
      Part
      I
       
      Part
      II
       
      Part
      III
       

      For Offline Viewing (same content as online version):

      Download Part1 SWF File
       (13.3 MB approx.)

      Download
      Part2 SWF File
       (16.2 MB approx.)

      Download
      Part3 SWF File
       (19.4 MB approx.)

      Source Code used in the video:
      Download
      104 Source Code
       (198 KB approx.)

      If you have any problems understanding any of the concepts presented in this video,
      be sure to try out the source code that accompanies this 3 part video series. While
      a screencast works pretty good for imparting information, nothing can beat trying
      a few things on your own and stepping through some code when trying to understand
      scope in Visual FoxPro. The files included in the source download for this video series
      should make it easier for you to explore all the different aspects of error handling
      in Visual FoxPro.

      NOTE: I haven’t forgotten Learning VFP 103. It’s on the way, I just haven’t had time
      to finish it yet.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3081060

      Visual FoxPro – It’s what’s for breakfast!

      by craigaaa3 ·

      In reply to The SPS Weblog

      I was reading a
      blog entry by Kevin Ragsdale
      yesterday which had a phrase that I really liked… “Visual
      FoxPro. Does more before breakfast than other languages do all day”.
      I liked
      the phrase so much that I decided to take that phrase and turn it into a short (less
      than a minute) promo for Visual FoxPro. Here are the links to it…

      Online SWF of the Visual FoxPro
      promo

      Offline ZIP of the Visual
      FoxPro promo
      (2.9 MB approx.)

      In a
      later entry
      , Kevin encouraged me to give the Visual FoxPro Community a new
      catch phrase to replace “Visual FoxPro Rocks!”. I think Kevin beat me to it.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3094281

      A Regular Expressions library for Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      What are Regular Expressions?
      Rather than spend thousands of keystrokes explaining what regular expressions
      are, here’s what the Wikipedia
      has to say
      .

      How can they be used in Visual FoxPro?
      The main way in which VFP developers have utilized regular expressions (if
      at all) in their applications is via the Windows Scripting Host. You can see some
      more information on regular expressions and how
      the RegExp object is used in VFP code on the Fox.Wikis
       (Thanks to Alex
      Feldstein
      for most of the content).

      While this solution is OK, there are a few gotchas such as the user account’s security
      settings getting in the way, or WSH not being available on the system. However, it
      is the best most of us could do if we didn’t have some spendy third party library
      to provide this functionality. But then I decided to try my hand at creating another
      solution that we could all benefit from.

      Introducing the regexp.fll
      I decided it was high time that Visual FoxPro developers had a free Visual
      FoxPro Dynamic-Link Library (FLL) that would provide for regular expressions in Visual
      FoxPro, so I sat down at my copy of Visual Studio 8 and, with the help of Boost,
      I wrote one. Unfortunately the process wasn’t quite as straight forward as that last
      sentence makes it sound.

      First I toyed with the idea of writing my own in pure Visual FoxPro code. That bad
      idea, while appealing to my reinvent the wheel side, was soon discarded because it
      would be too much effort and the end result would never be able to match the performance
      that could be achieved by doing this in C++. Next I researched all of the available
      C++ libraries that were available and for a time I was using GRETA,
      but between bugs in the code, the feeling that it wasn’t being supported quite as
      well since Eric Niebler left, and some disturbing things I read about the licensing
      regarding commercial applications, I soon discarded this as well.

      After playing around with a half-dozen other libraries and comparing form, function,
      and performance of each I settled on Boost
      RegExp
       and the regexp.fll project took shape and was finished in short order.
      It probably took me as long to compile the Boost RegExp libraries as it did to write
      the actual code for this FLL.

      Just a start
      This library currently just does matching. While matching is arguably the
      thing regular expressions are used for most, there are a lot of other things that
      I will be adding to this library that will allow us to do a whole host of things in
      Visual FoxPro using regular expressions, such as return match sets, perform positional
      searches, and do replacements. Even though the library doesn’t provide for this other
      functionality, I think you will find its current matching capabilities pretty useful.

      Important note about the required C++ runtime libraries
      In order to use this FLL (which was compiled with Visual Studio 8), you will
      need the correct runtime libraries and they have to be placed on the system in a very
      specific way. I can’t tell you the number of emails I’ve gotten for the
      vfpencryption.fll that I wrote
      where developers were having problems getting it
      to work because they didn’t have the runtimes or the runtimes weren’t installed on
      the system correctly. I’m not saying I minded the emails (it’s always good to hear
      from a member of the Visual FoxPro Community), or that I don’t understand the confusion…
      I’m just saying that with Visual C++ 8.0 some of the rules have changed and we all
      have to learn the correct way to go about doing this in the age of .NET 2.0.

      The easiest way to get the correct C++ runtime libraries installed on your system
      (or a user’s system) is to just download
      the installer
      (2.48 MB) that Microsoft has provided. It has some bloat to it,
      but it is point and click easy and the libraries all get installed where they should
      be without much hassle or fuss.

      Now, for those of you that want to create install sets or just want to have the bare
      minimum required you will want to create a subdirectory named “Microsoft.VC80.CRT”
      in the same directory that the regexp.fll is in. The Microsoft.VC80.CRT subdirectory
      needs to have 4 files in it: Microsoft.VC80.CRT.manifest, msvcm80.dll, msvcp80.dll,
      and msvcr80.dll. In order to help you set this up I have created a
      zip file of this folder
      (577 KB) that you can download. You don’t have to register
      any of these files or do anything additional other than provide them as I have specified
      here. The directory structure should look like this…

      As you can see, both the Microsoft.VC80.CRT and regexp.fll are in the same directory
      (My Application). And, inside of the Microsoft.VC80.CRT subdirectory are the previously
      mentioned 4 files. This is the way to do this for any FLL that I release. (truth be
      told there are other ways to do this, but then I have to go into a whole discussion
      about the WinSxS directory and what to do on pre-XP versions of Windows… life is
      too short)

      Using the regexp.fll in Visual FoxPro
      The first thing to do is download the FLL at the link provided at
      the bottom of this blog entry and make sure that you have the C++ runtimes
      installed as described in one of the two ways above. Then you can start using
      it from within Visual FoxPro or your Visual FoxPro applications. The syntax is very
      straightforward and there is only one function to remember… RegExp(cString, cRegExpression). The
      cString parameter is the string you want searched for a match, and the cRegExpression
      is the regular expression you want used when matching. RegExp() will return .T. for
      a match and .F. for no match. It might help to see some simple coded examples (cut-n-paste
      the code below into a prg and execute it)…

      CLEAR

      *!* Let Visual FoxPro know about the new function
      *!* by setting the library to the regexp.fll
      SET LIBRARY TO LOCFILE(“regexp.fll”,”FLL”,”Locate regexp.fll”)

      LOCAL lcExpression
      *!* Validate Email addresses
      lcExpression = “^([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$”
      ?RegExp(“
      john@isp.com”,lcExpression)
      ?RegExp(“
      john@.isp.com”,lcExpression)

      *!* Validate currency amounts
      lcExpression = “^(\$)?(([1-9]\d{0,2}(\,\d{3})*)|([1-9]\d*)|(0))(\.\d{2})?$”
      ?RegExp(“$1,244,311.81”,lcExpression) && Match
      ?RegExp(“$1,24,4311.81”,lcExpression) && No Match

      *!* Validate days of the week
      lcExpression = “^(Sun|Mon|(T(ues|hurs))|Fri)(day|\.)?$|Wed(\.|nesday)?$|Sat(\.|urday)?$|T((ue?)|(hu?r?))\.?$”
      ?RegExp(“Sunday”,lcExpression) && Match
      ?RegExp(“sundae”,lcExpression) && No Match

      *!* Validate phone numbers
      lcExpression = “^[2-9]\d{2}-\d{3}-\d{4}$”
      ?RegExp(“507-562-0020”,lcExpression) && Match
      ?RegExp(“507-56-0020”,lcExpression) && No Match

      *!* release the library reference
      SET LIBRARY TO

      Boost documentation for RegExp
      You can find the documentation
      for the RegExp’s syntax
      on the Boost website (you’ll note that it is based on
      the Perl regular expression syntax). You can also find a whole host of other examples,
      information and how-tos for regular expressions by doing a quick web
      search
      .

      Here’s the link to download the regexp.fll
      I’ve included the Boost license as a ReadMe.txt with this FLL. It isn’t necessary
      to distribute this disclaimer with the FLL as the FLL is a compiled library, however
      I am including it so you can see what the license says – the basic point is that we
      are free to use this commercially. If you want more information on the license
      requirements for Boost
      .

      Download the regexp.fll (47
      KB approx)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3095405

      Another Visual FoxPro Promo

      by craigaaa3 ·

      In reply to The SPS Weblog

      I had so much fun with the
      last one
      , I decided to try my hand at creating a short Visual FoxPro promo video
      again. The online version is the same as the offline, I just provide both so those
      of you that want to can download the SWF file. Enjoy!

      Online SWF of the Visual
      FoxPro promo #2

      Offline ZIP of the
      Visual FoxPro promo #2
      (1.9 MB approx.)


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3095873

      VFP foxhead logo is a trademark

      by craigaaa3 ·

      In reply to The SPS Weblog

      Craig Berntson raises an issue
      Earlier today Craig Berntson wrote a
      short blurb on his blog
      raising the concern that the VFP foxhead logo (morphfox.gif) and
      music I am using in the Visual FoxPro promo
      video #1
      and promo
      video #2
      was infringing on copyrights and/or trademarks. I didn’t see Craig’s
      blog entry until I received an email from Microsoft telling me that the VFP foxhead
      logo was indeed a non-redistributable logo trademark that I needed to remove from
      my website.

      Copyrights/Trademarks matter to me
      As anyone who has downloaded any of my derivitative works knows, I strive
      hard to protect individual property rights and/or give credit where credit is
      due. In the interests of protecting and respecting others’ rights, I have replaced
      the VFP foxhead logo with two Microsoft approved logos in the promo videos. I have
      also replaced the soundtrack on promo video #2 with a royalty free copy of “Also Sprach
      Zarathustra” (a.k.a. the theme for 2001: A Space Odyssey) that I purchased. The soundtrack
      for video #1 is already a royalty free loop. I have also begun the process
      of removing the VFP foxhead logo from other places it appears in my code samples,
      screen shots, and the Learning Visual FoxPro videos. As some of these tasks are somewhat
      large, Microsoft has been kind enough to provided me with additional time to complete
      the removal. In any event, when you view the newest versions of the promo videos online
      you should NOT see the VFP foxhead logo.

      Important Note: Those of you that have already viewed
      the VFP promo videos may still have the older versions in your browser cache. In order
      to see and use the new videos you will need to delete these SWF files from the cache.
      Alternately, you can download the zip files and view them offline. I apologize for any inconvenience
      this may cause you.

      Microsoft has provided alternate logos for use
      I am providing copies of both of the logos that we can use in lieu of the
      VFP foxhead logo for anyone who may be interested in them. Download VFP9_Boxshot.jpg and Boxshot_VFP9.jpg.
      These are images of the Visual FoxPro CD case that has the foxhead logo on it (see
      bottom of this entry). It is my understanding that we are allowed to use these images
      as is. It is also my understanding that we can’t modify them other than simply resizing
      them, but we can use them on our websites or in videos such as I created.

      I like these logos and really appreciate that they have been provided. I would even
      go so far as to say that the promo videos look better with these logos in them as
      it gives the viewer a better sense for what exactly is being promoted.

      In the future
      Should you come across any material on this site that you believe is infringing
      on someone’s rights – copyright, trademark, or otherwise – I would appreciate
      it if you would contact me directly as soon as possible via email or
      phone (both are listed on the SweetPotato
      Software website
      ). I will work quickly to rectify the problem once I know
      about it. Thanks to Craig Berntson and Microsoft for the heads-up regarding these
      problems.

      It is my understanding that these two logos are the ones that developers may use in
      lieu of the VFP foxhead logo (morphfox.gif).


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3096410

      Visual FoxPro College Competition – Sounds Great!

      by craigaaa3 ·

      In reply to The SPS Weblog

      Electronic Filing Group’s Bill Sanders sent
      me an interesting email regarding a college competition for Visual FoxPro.

      Begin Email Quote —
      efG is producing 2 College Level Programming
      Contests in the US this year, one for spring term and another

      for fall term, to coincide with and predate 2 VFP DevCons. We are looking for volunteers
      for 4 categories:

      1. get the word out – Distribute our CollegeCon Flyers
      both in person and electronically to all of the universities in your area in both
      January and August.
       
      2. electronic virtual judges – Review submissions
      during a 3 week period and grade on a scale during April and October, no more than
      5 to an EVJ.
       
      3. electronic virtual mentors – assist CollegeCon
      entrants with basic VFP stuff online within any of the VFP online communities.
       
      4. Event Judges – need 20 per term. You will form
      the panel for the final leg of the competition and each judge will be

      assigned to do a real time stand up peer review of ONE entrant, whilst the other 19
      make scoring marks on our scoring system. We will pay for your airfare, conference
      registration fees and hotel (our 2 days plus the conference days). You’ll be responsible
      for your own food and booze. We will be taping the Final Leg and getting a video release
      from you; content will be rebroadcast after editing.
       
      For #1, there is no VFP background requirement.

      For #4, you must be a VFPGod.

      For #2 you must be a VFPGod or know how to emulate a VFPGod.

      For #3 you must have at least 2 years of experience with VFP and be able to write
      coherently in English with a modicum of code examples.
       
      for more info please email to [ CCVol at efgroup
      dot net ]”
      — End Email Quote

      From some additional information I have about the competition there will be 2 categories,
      Individual and Group, and there will be 6 prizes given away including cash, laptops,
      and MSDN subscriptions. If this materializes, and I have no reason to doubt Bill’s
      sincerity and resolve, this could be a very good thing for Visual FoxPro. I believe
      that when you take initiatives like this and add it to all of the other things that
      are currently being done in the interest of furthering Visual FoxPro, we are beginning
      to see the power of a true Community. Thanks for the email Bill and I know that the
      Visual FoxPro Community (including myself) will do what we can to help you make
      this a success.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3078099

      Creating our own Fox logos

      by craigaaa3 ·

      In reply to The SPS Weblog

      Now here’s an idea
      Bill Sanders announced (in a comment to a recent
      blog entry
      I made) that he is funding graphic artists to create 3-5 Fox logos
      that the VFP Community can use. The reason for this is that the Foxhead logo, that
      comes with Visual FoxPro 9, is a Microsoft trademarked logo that they are not giving
      us permission to use by itself. It can only be used as it is in the image of the Visual
      FoxPro 9.0 CD case. In any event, I’m excited by the prospect of these new logos and
      I can’t wait to see what Bill comes up with.

      My own stab at it
      I’m not a professional graphic artist but, intrigued by Bill’s idea of rolling
      our own, I decided to try my hand at creating a logo. I wanted something dark, to
      match the Visual FoxPro 9.0 CD case, and I wanted it to be a fox’s head. With those
      two goals in mind, the following is what I came up with. A little too menacing
      perhaps?








      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3078701

      Regular Expressions in Visual FoxPro – Part 2

      by craigaaa3 ·

      In reply to The SPS Weblog

      Just the beginning
      In an
      earlier blog entry
      I unveiled a new FLL for Visual FoxPro that would allow Visual
      FoxPro developers to use Regular Expressions for matching. That FLL, while very useful
      if you are competent with regular expressions, was just the start of what’s possible.
      Now that I have a basic library that exposes part of the functionality of Boost Regex,
      I can expand it to include additional functionality. I believe you’ll find the additions,
      which include formatting and splitting useful.

      Download the regexp.fll (61
      KB approx)


       regexp.fll
      Documentation…


      Function REGEXP()

      Signature: RegExp(cString, cRegularExpression [, nFunctionType[,
      cFormatExpression | cArrayName]])

      Parameters:

      cStringtoEncrypt – The string to be searched, formatted,
      or split

      cRegularExpression – A regular expression using Perl syntax. Additional
      documention
      .

      nFunctionType – There are currently 3 function
      types available. The value of this parameter determines the operation that RegExp
      will perform as well as its return value.

      List of currently supported functions:

      • 0 = Pattern Match – RegExp() returns .T. if a pattern is found in cString that
        matches the cRegularExpression, otherwise .F. is returned signifying that no match
        was found. This is the default behavior for RegExp() when only the first
        two parameters are sent in.
      • 1 = Format – RegExp() returns a formatted character string that is created
        by iterating through cString looking for matches of cRegularExpression and applying
        cFormatExpression to those matches found.
      • 2 = Split – RegExp() returns the number of splits when it has create an array
        of the patterns it has found in cString that match the cRegularExpression.
        The name of the array is specified by the parameter cArrayName.

      cFormatExpression | cArrayName – Depends
      on the value of the nFunctionType parameter

      • If nFunctionType is 1, then this parameter is a perl-like format string. Additional
        documentation
        .
      • If nFunctionType is 2, then this parameter is the name of the array to be created.

      Return Value:

      Depends on value of the nFunctionType parameter (see documentation for nFunctionType
      parameter above). RegExp() will return a logical value indicating whether a match
      was found if nFunctionType is 0. RegExp() will return a formatted character string
      if nFunctionType is 1. RegExp(), after succefully creating the array of splits will
      return the number of elements (number of splits) if nFunctionType is 2.

      Example of use: (cut-n-paste the following code into a PRG and execute
      it from within Visual FoxPro)

      *!* The following simple example shows how to use the RegExp()
      *!*
      function to validate, format, and split credit
      card numbers


      CLEAR

      *!* Let Visual FoxPro know about the new function
      *!* by setting the library to the regexp.fll
      SET LIBRARY TO LOCFILE(“regexp.fll”,”FLL”,”Locate regexp.fll”)

      LOCAL lcExpression
      lcExpression = “\A(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})\z”

      ? “Pattern Matches:”
      *!* Validate credit card number using RegExp()
      ?RegExp(“1234-5678-9101-1121”,lcExpression) && Match Found
      ?RegExp(“123-567-910-112”, lcExpression) && No Match Found
      ?

      ?”Formatting:”
      *!* Format credit card number using RegExp()
      ?RegExp(“1234567891011121”,lcExpression, 1, “\1-\2-\3-\4”) && Match Found
      ?RegExp(“12345678910111”, lcExpression, 1, “\1-\2-\3-\4”) && No Match Found
      ?

      *!* Split credit card number using RegExp()
      ?”Splits: ” + TRANSFORM(RegExp(“1234-5678-9101-1121”,lcExpression, 2, “arySplits”))
      && Matches Found
      ShowSplits()
      ?”Splits: ” + TRANSFORM(RegExp(“1234-5678-9101-112”, lcExpression, 2, “arySplits”))
      && No Matches Found
      ShowSplits()

      *!* release the library reference
      SET LIBRARY TO

      ***************************
      Procedure ShowSplits()
      ***************************
       LOCAL lnCounter
       FOR lnCounter = 1 TO ALEN(arySplits)
        ? CHR(9) + TRANSFORM(lnCounter) + “: ” + arySplits(lnCounter)
       ENDFOR
       ?
      ENDPROC



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3078448

      OzFoxRocks Episode 2 – The Surge

      by craigaaa3 ·

      In reply to The SPS Weblog

      Craig Bailey and Scott Scovell have produced the second
      episode of their OzFoxRocks podcast
      . Great job guys! Their content is first rate
      and the back and forth banter between the two of them is a pleasure to listen to (love
      the accents). OzFoxRocks, a great thing to listen to when you’re up coding at 3:00
      AM.

      Congratulations to Andrew MacNeill, winner
      of the “OzFoxRocker of the Month” award. Andrew was the first to begin producing regular
      podcasts of Visual FoxPro-related content and well deserving of the award.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3077545

      Regular Expressions for Visual FoxPro – Part 3

      by craigaaa3 ·

      In reply to The SPS Weblog

      Updated FLL with more functionality
      I don’t have time (it’s late) to comment too much on the changes I’ve made
      to the regexp.fll. I significantly enhanced the functionality of the regexp() function
      when it is splitting. You can now split results into an array or a cursor. I also
      fixed a couple of bugs in the code having to do with the splitting feature. In any
      event, the documentation from my
      previous blog entry
      is still good, but now you can send in parameter nFunctionType
      = 4 and you will get a cursor. Also, if you are using nFunctionType = 3 or 4, you
      can specify a Visual FoxPro command for the regular expression engine to execute each
      time a match is found (think of it as a callback function of sorts).

      An XML parsing example
      This library is really shaping up, but I think there are lots of other possibilities
      that haven’t been explored yet (Comment here on the blog or send me any good ideas
      for functionality you might have – I’d love to hear them). One thing I knew the library
      could do is parse XML. Using some regular expressions I found freely available on
      the internet, I created some sample code (see below) to show of the wonderous
      abilities of regular expressions as well as the new functionality in the FLL.

      More to come
      As cool as this may be, I’m still not really doing them (regular expressions
      or this FLL) justice. When I get more time, I’ll be back to update the documentation
      and show how this FLL gives us abilities in Visual FoxPro that we didn’t ever
      have before. Here’s the download and some example code (the ParseXML function is the
      guts of it and you need the newest regexp.fll to run this). Enjoy.

      Download the regexp.fll (63
      KB approx)



      *!* Example
      of using the
      ParseXML function
      #DEFINE CREATEANARRAY 2
      #DEFINE CREATEACURSOR 3

      LOCAL lcArrayToCreate, lcCursorToCreate, lnTotal, lnCounter
      *!* Here’s
      some sample XML
      *!* just
      to demonstrate
      TEXT TO lcSampleXML NOSHOW PRETEXT 7
      <?xml version=“1.0”?>
      <samples>
      <sample>Visual FoxPro Rocks!</sample>
      <sample>Does more before breakfast</sample>
      <sample>than other languages do all
      day</sample>
      </samples>
      ENDTEXT

      *!* Or
      you can try this using an
      XML file
      *!* You
      can get some sample XML files at
      *!* ftp://sunsite.unc.edu/pub/sun-info/standards/xml/eg/shakespeare.1.01.xml.zip

      *!* Once
      you have extracted them then
      *!* comment out the
      TEXT/ENDTEXT code above
      *!* lastly
      you can something like the following
      *!* to
      load the example XML files
      *!* lcSampleXML = FILETOSTR(GETFILE())

      *!* Create
      an array
      DIMENSION aryXMLDoc(1)
      lcArrayToCreate = “aryXMLDoc”

      lnTotal = ParseXML(lcSampleXML,
      lcArrayToCreate, CREATEANARRAY)
      CLEAR
      FOR lnCounter = 1
      TO lnTotal
          ?aryXMLDoc(lnCounter)
      ENDFOR
      MESSAGEBOX(“Parsed
      XML has been output to the screen from the array.”
      ;
              + CHR(13) + “Click
      OK to continue with the next example.”
      , ;
              64, “XML
      Parsing Complete”
      )

      *!* Create
      a cursor
      lcCursorToCreate = “crsXMLDoc”

      lnTotal = ParseXML(lcSampleXML,
      lcCursorToCreate, CREATEACURSOR)
      IF lnTotal > 0
          GO TOP IN (lcCursorToCreate)
          BROWSE
      ENDIF

      MESSAGEBOX(“Click
      OK to run the final example.”
      , ;
              64, “Begin
      Final XML Parsing Example”
      )
              
      *!* Create
      a cursor, but also execute some
      *!* VFP
      code as the
      C++ parser runs.
      *!* This
      can be used to manipulate the data

      *!* as it is retrieved
      or whatever.
      *!* The
      C++ parser in the
      FLL
      *!* will
      execute whatever command you tell it to
      lcCursorToCreate = “crsXMLDoc”

      lcVFPCommand = “DO
      AppendVFPRocks”


      lnTotal = ParseXML(lcSampleXML,
      lcCursorToCreate, CREATEACURSOR, lcVFPCommand)
      IF lnTotal > 0
          CLEAR
          GO TOP IN (lcCursorToCreate)
          SCAN ALL
              ? Splits
          ENDSCAN
      ENDIF

      **************************
      PROCEDURE AppendVFPRocks
      **************************
          Replace splits WITH “VISUAL
      FOXPRO ROCKS!”
      + splits
      ENDPROC

      *******************************
      FUNCTION ParseXML (tcXML, tcName, tnType, tcCommand)
      *******************************
      *!* This
      Function is made
      possible by the work
      *!* of
      Robert Cameron…
      *******************************
      *!* REX/Perl
      1.0

      *!* Robert
      D. Cameron “REX:
      XML Shallow Parsing with Regular Expressions”
      ,
      *!* Technical
      Report TR 1998-17, School of Computing Science, Simon Fraser

      *!* University,
      November, 1998.
      *!* Copyright
      (c) 1998, Robert D. Cameron.

      *!* The
      following code may be freely used and distributed provided that
      *!* this copyright
      and citation notice remains intact and that modifications
      *!* or
      additions are clearly identified.
      *!* http://www.cs.sfu.ca/~cameron/REX.html

      *******************************
      *!* 01-14-2006:
      Translated and modified his expressions
      *!* for use in Visual
      FoxPro with the regexp.fll
      *!* by
      Craig Boyd http://www.sweetpotatosoftware.com/spsblog

      *******************************

          LOCAL lcTextSE, lcUntilHyphen, ;
              lcUntil2Hyphens, lcCommentCE, lcUntilRSBs,
      ;
              lcCDATA_CE, lcS, lcNameStrt, lcNameChar,
      ;
              lcName, lcQuoteSE, lcDT_IdentSE, ;
              lcMarkupDeclCE, lcS1, lcUntilQMs,
      ;
              lcPI_Tail, lcDT_ItemSE, lcDocTypeCE,
      ;
              lcDeclCE, lcPI_CE, lcEndTagCE, lcAttValSE,
      ;
              lcElemTagCE, lcMarkupSPE, lcXML_SPE,
      ;
              lcExpression, lvReturn
          llWasntSet = .F.
          IF !(“\REGEXP.FLL” $
      SET(“Library”))
              SET LIBRARY TO LOCFILE(“regexp.fll”, “FLL”)
          ENDIF
          lcTextSE = “([^<]+”

          lcUntilHyphen = “[^-]*-“

          lcUntil2Hyphens = lcUntilHyphen + “(?:[^-]” + lcUntilHyphen + “)*-“

          lcCommentCE = lcUntil2Hyphens + “>?”

          lcUntilRSBs = “[^\]]*](?:[^\]]+])*]+”

          lcCDATA_CE = lcUntilRSBs + “(?:[^\]>]” + lcUntilRSBs + “)*>”

          lcS = “[
      \n\t\r]+”


          lcNameStrt = “[A-Za-z_:]|[^\x00-\x7F]”

          lcNameChar = “[A-Za-z0-9_:.-]|[^\x00-\x7F]”

          lcName = “(?:” + lcNameStrt + “)(?:” + lcNameChar + “)*”

          lcQuoteSE =“[^”]*“|’
      + “
      ‘[^’]*
          lcDT_IdentSE = lcS + lcName + “
      (?:
      + lcS + “
      (?:
      + lcName + “
      |
      + lcQuoteSE + “
      ))*
          lcMarkupDeclCE = ‘(?:[^\]”
      + “‘><]+|” + lcQuoteSE + “)*>”

          lcS1 = “[\n\r\t
      ]”


          lcUntilQMs = “[^?]*\?+”

          lcPI_Tail = “\?>|” + lcS1 + lcUntilQMs + “(?:[^>?]” + lcUntilQMs + “)*>”

          lcDT_ItemSE = “<(?:!(?:–“ + lcUntil2Hyphens + “>|[^-]” + lcMarkupDeclCE + “)|\?” + lcName + “(?:” + lcPI_Tail + “))|%” + lcName + “;|” + lcS
          lcDocTypeCE = lcDT_IdentSE + “(?:” + lcS + “)?(?:\[(?:” + lcDT_ItemSE + “)*](?:” + lcS + “)?)?>?”

          lcDeclCE = “–(?:” + lcCommentCE + “)?|\[CDATA\[(?:” + lcCDATA_CE + “)?|DOCTYPE(?:” + lcDocTypeCE + “)?”

          lcPI_CE = lcName + “(?:” + lcPI_Tail + “)?”

          lcEndTagCE = lcName + “(?:” + lcS + “)?>?”

          lcAttValSE =“[^<“]*“|’
      + “
      ‘[^<‘]*
          lcElemTagCE = lcName + “
      (?:
      + lcS + lcName + “
      (?:
      + lcS + “
      )?=(?:
      + lcS + “
      )?(?:
      + lcAttValSE + “
      ))*(?:
      + lcS + “
      )?/?>?
          lcMarkupSPE = “
      <(?:!(?:
      + lcDeclCE + “
      )?|\?(?:
      + lcPI_CE + “
      )?|/(?:
      + lcEndTagCE + “
      )?|(?:
      + lcElemTagCE + “
      )?))
          lcXML_SPE = lcTextSE + “
      |
      + lcMarkupSPE

          lcExpression = lcXML_SPE
          IF VARTYPE(tcCommand) = “C”
              lvReturn = RegExp(tcXML,
      lcExpression, tnType, tcName, tcCommand)
          ELSE
              lvReturn = RegExp(tcXML,
      lcExpression, tnType, tcName)
          ENDIF
          RETURN (lvReturn)
      ENDFUNC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3079194

      Hosting a .NET ActiveX Control in Visual FoxPro

      by craigaaa3 ·

      In reply to The SPS Weblog

      Not Supported
      Creating ActiveX controls in Visual Studio 2005 for use in Visual FoxPro
      is not officially supported by Microsoft. Now with that out of the way, let’s see
      what we can do (see screen shots at the bottom of this blog entry).

      Superior + Superior = 2XSuperior
      Visual FoxPro is generally superior to .NET in working with data. .NET is
      generally superior to Visual FoxPro when it comes to controls and visual eye candy.
      So, the idea is to marry the two and enjoy the benefits that each has to offer. Now
      before either side starts flaming me about how VFP can be visually appealing or .NET
      can work with data, you should know that I don’t care (LOL). The arguments are played
      out, and a waste of time. Better to spend our time sharing really cool code, extending
      Visual FoxPro in every way possible, and getting ready for Sedna.

      Great articles on this topic
      There are some really good articles about .NET interop that will hopefully
      help those of you not familiar with the topic to come up to speed. The first three
      links are articles that were done by Rick Strahl and relate specifically to .NET interop
      as it pertains to Visual FoxPro. The last two articles were the basis for what I’m
      about to show.

      1. Passing
        objects between FoxPro and .NET COM Components
      2. Handling
        .NET Events in FoxPro via COM Interop
      3. Creating
        multi-threaded components .NET for COM Interop with Visual FoxPro
      4. HOW TO: Sink
        Managed C# Events in Internet Explorer Script
      5. Exposing
        Windows Forms Controls as ActiveX controls

      Adventures of trying to create a .NET UserControl for use in Visual
      FoxPro
      One of the things that I like about .NET is its toolstrip and menustrip controls,
      and given the popularity of the ARG-Software’s Command
      Bars Library
       among Visual FoxPro developers I’d say I’m not the only one.
      They’re just really professional looking. So, I decided that I wanted to create a
      menustrip and a toolstrip in Visual Studio .NET and use it on a Visual FoxPro form.
      The first thing I ran into was a bunch of information on the internet that said it
      wasn’t possible to create a visual ActiveX control in .NET and use it in an environment
      like Visual FoxPro or Visual Basic 6.0. But as the search continued, I finally uncovered
      the page that is link #5 in the list above.

      So it is possible. Next thing to work out was how to get events to fire over in Visual
      FoxPro. Unfortunately I ran into the page that is link #4 above before I ran
      into Rick Strahl’s article on it (link #2 above). Oh well, while Rick’s article would
      have saved me some time, it was fairly straight forward to implement looking at the
      steps and C# code at link #4 above even if the content was not purported to be for
      Visual FoxPro. Same concept, same end result.

      Abridged version of what to do in C#

      1. Create a new Class Library project that consists of a UserControl
      2. Throw a toolstrip and a menustrip in your UserControl
      3. Set the modifier property for each to Public so you can see them from Visual FoxPro
      4. At the top of your source file add the following using statments:

        using System;
        using System.Text;
        using System.Windows.Forms;
        using System.Runtime.InteropServices;
        using System.Reflection;
        using Microsoft.Win32;

      5. In the namespace block of your control code define delegates for
        the events like this:

        namespace DotNetControl
        {
        [ComVisible(false)]
        public delegate void MyClick1EventHandler();
        [ComVisible(false)]
        public delegate void MyClick2EventHandler();

      6. Define a public interface to expose the events of your UserControl
        class in Visual FoxPro like this (Notice the Guid, InterfaceType, and DispId attributes
        – you’ll need to generate your own Guid):

        [GuidAttribute(“F11EC17C-59E1-42D1-AE96-712AB79F20AB”)]
        [
        InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
        public interface ControlEvents
        {
        [
        DispIdAttribute(1)]
        void MyClick1();
        [
        DispIdAttribute(2)]
        void MyClick2();
        }

      7. The beginning of your class definition should look something like
        the following (Notice the Guid, ProgId, ClassInterface and ComSourceInterfaces – generate
        your own Guid and make sure the parameter sent to typeof is the same as
        the public interface you created in step 6) :

        [Guid(“2DEFE6F9-6738-454C-BEF1-CF944E7F5F06”)]
        [
        ProgId(“DotNetControl.DotNetToolbar”)]
        [
        ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))]
        public partial class DotNetToolbar : UserControl
        {
        public DotNetToolbar()
        {
        InitializeComponent();
        }

      8. Specify your events

        event DotNetControl.MyClick1EventHandler MyClick1;
        event DotNetControl.MyClick2EventHandler MyClick2;>

      9. In the designer double-click on the controls that you are exposing events for and
        you will end up with some method code blocks like the following being added (Notice
        I have added some simple if condition blocks to call the events we defined in
        step #8) :

        private void myToolStripButton_Click(object sender, EventArgs e)
        {
        if (MyClick1 != null)
        {
        MyClick1();
        }
        }

        private void myToolStripMenuItem_Click(object sender, EventArgs e)
        {
        if (MyClick2 != null)
        {
        MyClick2();
        }
        }
        >
        >

      10. Override the Dispose method:

        protected override void Dispose(bool disposing)
        {
        if (disposing)
        {
        if (components != null)
        components.Dispose();
        }
        base.Dispose(disposing);
        }
        >
        >>

      11. Add the following method to your class (Notice since it has been attributed with ComRegisterFunction
        this code will fire when the assembly is registered for COM interop)



        //copyright Morgan Skinner, 2001
        [ComRegisterFunction()]
        public static void RegisterClass(string key)
        {
        // Strip off HKEY_CLASSES_ROOT\ from the passed
        key as I don’t need it
        StringBuilder sb = new StringBuilder(key);
        sb.Replace(
        @”HKEY_CLASSES_ROOT\”, “”);
        // Open the CLSID\{guid} key for write access
        RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
        // And create the ‘Control’ key – this allows it
        to show up in

        // the ActiveX control container

        RegistryKey ctrl = k.CreateSubKey(“Control”);
        ctrl.Close();
        // Next create the CodeBase entry – needed if not
        string named and GACced.
        RegistryKey inprocServer32 =
        k.OpenSubKey(
        “InprocServer32”, true);
        inprocServer32.SetValue(
        “CodeBase”, Assembly.GetExecutingAssembly().CodeBase);
        inprocServer32.Close();
        // Finally close the main key
        k.Close();
        }
        >

      12. Add the following method to your class (Notice since it has been attributed
        with
        ComUnRegisterFunction this code will fire when the assembly
        is unregistered)

        //copyright Morgan Skinner, 2001

        [ComUnregisterFunction()]
        public static void UnregisterClass
        (
        string key )
        {
        StringBuilder sb = new StringBuilder (
        key ) ;
        sb.Replace(
        @”HKEY_CLASSES_ROOT\”,“”)
        ;
        // Open HKCR\CLSID\{guid} for write access
        RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
        // Delete the ‘Control’ key, but don’t throw an
        exception if it does not exist
        k.DeleteSubKey ( “Control” , false )
        ;
        // Next open up InprocServer32
        RegistryKey inprocServer32 =
        k.OpenSubKey (
        “InprocServer32” , true )
        ;
        // And delete the CodeBase key, again not throwing
        if missing

        k.DeleteSubKey ( “CodeBase” , false )
        ;
        // Finally close the main key

        k.Close ( ) ;
        }

      13. In your solution’s properties do the following:

      • Checkmark the “Register for COM interop” checkbox on the Build page
      • Checkmark the “Make assembly COM-visible” checkbox in the Assembly Information screen
        accessible from the Application page (alternately you can just open up the AssemblyInfo.cs
        file and make sure it says:
        [assembly: ComVisible(true)]

      After you’ve completed these steps, you can build your assembly and you should have
      a useable ActiveX control for use in environments such as Visual FoxPro and Visual
      Basic 6.0. You may see some warning regarding non COM visible value types during the
      build, but there shouldn’t be any errors and the assembly should be in your bin directory.
      If you get stuck on any of the steps above, you can always refer to C# solution I
      am including in the download at the bottom of this page.

      How to use the ActiveX in Visual FoxPro
      Once you have built your ActiveX control you can then proceed to use it in
      Visual FoxPro. If you aren’t building the control (which will register the control
      for COM interop on your system) and just want to use one like I made, you’ll have
      to register the DLL with REGASM.
      The same holds true for when you distribute the control. You’ll either need to include
      it in an installer package that was created with a program that understands how to
      register .NET assemblies or you’ll have to use regasm on the user’s system. If you’ve
      never heard of Regasm before this, you can think of it as very much like RegSvr32.

      In any event, for the control that I’ve created you’ll want to follow the following
      steps in Visual FoxPro:

      1. Make sure the .NET assembly (DLL) has been registered on your system
      2. Go to Tools->Options and on the resultant Options screen go to the Controls page,
        select ActiveX and scroll down through the list of ActiveX controls until you find
        the .NET control you want. In the case of the control I built, it will be named DotNetControl.DotNetToolbar.
        Place a checkmark next to it and then click OK
      3. Create a new form and on the Form Controls toolbar click the View Classes dropdown
        button (looks like library books) and select ActiveX controls.
      4. Select the button that is provided for the DotNetToolbar and place an instance of
        it on your form
      5. Resize and position the resultant menu/toolbar at the top of your form and set its
        Anchor property to 11.
      6. Go into the methods of the control and add whatever code you want to the ToolClick
        and MenuClick events (such as toolnewclick, toolsaveclick, menuexitclick, menuhelpclick,
        etc.)
      7. Run your form.

      I am providing a sample form in the download for this blog entry. I haven’t done much
      with those events except add messageboxes to show that they fire. Also, I’ve provided
      an optiongroup that will set the RenderMode of the toolstrip and menustrip just to
      show that we aren’t limited to events that we have exposed through the interface.
      Public objects and their properties are accessible as well.

      Just the beginning of what’s possible
      In this blog entry I am merely showing that it is possible to create .NET
      ActiveX controls for use in Visual FoxPro. More is possible, such as starting with
      an empty menustrip and empty toolstrip and allowing the Visual FoxPro developer to
      add items to the .NET controls dynamically. Plus, the toolstrip and menustrip are
      but two examples of many other controls that could be made for use in Visual FoxPro.
      Extending Visual FoxPro by utilizing the .NET framework is powerful, and the chief
      reason I wholeheartedly support the Sedna initiative put forward by the Micorosft
      Fox Team. It was, in my opinion, the right decision based on the resources available
      and the benefits to be gained. Coupling Visual FoxPro’s unmatched data handling abilities
      with the best that .NET has to offer is a very powerful combination.

      Source download and the screen shots

      Download
      Source and Example VFP Form
      (51 KB approx.)

      Note: In the download the example form is contained in the VFPExampleForm subdirectory
      and the .NET control is contained in the bin\Release subdirectory. The .NET control
      MUST be registered using Regasm before you can run the VFP example form.

       



      .NET menustrip and toolstrip look professional



      Menus have great theme support



      Resizing the form will cause toolstrip to show dropdown button



      Using the optiongroup the RenderMode can be changed



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3099170

      Registering the .NET ActiveX

      by craigaaa3 ·

      In reply to The SPS Weblog

      Problems with registering
      I received a few comments and a couple of emails regarding how to properly
      register the ActiveX
      Menustrip/Toolstrip
      . The problem is that even after registering the control with
      RegAsm, the developer gets either an error about the control not being registered
      or an error about a specified file not being found. The second of these error messages
      is closer to the truth, since the problem is that even though the control is registered
      the system can’t find the assembly. Now there are a few ways you can fix this, some
      are better than others.

      First way (definitely a bad idea)
      The first way to do this is to put it in the Global
      Assembly Cache (GAC)
       which has two problems, it’s a bad idea to be gunking
      up your (or your customers) GAC with a bunch of home-grown assemblies and since
      the original release I put out for download is not signed with a strong name it won’t
      work.

      Second way (probably a bad idea)
      The second way to do this is to use the /codebase switch with regasm.exe.
      To find out what the codebase switch does you can read about it at Assembly
      Registration Tool
      . The basic command line command to do this:

      regasm /codebase dotnetcontrol.dll

      Just in case you don’t know, you may need to include the full path to both regasm
      and the dotnetcontrol.dll in the command above. So for you it might be something more
      like:

      C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /codebase C:\DotNetControl\DotNetControl.dll

      The problem with this approach is that since the assembly (dotnetcontrol.dll) isn’t
      signed with a strong name you’ll get a scarey message like the following when you
      run register the assembly with the /codebase switch:

      RegAsm : warning RA0000 : Registering an unsigned assembly with /codebase can
      ca
      use your assembly to interfere with other applications that may be installed on
      the same computer. The /codebase switch is intended to be used only with signed
      assemblies. Please give your assembly a strong name and re-register it.
      Types registered successfully

      Now, I personally think the warning message is a little overblown, but if they say
      that the /codebase switch should only be used for assemblies with a strong name then
      let’s move on to the third way to do this.

      Third way
      Download
      the assembly I’ve rebuilt
      . It is signed with a strong name so you can use the
      /codebase switch without getting that scarey message above. If you’ve already registered
      the one from my previous blog entry then unregister it. Then register this new one
      using the same steps given in the second way I presented above.

      How to sign an assembly with a strong name
      For those of you that are working with the C# project and would like to know
      how to sign your assembly with a strong name, you can read about it in Signing
      an Assembly with a Strong Name
      . Basically the easiest way to do it is to use sn.exe
      (comes in the SDK) to create a strong name key file (.SNK). Then put that strong name
      key file in your project somewhere. Finally open up the AssemblyInfo.cs file in your
      project and put the following line at the bottom of it (you need either the fullpath
      or relative path to the key file inside the quotes):

      [assembly:AssemblyKeyFileAttribute(@”sgKey.snk”)]

      Now you can rebuild your assembly and it will be signed with a strong name.

      Parting thoughts
      When creating controls or examples with .NET whether it be an FLL,
      an ActiveX control, or whatever it pays to take the time to map out the steps for
      properly installing the runtimes or registering the control. A few extra
      minutes on my part could have saved some of you precious time. You have my apologies
      and I think I’ve learned my lesson this time. Special thanks to Bernard Bout and Gary
      Williams for being the first two developers to bring this issue to my attention.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3098735

      Visual FoxPro Encryption – using VC++ 7.1 runtimes

      by craigaaa3 ·

      In reply to The SPS Weblog

      Rebuilt using Visual Studio 2003
      Developers continue to have problems using the FLLs that I have created using
      Visual Studio 8.0. These problems are in installing the VC++ runtimes for FLLs, or
      the developers are turned off by the size of the runtimes required for these FLLs.
      So, against my better judgement I have created a Visual Studio 2003 version of vfpencryption,
      named vfpencryption71.fll.

      My thoughts on this
      This is not a good idea because it gets this particular FLL stuck in
      a particular version of C++, it makes me maintain two entirely seperate projects.
      The savings in size aren’t all that great (VC++ 80 runtimes are only 789 KB bigger
      than the VC++ 71 runtimes – yes, I know that msvcr71.dll is already distributed with
      VFP 9 applications, but even then we are talking something just over 1 MB in
      size difference). In the age of 300+ GB hard drives and broadband, the drawbacks
      just don’t seem worth it to me.

      The VC++ 8.0 runtimes can be deployed by just copying them to the users harddrive
      as I’ve shown in a
      previous blog entry
      (see “Important note about the required C++ runtime
      libraries”
      in that entry), or they can be installed using one of the available
      installers provided by Microsoft, or they can be installed by creating an install
      for your application using installshield that includes them. I was hoping that I could
      convince most Visual FoxPro developers to use the FLLs that were built with the newest
      version of VC++. But, some developers are still having problems, or have expressed an
      adamant opinion that they do not want to be dependent on the VC++ 8.0  runtimes.
      So, I am hopeful that by providing this alternate build of the vfpencryption FLL that
      I am able to ease the pain somewhat.

      NOTE: This will be the only FLL that I will be providing a VC++ 7.1
      build for. All other FLLs and projects that I create for use in Visual FoxPro will
      be done exclusively using the newest version of Visual Studio. It is my strong opinion
      that Visual FoxPro and the applications that are created with it must continue to
      move forward. Please know that I understand why some developers want these FLLs to
      be built with the earlier version of VC++. I just don’t agree with it.

      For those of you that are using the
      newest version
      (vfpencryption.fll) there is nothing new in this build. The functions
      in vfpencryption71.fll are the same as those provided in the vfpencryption.fll. The
      only changes will be in your Visual FoxPro code, SET LIBRARY TO will point to vfpencryption71.fll,
      and the VC++ runtimes that are needed are the 7.1 libraries instead of the 8.0
      libraries as noted below.

      Here is the vfpencryption71.fll (required VC++ runtimes are msvcr71.dll and msvcp71.dll):

      Download vfpencryption71.fll (59
      KB approx.)

       


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3107460

      FoxShow #36: Interview with SednaX

      by craigaaa3 ·

      In reply to The SPS Weblog

      Doug Hennig, Rick Schummer, and I had the privilege of being interviewed by Andrew
      MacNeill for the FoxShow yesterday regarding SednaX.
      Andrew has the interview online at FoxShow
      #36: Interview with SednaX
      . If you’re interested in helping the Visual FoxPro
      Community improve Visual FoxPro through SednaX, this interview will give you more
      information on what SednaX is, what it isn’t, and where its headed.

      Thanks to Rick, Doug, and Andrew for taking the time to make this interview happen.
      There’s nothing I enjoy more than talking about the great things happening in the
      Visual FoxPro Community. I had a blast.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3133445

      State of the Language Address

      by craigaaa3 ·

      In reply to The SPS Weblog

      The State of Visual FoxPro
      Visual FoxPro and the Community that vigorously supports it has made many
      positive strides in the last year. With Visual FoxPro 9.0 in hand, Sedna on the horizon,
      and many Community driven efforts to improve and enhance the language, the state of
      Visual FoxPro is strong and will continue to strengthen in the coming years. Visual
      FoxPro and the experienced developers that are working in it are providing customers
      with a sound, cost-effective, high-performance alternative for their data-centric
      applications. Customers respond to value and Visual FoxPro developers continue to
      deliver that value day-in and day-out using the greatest data-centric development
      tool Microsoft currently has in its product line. This is not hype, this is not wishful
      thinking… this is the simple truth. When it comes to creating today’s data-centric
      applications, Visual FoxPro has absolutely no equal.

      Fox Team changes
      Many may have noted over the last year that a number of key Microsoft Fox
      Team employees have left the fold. Randy Brown, a program manager with over 10 years
      on the team, influenced or had a hand in more Visual FoxPro features than any other
      individual on the planet. John Koziol, in charge of managing the testing for
      Visual FoxPro, helped develop a testing strategy that led to one of the most stable
      releases of Visual FoxPro to date in version 9.0 of the product. And last, but not
      least, Ken Levy, to many the face of Visual FoxPro at Microsoft, has announced
      today that he is leaving
      the Microsoft Fox Team. I am grateful for everything
      these men contributed and wish them well in there new endeavours or positions at Microsoft.

      What is one to make of all this turn-over at the Microsoft Fox Team? Nothing. Yep,
      that’s right… not a thing. Call it an omen or a passing of some symbolic torch if
      you will, but to me and many others it has next to no impact on Visual FoxPro,
      the developers that work with it, and last, but most importantly, the customers we
      serve. Microsoft employees come and go on the Fox Team just as they do in many Microsoft
      departments. If you ask me, it is a sheer testament to the Visual FoxPro product and
      the loyalty that it engenders that people like Randy Brown and Ken Levy stayed with
      the Fox Team for as long as they did. We can certainly while away our keystrokes
      on the members we’ve lost, but in this State of the Language address, I think I’ll
      talk about some of the people and things that have been gained or are still around.

      Richard Stanton
      Showed up sometime in 2002 after he graduated and along with a contractor
      or two (Colin Nicholls?) turns
      out the Visual FoxPro 9.0 reporting engine, the features and capabilities of which
      few VFP developers have begun to scratch. You rock Richard! And, don’t think for a
      moment that your efforts and brilliance went unnoticed at this end.

      Calvin Hsia
      Lead developer on Visual FoxPro for some time and still using his free-time
      to post great Visual FoxPro-related content on his
      blog
      . YAG has no doubt buried him in work on the LINQ project for Visual Studio
      9.0, but it’s not Calvin’s fault. Calvin has a better understanding of the code in
      Visual FoxPro’s core than anyone else alive and much of his previous work and experience
      made Visual FoxPro 9.0 possible. Developers of Visual FoxPro applications benefit
      on a daily basis from the hardwork that Calvin put into the product.

      Milind Lele
      A relatively fresh face on the Microsoft Fox Team that is now the VS
      Data Program Manager. Whatever that ostentatious title may mean, he appears to be
      the man in charge of Sedna and by extension, Visual FoxPro moving forward. I spoke
      with Milind Lele at length down at the 2005 Southwest Fox Conference and I can tell
      you that he comes from a Security-based background and is very bright. I expect to
      see great things from Milind. Note to self: Stop sucking up to Ken Levy and start
      sucking up to Milind Lele.

      Extensibility, new EULA, and Sedna
      These are the building blocks that make it possible for Visual FoxPro to
      be improved and enhanced outside of Microsoft. There are hundreds of features in Visual
      FoxPro 9.0 that few Visual FoxPro developers even know about. These features allow
      Visual FoxPro to be extended and improved in ways yet to be imagined. That coupled
      with the surprising EULA change for XSource, shows that Microsoft’s Fox Team is clearly
      empowering Visual FoxPro developers to collaborate and work together to share enhancements
      and improve Visual FoxPro in a big way. There’s more to this story, though I am regrettably
      contractually unable to speak about it. Needless to say more tricks are up sleeves and
      the future for Visual FoxPro, the developers that work in it, and the customers that
      rely on it is as bright as we want to make it.

      The Visual FoxPro Community
      The only crew of developers big enough, experienced enough, and in-touch
      enough with the needs of the hundreds of thousands of customers we produce and maintain
      applications for to take Visual FoxPro where it needs to go. As we make
      the transition from a language mostly improved/enhanced by scant resources at Microsoft
      to one that is improved and furthered by this large Community of developers devoted
      to inventing Visual FoxPro’s future, you’re going to see an explosion of resources,
      enhancements, and visibility for Visual FoxPro. The fuse has already been lit by countless
      blogs, podcasts, forums, downloads, community driven efforts like SednaX,
      and a fundamental change in the mindset of most Visual FoxPro developers.

      Blitzy ad campaigns
      Ultimately we developers and the customers out there that are so ill-served
      by flavor of the month languages for serious data-centric applications hold the cards.
      Visual FoxPro and our future is what we make of it. Make no mistake, this isn’t business
      as usual for us, or for Microsoft. Visual FoxPro is absolutely the best product Microsoft
      has or will have for the foreseeable future when it comes to building data-centric
      applications. We know it and Microsoft certainly knows it (they’re working overtime
      at MS to implement FoxPro-like features into Visual Studio). And, the great thing
      about customers, is they know value when they see it and are not as swayed by marketing
      hype as they once were. Blitzy ad campaigns don’t solve problems and empower businesses
      to make the most of their information. Blitzy ad campaigns don’t allow companies to
      work smarter by lowering risk and improving efficiency. Blitzy ad campaigns are
      designed to sell a product and make the vendor of that product money. Sometimes the
      product featured in the ad campaign lives up to the hype, but more often than not
      it doesn’t. Far too often the developer is less productive and experienced with the
      new tool and the customer is given less bang for their hard earned buck. Developers
      or customers that make critical business decisions based on blitzy ad campaigns are
      far too often burned these days.

      No ad campaign here, just value
      On the other hand, Visual FoxPro, is about the business of saving developers
      and customers time, decreasing risk, maximizing the potential of information, increasing
      efficiency and lowering costs. No blitzy ad campaign from Microsoft, just developers
      with loads of experience and a development tool that has been improving and cranking
      out solutions for decades that best serve the customer’s needs. If you’re in the market
      for a great data-centric development tool or a solution created with one, then you
      owe it to yourself and your company to give Visual
      FoxPro 9.0
      and the developers that work in it a serious look.

      God bless our customers, and God bless Visual FoxPro!


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3107578

      Visual FoxPro Conferences for 2006

      by craigaaa3 ·

      In reply to The SPS Weblog

      Conferences, Conferences, and more Conferences
      Below is a list of Visual FoxPro conferences that I know of in 2006.
      My hat is off to all of the conference organizers and speakers. Even the smallest
      of these conferences has to be a large and complicated undertaking. Please know that
      myself and many others in the VFP Community appreciate your efforts.

      For those of you trying to decide which conference(s) to attend, the Universal Thread
      has provided some great coverage for many of these conferences in years past, so head
      on over to the UT Coverage Area if you want
      to know what they were like before. Which of these conferences will I be at? To be
      honest, I’ve just started seriously thinking about which conferences to attend or
      speak at. I’d like to go to them all. There’s gotta be nothing like a whirlwind world
      tour of Visual FoxPro conferences – no sleep, awesome code, great sessions, fireworks,
      and a parade of developers chanting, “Visual FoxPro Rocks!” in unison as they march
      on Redmond, Washington! OK, I got a little carried away there. Here’s the conference
      list…

      OzFox Lite

      Dates: March 25-26, 2006

      Location: Sydney, Australia

      Registration Fee: ??? (perhaps less than $100)

      Overview: A low cost Microsoft Visual FoxPro conference, with
      presentations given by local VFP developers.

      Great
      Lakes Great Database Workshop


      Dates: April 21-24, 2006

      Location: Milwaukee, Wisconsin

      Registration Fee:
         By midnight, Friday, March 24 for $475
         By midnight, Friday, April 14, for $525
         By midnight, Friday, April 21, for $655

      Overview: One track consisting of 14 sessions held sequentially from
      Friday night through Monday noon, covering virtually every major aspect of Fox development
      best practices.

      ADVISOR DEVCON on MICROSOFT
      VISUAL FOXPRO


      Dates: August 27-31, 2006

      Location: Phoenix, Arizona

      Registration Fee: ???

      Overview: An annual technical conference on Microsoft VFP database
      software, including architecting, development, integration, administration, performance,
      and more…

      OzFox

      Dates: ??? (probably Semptember 2006)

      Location: Sydney, Australia

      Registration Fee: ???

      Overview: ???

      Fox Forward

      Dates: September 15-17, 2006

      Location: Alpharetta, Georgia

      Registration Fee: To Be Announced

      Overview: The Fox Forward conference is a great opportunity to not
      only look at our favorite technology, but to compare and contrast it with other (competing?)
      technologies in an open, honest, and frank way… The intention of the Fox Forward
      conference is to be an all volunteer conference for developers, by developers. Every
      effort will be made keep the conference as reasonable in cost as possible.

      Southwest Fox

      Dates: October 19-22, 2006

      Location: Tempe, Arizona

      Registration Fee: $595

      Overview: ???

      German DevCon

      Dates: November 9-11, 2006

      Location: Frankfurt, Germany

      Registration Fee: ???

      Overview: ???


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3107577

      Visual FoxPro on Windows Vista

      by craigaaa3 ·

      In reply to The SPS Weblog

      Windows Vista is on it’s way
      Many
      are speculating
      that Microsoft is doing whatever it takes to get their newest OS
      released before the end of 2006
      . It won’t be long and Visual FoxPro developers
      will be catering to customers running Windows Vista. Microsoft’s Visual
      FoxPro Roadmap
      has Sedna currently scheduled for release sometime around the 2Q
      of 2007. This could lead some Visual FoxPro developers to be somewhat alarmed as one
      of the things that Sedna will provide is the ability for Visual FoxPro applications
      to be more successfully deployed on Windows Vista.

      Seems to work fine
      In order to ascertain just what kinds of problems we are going to run into
      deploying and running Visual FoxPro 9.0 applications on Windows Vista without Sedna,
      I decided to give it a go. I installed Windows Vista Beta 2 – Build 5231 on a
      Windows XP Professional box using Microsoft’s
      Virtual Server 2005
      . Then I installed a copy of Visual FoxPro 9.0 SP1 into Windows
      Vista and started playing around with it. While it will be sometime before I
      can make a final determination regarding the complete viability of deploying Visual
      FoxPro 9.0 applications on Windows Vista, for now I am quite pleased with how well
      Visual FoxPro appears to run and act in Windows Vista. I’ll report back with more
      once I have had the time to take a closer look. For now, here’s a screen shot of Visual
      FoxPro running like a top on Windows Vista.

      NOTE: Given that I am using Microsoft’s Virtual Server,
      the Aero Glass effects are not enabled because the graphics card emulator doesn’t
      support them. This is not a limitation of Visual FoxPro, but rather a limitation of
      the environment in which I am hosting Windows Vista.



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3090951

      Change Mouse Cursor

      by craigaaa3 ·

      In reply to The SPS Weblog

      Setting the System Cursor
      Someone out on the Universal Thread was
      asking how to set the mouse cursor to a string of text. Doing this is pretty straight-forward
      with GDI+ and Visual FoxPro 9.0. The following runnable example will save the current
      mouse cursor icon and then change it to the string “VFP ROCKS!”. It will also allow
      you to select an image file to use as your mouse cursor, which is really the technique
      that makes the previous string example possible. Finally, after the two examples have
      run it will set your mouse cursor back the way it was (saving a trip into Control
      Panel -> Mouse). Just cut-n-paste the following code into a PRG file in Visual
      FoxPro 9.0 and execute it.

      IMPORTANT NOTES: The active portion of the cursor is the
      center of the image. Images for the second example aren’t limited to icons only, most
      other image formats are supported. But, be careful how big the image is you select
      for the 2nd example. I was dragging around a huge screen shot as my mouse cursor at
      one point… it makes it a little difficult to click on things. LOL

      LOCAL
      lnPreviousIconHandle, lnNewIconHandle, lcImageFile, loExc as Exception
      *!* Save
      the current icon handle so we can set it
      back
      m.lnPreviousIconHandle = GetCurrentCursorHandle()
      IF m.lnPreviousIconHandle
      != 0
          TRY

          m.lnNewIconHandle = GetHICONFromString(“VFP
      ROCKS!”
      , 0, 0, “Arial”,
      12, 1, 3, RGB(255,0,0),
      255, 0)
          IF m.lnNewIconHandle
      != 0
              SetSystemCursorToHICON(m.lnNewIconHandle)
          ENDIF
          MESSAGEBOX(“Click
      OK when you are ready for the next example.”
      )
          SET DEFAULT TO (ADDBS(HOME(4)) + “Icons\Computer\”)
          m.lcImageFile = GETPICT(“”,“Select
      an image file”
      , “Select”)
          m.lnNewIconHandle = GetHICONFromImage(m.lcImageFile)
          IF m.lnNewIconHandle
      != 0
              SetSystemCursorToHICON(m.lnNewIconHandle)
          ENDIF
          MESSAGEBOX(“Click
      OK when you are ready to return the cursor to its orginal image.”
      )
          CATCH TO loExc
              *!* Ooops!
          FINALLY

              *!* Set icon
      handle back to the
      way it was
              SetSystemCursorToHICON(m.lnPreviousIconHandle)
          ENDTRY
      ENDIF

      ***************************************
      Function GetCurrentCursorHandle()
      ***************************************
          LOCAL lnReturn
          DECLARE INTEGER CopyIcon IN Win32Api INTEGER

          DECLARE INTEGER GetCursor IN WIN32API AS _GetCursor
      *!* Save
      current cursor so we can restore it
          m.lnReturn = CopyIcon(_GetCursor())
          CLEAR DLLS “CopyIcon”, “_GetCursor”

          RETURN (lnReturn)
      ENDFUNC

      ***************************************
      FUNCTION SetSystemCursorToHICON(tnIconHandle,
      tnCursorStateToSet)
      ***************************************
      *!* Defines
      are provided so you‘ll
      know


      *!* what‘s
      available


      #define OCR_NORMAL 32512
      *!*    #define
      OCR_IBEAM 32513
      *!*    #define
      OCR_WAIT 32514
      *!*    #define
      OCR_CROSS 32515
      *!*    #define
      OCR_UP 32516
      *!*    #define
      OCR_SIZE 32640 /* OBSOLETE: use OCR_SIZEALL */
      *!*    #define
      OCR_ICON 32641 /* OBSOLETE: use OCR_NORMAL */
      *!*    #define
      OCR_SIZENWSE 32642
      *!*    #define
      OCR_SIZENESW 32643
      *!*    #define
      OCR_SIZEWE 32644
      *!*    #define
      OCR_SIZENS 32645
      *!*    #define
      OCR_SIZEALL 32646
      *!*    #define
      OCR_ICOCUR 32647 /* OBSOLETE: use OIC_WINLOGO */
      *!*    #define
      OCR_NO 32648
      *!*    #define
      OCR_HAND 32649
      *!*    #define
      OCR_APPSTARTING 32650
          IF PCOUNT() = 1
              m.tnCursorStateToSet = OCR_NORMAL
          ENDIF
          DECLARE SetSystemCursor IN Win32Api INTEGER, INTEGER

          SetSystemCursor(m.tnIconHandle,m.tnCursorStateToSet)
          CLEAR DLLS “SetSystemCursor”

      ENDFUNC

      ***************************************
      Function GetHICONFromImage(tcImageName)
      ***************************************
          LOCAL lnIconHandle, lnBitmap, lnReturn

          STORE 0 TO m.lnIconHandle,
      m.lnBitmap, m.lnReturn

          DECLARE INTEGER GdipCreateBitmapFromFile IN GDIPLUS.DLL
      ;
              STRING wFilename, INTEGER @
      nImage
          DECLARE LONG GdipCreateHICONFromBitmap IN GDIPLUS.DLL
      ;
              INTEGER nBitmap, INTEGER @hbmReturn

          IF !EMPTY(tcImageName)
              GdipCreateBitmapFromFile(STRCONV(m.tcImageName+CHR(0),5),
      @m.lnBitmap)
              IF m.lnBitmap
      != 0
                  GdipCreateHICONFromBitmap(m.lnBitmap,
      @m.lnIconHandle)
                  IF m.lnIconHandle
      != 0
                      m.lnReturn = m.lnIconHandle
                  ENDIF
              ENDIF
          ENDIF
          CLEAR DLLS “GdipCreateHICONFromBitmap”, “GdipCreateBitmapFromFile”

          RETURN m.lnReturn
      ENDPROC

      ***************************************
      PROCEDURE GetHICONFromString(tcString, tnXCoord, tnYCoord, tcFontName, ;
                                  tnFontSize,
      tnFontStyle, tnUnitofMeasure, ;
                                  tnRGB,
      tnAlpha, tnStringFormat)
      ***************************************
          LOCAL logpColor, logpSolidBrush, logpFont, ;
              logpStringFormat, logpPoint, logpGraphics,
      ;
              logpBitamp, lnBitmap, lnIconHandle
              
          DECLARE LONG GdipCreateHICONFromBitmap IN GDIPLUS INTEGER nBitmap, INTEGER @hbmReturn
          DECLARE LONG GdipSetTextRenderingHint IN GDIPLUS LONG graphics, LONG mode
          DECLARE LONG GdipSetInterpolationMode IN GDIPLUS LONG graphics, LONG interpolation
          DECLARE LONG GdipSetSmoothingMode IN GDIPLUS LONG graphics, LONG SmoothingMd

          IF TYPE(“m.tcString”) = “C” AND TYPE(“m.tnXCoord”) = “N” ;
                  AND TYPE(“m.tnYCoord”) = “N” AND TYPE(“m.tcFontName”) = “C” ;
                  AND TYPE(“m.tnFontSize”) = “N”

              SET CLASSLIB TO (ADDBS(HOME(1)) + “FFC\_gdiplus.vcx”)
              
              *!* If the
      last 4 params weren‘t
      sent in, then give them default values


              IF TYPE(“m.tnFontStyle”)
      != “N”

                  m.tnFontStyle = 0
              ENDIF
              IF TYPE(“m.tnUnitofMeasure”)
      != “N”

                  m.tnUnitofMeasure = 3
              ENDIF
              IF TYPE(“m.tnRGB”)
      != “N”

                  m.tnRGB = 0
              ENDIF
              IF TYPE(“m.tnAlpha”)
      != “N”

                  m.tnAlpha = 255
              ENDIF
              IF TYPE(“m.tnStringFormat”)
      != “N”

                  m.tnStringFormat = 0
              ENDIF

              m.logpColor = CREATEOBJECT(“gpcolor”, MOD(m.tnRGB,
      256), ;
                  MOD(BITRSHIFT(m.tnRGB,
      8), 256), ;
                  MOD(BITRSHIFT(m.tnRGB,
      16), 256), ;
                  m.tnAlpha)
              m.logpSolidBrush = CREATEOBJECT(“gpsolidbrush”,
      m.logpColor.argb)
              m.logpFont = CREATEOBJECT(“gpfont”,
      m.tcFontName, m.tnFontSize, m.tnFontStyle, m.tnUnitofMeasure)
              m.logpStringFormat = CREATEOBJECT(“gpstringformat”,
      m.tnStringFormat)
              m.logpPoint = CREATEOBJECT(“gppoint”,
      m.tnXCoord, m.tnYCoord)
              m.logpbitmap = CREATEOBJECT(“gpBitmap”)
              
              *!* Could
      use GdipMeasureString to get the
              *!* measurements
      so that the size wasn‘t

              *!* hardcoded
      here
              m.logpbitmap.CREATE(110, 24)
              m.logpGraphics = CREATEOBJECT(“gpgraphics”)
              m.logpGraphics.CreateFromImage(m.logpbitmap)
              
              *!* The
      following 3 lines of code make the
              *!* rendered
      text look nice not all
      jagged
              GdipSetTextRenderingHint(m.logpGraphics.gethandle(),
      3)
              GdipSetInterpolationMode(m.logpGraphics.gethandle(),
      7)
              GdipSetSmoothingMode(m.logpGraphics.gethandle(),
      4)
              m.logpGraphics.DrawStringA(m.tcString,
      m.logpFont, m.logpPoint, m.logpStringFormat, m.logpSolidBrush)
              m.lnIconHandle = 0
              GdipCreateHICONFromBitmap(m.logpbitmap.GetHandle(),
      @m.lnIconHandle)
              m.lnReturn = m.lnIconHandle
              STORE .NULL. TO m.logpbitmap,
      m.logpColor, m.logpSolidBrush, m.logpFont, m.logpStringFormat, m.logpPoint, m.logpGraphics
              RELEASE m.logpbitmap, m.logpColor,
      m.logpSolidBrush, m.logpFont, m.logpStringFormat, m.logpPoint, m.logpGraphics
          ENDIF
          CLEAR DLLS “GdipCreateHICONFromBitmap”, “GdipSetTextRenderingHint”,
      ;
                      “GdipSetInterpolationMode”, “GdipSetSmoothingMode”

          RETURN m.lnReturn
      ENDFUNC


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3102833

      Visual FoxPro’s Future

      by craigaaa3 ·

      In reply to The SPS Weblog

      What does the future hold for VFP?

      This is perhaps one of the most asked questions lately. Most of the time when I’m
      asked this question it is in regards to SednaX,
      but today I’d like to talk about the contract work I recently started on Sedna.
      The Microsoft Visual FoxPro Team is allowing me to talk about things that would ordinarily
      be kept behind closed doors. In fact, when I asked them what I was allowed to talk
      about, their response was pretty surprising. Basically they feel that the more that
      we discuss, preview, and show before the eventual release of Sedna, the better (they
      obviously weren’t just blowing smoke when they began touting the concept of transparency
      – I must admit that before this I had my doubts).

      Windows Vista

      The bulk of my work is being done on what some would call a Vista toolkit, but really
      it’s just the Visual FoxPro Team and I working on some really cool and useful stuff
      for Visual FoxPro using new features and APIs that are being unveiled by Microsoft
      as they move towards Windows Vista. As Microsoft is back porting a lot of this new
      stuff, some of these proposed Sedna components would work on Windows XP and maybe
      even Windows 2000 as well. In the coming months you can expect to see lots of things
      both here on my blog and also in the CTPs that will be released for Sedna. Most are
      things that have never been done, or were never possible before, in Visual FoxPro.
      Not excited now? You will be… OH, you will be! 🙂

      Let’s take a look at a few things that I’ve worked on that are being considered for
      possible inclusion in Sedna…

      Windows Presentation Foundation (WPF) – XAML (codename was Avalon)

      Below is a screen shot of XAML controls running inside a Visual FoxPro form.
      When the buttons are clicked they actually fire Visual FoxPro methods. While this
      example is just showing some simple drop-shadowed buttons, pretty much anything that
      WPF is capable of doing with XAML could be done. So if you wanted something more complex,
      like a 3D model that would spin around, you could have it. Think of a database application
      for products where the user could rotate an image of the product a full 360 degrees.

       

      XML Paper Specification (XPS)

      Sometimes referred to as the Office 12 document format, XPS is going to be huge in
      the coming years in my opinion. Given the open nature of the XPS format (basically
      a bunch of XML documents inside a zip file), there will be a lot of 3rd party products
      that will be coming out supporting XPS. So how about the ability to create XPS documents
      from Visual FoxPro reports? Here’s a screen shot of one of the solution sample reports
      in XPS format. It is being shown in the XPS viewer that Microsoft has created
      for IE 7, but Microsoft will also be providing a standalone viewer as well. In XPS
      format, the report’s text is fully searchable and the document can even be digitally
      signed. Also, the rendered quality of an XPS document is super crisp and clear.

       

      Task Dialogs

      Say goodbye to the simple and somewhat tired looking Windows message box and
      hello to Task Dialogs! Task dialogs are message boxes on steroids, and just one of
      the new common controls provided by Microsoft in Windows Vista. What the screen shot
      below doesn’t show is some of the other features that come with task dialogs, such
      as enhanced button types, progressbars, additional icons, callback functions, additional
      control areas… the list goes on and on. In addition to being very useful, task dialogs
      can help give a Visual FoxPro application one of those little touches that makes it
      look and feel more professional.

       

      Speech API (SAPI)

      Sorry, no screen shot for this one, but SAPI has really been improved in Windows Vista.
      Imagine users using Visual FoxPro applications to do dictation (saved directly into
      a memo file as data), or run queries… “Bring up customer, last name Smith”, “Show
      me the February sales report”, “Upload progress report to headquarters”. Sounds a
      bit futuristic perhaps, but given the new Speech engine in Windows Vista, all of this
      and more is possible. I haven’t worked out what all the uses might be for this in
      Visual FoxPro applications, but talking into a microphone and seeing the sentences
      appear in an editbox on a Visual FoxPro form is still pretty neat. And, when thought
      of in conjunction with the growing popularity of internet telephony (VoIP),
      I have to think there is some use for speech recognition in the Visual FoxPro applications
      of the future.

      More to come

      That’s all for this blog entry, but certainly not all that is being worked on. I’ll
      be back with more later. I just thought that some of you would enjoy seeing these,
      and maybe it would generate some excitement and useful discussion here or out on the
      Visual FoxPro forums. As for SednaX
      more is on the way there too. I promise.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3102342

      VFPEncryption FLL Update

      by craigaaa3 ·

      In reply to The SPS Weblog

      A new and useful function
      gets added
      Based
      on a recent request by John Clarke, I’ve added a HashFile() function to the library.
      The reason this is needed is that the Hash() function receives a string and Visual
      FoxPro has a string size limit (16,777,184 characters) that makes producing a
      message digest on files larger than about 16 MB impossible. This new HashFile() function
      lifts that restriction. Note that it is used exactly as the Hash() function is except
      that the first parameter is the file you want to hash.

      A bug gets squashed
      Kenneth Tamayo reported in the comments section of an
      earlier blog post
      that RC4 encryption and decryption was failing in certain circumstances.
      Problem is fixed in this newest library. There are no current bugs in this library
      that I am aware of. If you find one, please contact me as Kenneth did, either by posting
      a comment here or via email.

      Others have requested changes as well
      To others that have requested changes… I haven’t forgotten you. A requested
      change currently being considered is providing for compatibility with Visual Studio’s
      encryption. This will involve, among other things, allowing vectors to be specified
      in the Encrypt, Decrypt, EncryptFile, and DecryptFile functions.

      For now, here’s the download for the newest FLL libraries in two C++ flavors and the
      documentation for the HashFile function that has been added. More complete documentation
      is available in a previous
      blog entry
      .

      Download
      the Latest Version of the VFP Encryption FLL
      (58 KB approx.)
      (compiled with Visual Studio 2005 and requires the C++ 8.0 runtimes)

      Download
      the Latest Version of the VFP Encryption 71 FLL
      (59 KB approx.)
      (compiled with Visual Studio 2003 and requires the C++ 7.1 runtimes)


      Function HASHFILE()

      Signature: HashFILE(cFileName[, nHashType])

      Parameters:

      cFileName – The fullpath and name
      of an existing file you wish to generate a message digest for

      nHashType – The type of hash function to generate. There
      are currently 7 different hash functions supported

      1 = SHA1 (a.k.a SHA160)
      2 = SHA256
      3 = SHA384
      4 = SHA512 *Default
      5 = MD5
      6 = RIPEMD128
      7 = RIPEMD256

      Return Value:

      Binary Character Data – the hash for cFileName.

      Remarks:

      The hash is returned as a series of binary characters. However, it is more
      common to see hashes in a hexBinary format. This can be accomplished in Visual FoxPro
      by taking the return of the HashFile() function and sending it in as a parameter to
      the STRCONV() function. For example:

      ?STRCONV(HashFile(“C:\MyFile.txt”), 15) && hexBinary Hash


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3085019

      Speaking at Chicago FUDG

      by craigaaa3 ·

      In reply to The SPS Weblog

      Chicago FoxPro Users and Developers Group (FUDG)

      Tuesday, March 14th will be my first speaking engagement of the year at the Chicago
      FUDG
      . I encourage you to make plans to attend if you’re anywhere in the area.
      Or, do what I’m doing and, fly in for the day. What’s the topic? EVERYTHING!
      At most Visual FoxPro Conferences a speaker is given around 75 minutes to make their
      presentation on a single topic, but at the Chicago FUDG I have the opportunity to
      present VFP-related content for about 2 hours. So, I’ll be going over everything from
      custom classes and C++ libraries to COM interop to VFP on the latest version of Windows
      Vista to SednaX to VFP world
      domination! The presentation will be a fast paced look at a large range of topics
      that most VFP developers are interested in, and I’ll also be showing/explaining why
      I think the future of VFP, as well as the developers working in it, is very bright.

      What you can expect to get out of this meeting…

      If you want to get an accurate picture of where VFP is and where it’s headed…
      If you want to see some amazing things that are possible in VFP today… If you want
      to know how you can make a difference and create VFP’s future… If you’re in need
      of some positive reinforcement of your decision to stick with VFP for development…
      If you want to see how VFP can leverage all of the new stuff coming out of Redmond…
      If you want to see what a presentation on VFP looks like when the topic is EVERYTHING
      and someone has made the mistake of telling me to just go nuts on it… then
      attend the Chicago FUDG meeting on:

      Tuesday March 14, 2006
      Monadnock Building, 53 W. Jackson, Chicago Loop, 5:30 PM

      I assure you, this will be a not-to-be-missed user group meeting for any and all VFP
      developers that can make it.



      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3085018

      Another Update VFPEncryption FLL

      by craigaaa3 ·

      In reply to The SPS Weblog

      Kenneth Reproduces another RC4 Bug

      Using the previous update to the VFP Encryption FLL, Kenneth Tamayo reproduces another
      bug in the RC4 code of the vfpencryption71.fll (also exists in vfpencryption.fll)
      and posts some repro code in the comments section of my
      previous blog entry
      .

      Another great catch Kenneth! I have made the appropriate fixes in the vfpencryption.fll
      and vfpencryption71.fll code. These bug reports and fixes are very important since
      RC4 is perhaps one of the more useful ciphers in the FLLs when working with table
      data as it provides for ciphertext that is the same length as the plaintext. My thanks
      to Kenneth for his help. Here are the downloads for the newest versions of both FLLs
      and also the repro code for this latest bug and the previous bug that Kenneth reported
      that are now fixed.

      Download
      the Latest Version of the VFP Encryption FLL
      (58 KB approx.)
      (compiled with Visual Studio 2005 and requires the C++ 8.0 runtimes)

      Download
      the Latest Version of the VFP Encryption 71 FLL
      (59 KB approx.)
      (compiled with Visual Studio 2003 and requires the C++ 7.1 runtimes)

      Code to Reproduce Bugs in previous versions of the FLLs using the RC4 stream
      cipher:

      SET LIBRARY TO (LOCFILE(“vfpencryption.fll”))
      && or vfpencryption71.fll

      CREATE cursor myTable (myField C(28))

      *!* Shows new bugs
      that Kenneth reported are fixed
      INSERT INTO myTable (myField) VALUES (“CALLE
      RAFAEL GIMENEZ”
      )

      INSERT INTO myTable (myField) VALUES (“CALLE
      GONZALO BERCEO”
      )

      INSERT INTO myTable (myField) VALUES (“COND
      COOP EL ALCAZAR”
      )

      INSERT INTO myTable (myField) VALUES (“CALLE
      MANUEL F ROSSY”
      )

      INSERT INTO myTable (myField) VALUES (“CALLE
      EFIGENIO COCO FERRER”
      )

      INSERT INTO myTable (myField) VALUES (“CALLE
      MANUEL JIMENEZ”
      )

      INSERT INTO myTable (myField) VALUES (“COND
      EST DEL BLVD”
      )

      INSERT INTO myTable (myField) VALUES (“URB
      PRADO ALTO”
      )

      INSERT INTO myTable (myField) VALUES (“HACIENDA
      LOMAS”
      )
      *!* Shows
      bug from before that Kenneth reported is fixed
      INSERT INTO myTable (myField) VALUES (“QTAS
      DE CANOVANAS”
      )

      BROWSE TITLE “Data
      is Inserted… (No problem)”


      REPLACE ALL
      MyField WITH ENCRYPT(mytable.MyField,“RUSHLIFE”,1024)

      BROWSE TITLE “Data
      is Encrypted… (No problem)”


      REPLACE ALL
      MyField WITH DECRYPT(mytable.MyField,“RUSHLIFE”,1024)

      BROWSE TITLE “Data
      is Decrypted… (Bugs are now fixed)”

      SET LIBRARY TO


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3147998

      OzFox Rocks Podcast #3

      by craigaaa3 ·

      In reply to The SPS Weblog

      Craig Bailey and Scott Scovell do a great job on their
      latest podcast
      . They give Ken Levy (previous product manager of Visual FoxPro)
      some much deserved props, have a little fun with Milind Lele (Ken’s replacement) and
       go on to talk about everything from Patterns and Practices to Team Foundation
      Server. The OzFox Rocks podcast has been first rate from day one, and this episode
      is no exception.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3147999

      Visual FoxPro Visibility

      by craigaaa3 ·

      In reply to The SPS Weblog

      Increased visibility

      Visual FoxPro has gone from utter obscurity two years ago to showing up all over the
      place these days. Visual FoxPro has been a meteor on the TIOBE
      Index
      first showing up in the top 20 some three months ago and now eclipsing the
      likes of VB.NET, Pascal, and COBOL. Mary Jo Foley has taken recent notice and posted repeated
      news articles and blog entries
      about Visual FoxPro and the VFP Community (that
      she endearingly refers to as the FoxPro Faithful). ENT News has taken
      note
       in a few articles. And, RemondMag.com has
      FoxPro popping corks. Presumably these corks are on champaign, but with
      Visual FoxPro’s recent increase in visibility there may be some who weren’t expecting
      (or wanting) this popping corks of another kind.

      Inevitable

      Now some may find this increased exposure all very surprising. I mean, who knew that
      Visual FoxPro existed or that it was even a Microsoft product? But to me, all of this
      was inevitable. Visual FoxPro serves the customer base that Microsoft has neglected
      to provide for in their other offerings, namely Visual Studio. Developer shops
      not doing large team development projects and customers that are looking for super-fast,
      robust, data-centric applications that won’t break the bank. Can Visual Studio create
      applications that handle data? Sure, but it doesn’t hold a candle to what Visual FoxPro
      can do and LINQ isn’t going to shore up the difference. Can Visual Studio be used
      by a small development team on a small to medium-sized project? Sure, but that’s not
      the target Microsoft has shot for with Visual Studio.

      What about .NET?

      .NET is an incredible framework of thousands of classes that can help developers produce
      modern looking, feature rich Windows applications. Well then, I guess Visual FoxPro
      is doomed since it’s not a .NET language, right? Quite the contrary actually.
      As a non-.NET language Visual FoxPro gets to continue creating data-centric applications
      with blinding speed and flexibility, and at the same time it can leverage
      the .NET framework where and when appropriate through the use of .NET assemblies and
      COM Interop. I’ve already shown many examples on this blog of .NET controls and code
      being run from Visual FoxPro. You can even compile and execute C# or VB.NET code from
      Visual FoxPro using .NET’s CodeDom if you want to. What I’m saying is that .NET is
      just a big beautiful framework of classes and it can be leveraged from a whole host
      of languages… Visual FoxPro included. Visual Studio isn’t the only development tool
      out there that can produce .NET assemblies or utilize the .NET framework… that was
      the whole point of .NET – to be language independent.

      Visual FoxPro knows data

      Visual FoxPro is probably one of the most misunderstood languages/development tools on
      the planet. Most people think that Visual FoxPro is just a database that uses flat
      files (DBF) for storage. While Visual FoxPro does provide developers with a time-tested,
      feature-rich, database they can use, Visual FoxPro’s real power is in creating
      database applications that access and modify data regardless of the backend. That
      data can be in a Visual FoxPro database or in SQL Server, MySQL, Postgres, Oracle,
      XML files, Access… whatever. Visual FoxPro knows data and knows how to work with
      it regardless of the source. Feature rich Windows front-ends (screens and reports) for
      any of these data sources can be created better and faster with Visual FoxPro than
      with any other development platform in the world. What? That can’t be true can it?
      Yes, it is true, that’s not an overstatement and I didn’t mispeak. Data-centric Windows
      applications accessing any of the aforementioned backends can be created better
      and faster with Visual FoxPro than with ANY other development platform in the
      world.

      A few other things you might not know about Visual FoxPro…

      1. it’s object-oriented (one of the first OOP languages Microsoft had for that matter)
      2. its built-in feature-rich database is royalty free (no per seat license fees
        anyone?)
      3. is rabidly supported by a large community of developers (many of which have decades
        of experience developing FoxPro applications – how many years of experience do the
        developers on your project have in the tool they’re using?)
      4. not originally a Microsoft product (MS purchased it because it was better than anything
        they had)
      5. it comes with a built in reporting engine (no 3rd party product needed –
        who would have thought that reports would be important to data-centric applications?)
      6. you can purchase it today for about $550 from all kinds of places (like here,
        or here,
        or even here)
      7. it’s got a really cool logo

      What’s next for FoxPro?

      Taking over the world. Either get on board or get out of the way.

      VFP9_Boxshot.jpg

       

      UPDATE: 03-12-2006 Thanks to Alex Feldstein for pointing out Visual C++. Visual C++
      1.0 was released in 1993 while Visual FoxPro 3.0 was released in 1995.
      Subsequently corrected blog entry regarding Visual FoxPro being first Microsoft object-oriented
      language.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3148000

      Southwest Fox Speakers

      by craigaaa3 ·

      In reply to The SPS Weblog

      Yes, I know it’s after 4:00 in the morning and I shouldn’t still be up. But, as I
      was sitting here working, I decided to take a quick break to see what I might have
      missed in my RSS feeds since the last time I checked them and I ran into a
      post by Rick Schummer
      about Southwest Fox.

      It looks as though Bob Kocher is putting together another great Southwest
      Fox
      conference this year. The initial
      list of speakers
      reads like a Who’s Who of Visual FoxPro heavy-weights. Marcia
      Akins, Tamar Granor, Cathy Pountney, Toni Feltman, Rick Schummer, Andy Kramek, Jim
      Booth, Mike Feltman, Doug Hennig, Claudio Lassala, Ken Levy, and Bill Anderson are
      on the initial list. And, there’s also some mysterious guest speaker (yet to
      be announced). I’ll be there as well (doing my best to keep up with all of these heavy
      hitters). Keep in mind that Southwest Fox is a ways off yet, so there will probably
      be more speakers added to this already impressive list – though if the list stayed
      just the way it is, it would still be a great value for the registration fee.

      If you’re a Visual FoxPro developer this conference is a not-to-be-missed event. If
      you’re a software firm that employs Visual FoxPro developers, then seriously consider
      sending them to Southwest Fox (this is the kind of investment that will pay big dividends).
      If you’re involved in your local VFP User Group, get 3 or more of your members
      to attend and Bob will give you a discount to boot.

      For those of you that haven’t had the pleasure of attending Southwest Fox previously
      and would like to know what to expect, you can read about last
      year’s Southwest Fox conference
       out on the Universal Thread. A quick recap…
      last year there were something like 18 speakers putting on lots of power-packed VFP
      sessions, vendors were giving away prizes like there was no tomorrow, good
      food and beverages were in ample supply, and Visual FoxPro Community spirit was everywhere.

      If at all possible, get to Southwest Fox 2006. You’ll be glad you did, and while you’re
      there you can help me celebrate Ken Levy’s birthday.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3148001

      Level Extreme magazines are now FREE!

      by craigaaa3 ·

      In reply to The SPS Weblog

      If you’re not a member of Universal Thread,
      you may want to head on over there and join up right away. Michel Fournier, through
      Level Extreme Inc., has decided to make both the Level Extreme .NET and the Universal
      Thread magazines FREE
      to all members
      of Universal Thread.

      Thank you to Michel Fournier, all previous paid subscribers, and the advertisers for
      making this incredible offer possible. I’ll be contacting one of the Universal Thread
      editors in the very near future to see whether I can contribute an article or two.
      There’s nothing I like better than software developers that are trying to take over
      the world – Level Extreme Rocks!


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3148002

      Doug Hennig Blog and TIOBE

      by craigaaa3 ·

      In reply to The SPS Weblog

      Doug Hennig Blog
      The number of great Visual FoxPro-related blogs continues to increase. The
      most recent addition is Doug Hennig’s Blog.
      You’ll want to keep an eye on this one, I know I will be. Doug is one of the most
      active, giving, and experienced members of the Visual FoxPro Community. Welcome to
      the blogosphere Doug – commence to blowing doors off!

      TIOBE

      The number of Visual FoxPro blogs is one of the contributing factors to the continued
      meteoric rise of Visual FoxPro on the TIOBE Programming Community Index (TPCI). When
      Visual FoxPro first appeared in the top 20, I made a New
      Year’s resolution
      to do my part to move it up another 5 spots. The Visual FoxPro
      Community has beat expectations (as we so often do) and it is now sitting in the 13th
      spot. That’s a move of 7 spots in 4 months and for the first time ever Visual FoxPro
      enjoys an “A–” status. While the TPCI does not give a good indication of overall
      numbers or use of a language, it does speak directly to a language’s
      visibility
      . And like so many things about Visual FoxPro these days, its visibility
      is on the upswing.

      Quote from the April 2006 TPCI – “There is an interesting ‘new’ generation
      of programming languages that entered the TPCI top 20 recently. Most of these languages
      are not really new but they are now for the first time in the spotlight. It concerns
      Visual FoxPro, ColdFusion, VB.NET, Ruby, and D. Visual FoxPro is even heading for
      an ‘A’ status.”

      LINQ – VFP 10?
      Some have been raising the prospect that the next version of Visual Studio
      (Orcas) will bring C# and VB.NET up to Visual FoxPro’s level when it comes to building
      data-centric applications. While LINQ is
      a good move in the right direction for the .NET framework (significant portions of
      it were heavily influenced by Visual FoxPro), don’t for a minute be fooled into thinking
      that LINQ will close the gap. Visual FoxPro is and will be the absolute best development
      tool that Microsoft has for building data-centric applications for a long time to
      come (the current version of Visual FoxPro is supported
      by Microsoft until 2015
      ), and with the growing need of businesses to consolidate
      disparate systems with a wide-range of data formats and backends, this is a big deal
      and a market that Visual FoxPro and the developers that work with it are born to serve.

      Just warming up
      So what’s next? More community members start VFP-related blogs, VFP
      reaches top 10 in the TPCI, Sedna potential
      begins to be realized, Congress enacts a 36 hour day so VFP developers can get all
      their work done, and of course… Visual FoxPro takes over the World. If
      you’re a business with data/informational needs or a developer of data-centric applications,
      you need look no further than Visual
      FoxPro
      . It’s absolutely the best there is.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3148003

      VFP World Domination Tour (cont.)

      by craigaaa3 ·

      In reply to The SPS Weblog

      Tomorrow I head for Detroit. I’ll be speaking at the Detroit
      Area Fox Users Group
       (DEFUG) on May 18th. Special thanks goes out to the
      sponsors of this meeting, Innovative Programming
      Systems
      – Dale Zimmer, and White
      Light Computing
      – Rick Schummer.

      So, what’s the meeting going to be about? Visual FoxPro’s future and the ability of
      the Visual FoxPro Community to make a huge difference in the visibility, usefulness,
      and overall success of Visual FoxPro. What’s being done and can be done now, and real
      possibilities for the future of Microsoft’s premiere data-centric development platform.

      If you’re in the area, swing by the DAFUG meeting and enjoy the show!

      For those wondering why my blog has been strangely silent lately… I’ve been buried.
      I’ll dig myself out eventually and resume posting.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3166492

      SednaX and TIOBE

      by craigaaa3 ·

      In reply to The SPS Weblog

      SednaX on the Move
      SednaX will be moving
      to Microsoft’s CodePlex soon. With over
      725 members and new projects being added every month, SednaX has outgrown the GotDotNet
      CodeGallery. Project managers and members need more tools to facilitate online collaboration
      and project control (among other things). CodePlex looks to be just the place for
      a community initiative of this size that continues to experience rapid growth.

      SednaX to be Renamed
      Much like Microsoft’s Sedna project, SednaX was/is just a codename until
      something more suitable and permanent can be found. With the impending move to CodePlex,
      now is a great opportunity to rename/brand SednaX for the future. A message board
      has been set up out on SednaX where
      members can weigh in with their thoughts and suggestions. The front-runner at the
      moment appears to be “VFPX”.

      TIOBE Programming Community Index June 2006
      Visual FoxPro now sits in position 12 on the TIOBE
      Index
      and enjoys an “A” rating for the first time ever. It also continues to hold
      as the fastest climbing language in the index over the past year. A distinction
      it has enjoyed for several months now.

      Visual FoxPro and the community that supports it are just getting warmed up! Speaking
      of which, did everyone see the cool
      Visual FoxPro screencasts
      that Craig Bailey did?


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3270146

      Visual FoxPro Progress

      by craigaaa3 ·

      In reply to The SPS Weblog

      SednaX

      In addition to the administrative duties that I share with Rick and Doug, I’ve been
      working with Bo Durban on the GDIPlusX library. The GDIPlusX library is a pure Visual
      FoxPro reproduction of the Drawing related namespaces in .NET. We’ve coded well over
      40,000 lines of VFP code and the library consists of 80+ classes now. At nearly 90%
      complete it is safe to say that no other library on the planet gives Visual FoPro
      developers the fuctionality and power that this one does when working with GDI+. Cesar
      Chalom posted a
      recent example
      using the new library to create a gradient background for a form
      (the new code is toward the bottom of the page – compare it with the old way of doing
      things and I’m sure you’ll begin to see one of the benefits of GDIPlusX). To download
      the GDIPlusX library as well as other useful VFP enhancements that are being worked
      on go to SednaX and enter the Downloads
      Section
      . For those of you that want to help, get involved! SednaX is open to everyone
      in the VFP Community.

      The number of active projects and members (nearly 800 now) out on SednaX continues
      to grow. We (Doug, Rick and I) are also receiving new project proposals on a near
      weekly basis. Given that SednaX is still much less than a year old, I’d say we’re
      right on track to take over the world.

      Vista Toolkit for VFP

      I also continue to work with Microsoft on the portion of Sedna that
      will help Visual FoxPro developers utilize some of the new technologies that Microsoft
      is coming out with. There was a substantial amount of R&D prior to actually starting
      on the actual products that will constitute the Vista Toolkit, but I am now working
      on the real deal as they say. It’s been a pleasure to work with the Fox Team, especially
      Milind Lele. He only cracks the whip every so often and has been receptive to input
      and new ideas. That’s not to say he as gone for every world domination scheme I’ve
      come up with, but he appears to have our (VFP Community’s) best interests at heart.

      A couple of pieces that you can look forward to seeing in the future are for Windows
      Desktop Search (WDS) and the RSS Platform (msfeeds). Wrapper classes have been
      created for both.

      Windows Desktop Search

      For Windows
      Desktop Search
       (WDS) I wrote an assembly in C# that allows VFP developers
      to do WDS queries and return a recordset object. This is then turned into a Visual
      FoxPro cursor via XML. Searches with WDS are lightning fast which makes it a perfect
      fit for Visual FoxPro which is lightning fast when it comes to data. Here’s a screen
      shot of a form I created that is using this new Vista Toolkit stuff.

      windowsdesktopsearch.jpg

      RSS Platform

      To handle the new RSS
      Platform
      I created a set of VFP wrapper classes that can be used to consume RSS
      feeds (including ATOM). I almost had to create a C++ DLL in order to handle the event
      interfaces in msfeeds, but thanks to a recent
      blog post
      by Calvin Hsia, I’ve been able to implement all of the wrappers in pure
      VFP. I’ve found that if you ever need to do something truly insane in Visual FoxPro
      that Calvin is the Go-To-Guy.

      MSFeeds comes with IE7 so with that in hand Visual FoxPro developers will be ready
      to harness the power of RSS. Here’s a screen shot of an RSS reader I am creating in
      pure Visual FoxPro that uses the new wrapper classes. Using the new wrapper classes
      this sort of thing is almost too easy.

      rssplatform.jpg

      Less Blogging, More Work

      So, while you may not have seen the usual amount of high activity on this blog lately,
      rest assured that I am working hard to help the Visual FoxPro Community invent the
      future of Visual FoxPro. Progress in many areas has been made and will continue to
      be made. Of that much, I am sure. Next up? Renaming
      SednaX
      and moving it over to CodePlex!


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3111132

      Visual FoxPro Videos

      by craigaaa3 ·

      In reply to The SPS Weblog

      Kevin RagsDale
      Just in case you missed them, Kevin
      Ragsdale
      has created 3 VFP promo videos recently…

      Visual FoxPro
      9.0 Promo

      Promo for VFPx
      at CodePlex.com

      Project D.O.A.

      There’s this music loop he uses in the videos that began to sound like the VFP
      theme song to me by the time I was done watching them. I liked it. I also
      got a good laugh when I saw that he was using Google
      Video
      . I guess Kevin’s decided that if Microsoft won’t market VFP, he’ll get Google
      to do it. 🙂 Great job Kevin, keep it up.

      Craig Bailey
      Speaking of promos, one of the best ways to promote Visual FoxPro is to create
      a screen cast showing how to use it. Craig
      Bailey
      did a wonderful job of this in these two…

      SQL
      Server Access with VFP

      Data
      binding in VFP

      SPS Blog Rehash
      In the interest of providing a blog entry with all the current VFP promos
      and learning videos that I know of, here are the previous promos and learning
      videos that I created…

      Breakfast of Champions

      2001: A Fox Odyssey

      OzFox Lite Trailer

      Learning
      Visual FoxPro 101

      Learning
      Visual FoxPro 102

      Learning
      Visual FoxPro 104

      Know of any others?
      If you know of a VFP related video that isn’t listed here, please let me
      know. I’d love to see them and link to them in my blog. If you don’t know of
      any but think you might want to try your hand at creating one, Andrew
      MacNeil
      of The FoxShow did a good white
      paper on some of the tools
      you can use to create screen casts.


      This weblog is sponsored by SweetPotato
      Software, Inc.

    • #3113577

      Visual FoxPro on Tiobe

      by craigaaa3 ·

      In reply to The SPS Weblog

      TIOBE Index
      Visual FoxPro remains in position 13 on the Tiobe
      Community Programming Index
      , but is still moving up percentage-wise. At its current
      rate of ascent it could be in position 12 in a couple of months. For those in the
      VFP Community that are given to superstitions that would be a welcome advancement.

      There was also a change in the way TIOBE is figured this month… “From this month
      on we also measure the hits of Google Blogs. The languages that benefit from this
      are Java, Visual Basic, Ruby, and VB.NET. On the other hand, Ada, D, dBase, and Fortran
      have a lower rating now because they are not popular in blogs.”

      I think this is a positive change. Likely to increase the accuracy and relevance
      of the TIOBE Index.

      Tech Ed 2006 Press Room
      I missed the fact the Mary
      Jo Foley had been talking about
      the response she got for her piece on Visual FoxPro
      in the Tech Ed press room. Thanks to Craig Bailey for pointing it out. To Tony Davis
      I’d say, later is not always greater. To Mary
      Jo
      I’d say, keep those great VFP-related pieces coming!

      FoxPro might not be considered a buzzword in the circles you run in, but Visual FoxPro
      9.0 is still the ultimate RAD database development tool. No other product available
      comes even close.


      This weblog is sponsored by SweetPotato
      Software, Inc.

Viewing 92 reply threads