CWindow RC 16

Started by José Roca, August 05, 2016, 06:53:03 PM

Previous topic - Next topic

José Roca

#15
There are plenty of methods that provide all kind of information.

In the following example, we are using NumResultCols and ColName to retrieve the names of the columns of the result set.


#include once "Afx/COdbc/COdbc.inc"
USING Afx

' // Connect with the database
DIM wszConStr AS WSTRING * 260 = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=biblio.mdb"
DIM pDbc AS CODBC = wszConStr

' // Allocate an statement object
DIM pStmt AS COdbcStmt PTR = NEW COdbcStmt(@pDbc)
IF pStmt = NULL THEN END

' // Generate a result set
pStmt->ExecDirect ("SELECT * FROM Authors ORDER BY Author")

' // Retrieve the number of columns
DIM numCols AS SQLSMALLINT = pStmt->NumResultCols
PRINT "Number of columns:" & STR(numCols)

' // Retrieve the names of the fields (columns)
FOR idx AS LONG = 1 TO numCols
   PRINT "Field #" & STR(idx) & " name: " & pStmt->ColName(idx)
NEXT

' // Delete the statement
Delete pStmt

PRINT
PRINT "Press any key..."
SLEEP


José Roca

#16
In the above example, I have used the dotted syntax for the connection object. We can do it if the connection will be alive until the application ends, but if the connection is temporary we must use NEW and the pointer syntax, to be able to delette the connection object with Delete when no longer needed.

Paul Squires

Wow, that is an amazing amount of work! Thanks Jose, I am always impressed at the amount of code that you can create in such a short period of time. I, also don't use ODBC very much. I think the last time was with FoxPro database files and that was like 10 years ago. I use SQLite for local database and most recently MySQL for anything online/internet based related.

The number of tools for FB is growing!
Paul Squires
PlanetSquires Software

José Roca

I have finished the documentation of the GDI+ classes. About 600 methods!

José Roca

#19
CTextStream Class.

Allows to read and write text files. Works with ascii and unicode. Works with Windows CRLF files and with Linux LF files. You must use CBSTR strings, not CWSTR.


' ########################################################################################
' Microsoft Windows
' File: CTextStream.inc
' Contents: Wrapper class for reading and writing text files.
' Compiler: FreeBasic 32 & 64-bit
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#pragma once
#include once "windows.bi"
#include once "Afx/AfxScrRun.bi"
#include once "Afx/CWStr.inc"

NAMESPACE Afx

' ########################################################################################
' CTextStream - Class for reading and writing text files.
' ########################################################################################
TYPE CTextStream

   Public:
      DIM m_Result AS HRESULT
      DIM m_pFileSys AS Afx_IFileSystem PTR
      DIM m_pTxtStm AS Afx_ITextStream PTR

   Public:
      DECLARE CONSTRUCTOR
      DECLARE DESTRUCTOR
      DECLARE FUNCTION GetLastResult () AS HRESULT
      DECLARE FUNCTION SetResult (BYVAL Result AS HRESULT) AS HRESULT
      DECLARE FUNCTION Create (BYREF cbsFileName AS CBSTR, BYVAL bOverwrite AS BOOLEAN = TRUE, BYVAL bUnicode AS BOOLEAN = FALSE) AS HRESULT
      DECLARE FUNCTION Open (BYREF cbsFileName AS CBSTR, BYVAL IOMode AS LONG = 1, BYVAL bCreate AS BOOLEAN = FALSE, BYVAL bUnicode AS BOOLEAN = FALSE) AS HRESULT
      DECLARE FUNCTION OpenUnicode (BYREF cbsFileName AS CBSTR, BYVAL IOMode AS LONG = 1, BYVAL bCreate AS BOOLEAN = FALSE) AS HRESULT
      DECLARE FUNCTION Close () AS HRESULT
      DECLARE PROPERTY Line () AS LONG
      DECLARE PROPERTY Column () AS LONG
      DECLARE FUNCTION EOS () AS BOOLEAN
      DECLARE FUNCTION EOL () AS BOOLEAN
      DECLARE FUNCTION Read (BYVAL numChars AS LONG) AS CBSTR
      DECLARE FUNCTION ReadLine () AS CBSTR
      DECLARE FUNCTION ReadAll () AS CBSTR
      DECLARE FUNCTION Write (BYREF cbsText AS CBSTR) AS HRESULT
      DECLARE FUNCTION WriteLine (BYREF cbsText AS CBSTR) AS HRESULT
      DECLARE FUNCTION WriteBlankLines (BYVAL numLines AS LONG) AS HRESULT
      DECLARE FUNCTION Skip (BYVAL numChars AS LONG) AS HRESULT
      DECLARE FUNCTION SkipLine () AS HRESULT

END TYPE
' ########################################################################################

' ========================================================================================
' Constructor
' ========================================================================================
CONSTRUCTOR CTextStream
   ' // Create an instance of the Filesystem object
   DIM CLSID_FileSystemObject_ AS GUID = (&h0D43FE01, &hF093, &h11CF, {&h89, &h40, &h00, &hA0, &hC9, &h05, &h42, &h28})
   DIM IID_IFileSystem AS GUID = (&h0AB5A3D0, &hE5B6, &h11D0, {&hAB, &hF5, &h00, &hA0, &hC9, &h0F, &hFF, &hC0})
   SetResult(CoCreateInstance(@CLSID_FileSystemObject_, NULL, CLSCTX_INPROC_SERVER, @IID_IFileSystem, @m_pFileSys))
END CONSTRUCTOR
' ========================================================================================

' ========================================================================================
' Constructor
' ========================================================================================
DESTRUCTOR CTextStream
   IF m_pTxtStm THEN
      m_pTxtStm->Close
      m_pTxtStm->Release
   END IF
   IF m_pFileSys THEN m_pFileSys->Release
END DESTRUCTOR
' ========================================================================================

' ========================================================================================
' Returns the last status code.
' ========================================================================================
PRIVATE FUNCTION CTextStream.GetLastResult () AS HRESULT
   RETURN m_Result
END FUNCTION
' ========================================================================================

' ========================================================================================
' Sets the last status code.
' ========================================================================================
PRIVATE FUNCTION CTextStream.SetResult (BYVAL Result AS HRESULT) AS HRESULT
   m_Result = Result
   RETURN m_Result
END FUNCTION
' ========================================================================================

' ========================================================================================
' Creates a specified file name and returns a TextStream object that can be used to read
' from or write to the file.
' Parameters:
' - bstrFileName: String expression that identifies the file to create.
' - bOverwrite: Boolean value that indicates whether you can overwrite an existing file.
'   The value is true if the file can be overwritten, false if it can't be overwritten.
'   If omitted, existing files are not overwritten.
' - bUnicode: Boolean value that indicates whether the file is created as a Unicode or
'   ASCII file. The value is true if the file is created as a Unicode file, false if it's
'   created as an ASCII file. If omitted, an ASCII file is assumed.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Create (BYREF cbsFileName AS CBSTR, BYVAL bOverwrite AS BOOLEAN = TRUE, BYVAL bUnicode AS BOOLEAN = FALSE) AS HRESULT
   IF m_pTxtStm THEN
      SetResult(m_pTxtStm->Close)
      m_pTxtStm->Release
      m_pTxtStm = NULL
   END IF
   RETURN SetResult(m_pFileSys->CreateTextFile(**cbsFileName, bOverwrite, bUnicode, @m_pTxtStm))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Opens a specified file and returns a TextStream object that can be used to read from,
' write to, or append to the file.
' Parameters:
' - bstrFileName: String expression that identifies the file to open.
' - IOMode: Can be one of three constants: IOMODE_ForReading, IOMODE_ForWriting, or IOMODE_ForAppending.
' - bCreate: Value that indicates whether a new file can be created if the specified
'   filename doesn't exist. The value is True if a new file is created, False if it isn't
'   created. If omitted, a new file isn't created.
' - bUnicode: TRUE or FALSE. Indicates the format of the opened file. If omitted, the file
'   is opened as ASCII.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Open (BYREF cbsFileName AS CBSTR, BYVAL IOMode AS LONG = 1, BYVAL bCreate AS BOOLEAN = FALSE, BYVAL bUnicode AS BOOLEAN = FALSE) AS HRESULT
   IF m_pTxtStm THEN
      SetResult(m_pTxtStm->Close)
      m_pTxtStm->Release
      m_pTxtStm = NULL
   END IF
   RETURN SetResult(m_pFileSys->OpenTextFile(**cbsFileName, IOMode, bCreate, bUnicode, @m_pTxtStm))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Opens a specified file and returns a TextStream object that can be used to read from,
' write to, or append to the file.
' Parameters:
' - bstrFileName: String expression that identifies the file to open.
' - IOMode: Can be one of three constants: IOMODE_ForReading, IOMODE_ForWriting, or IOMODE_ForAppending.
' - bCreate: Value that indicates whether a new file can be created if the specified
'   filename doesn't exist. The value is True if a new file is created, False if it isn't
'   created. If omitted, a new file isn't created.
' ========================================================================================
PRIVATE FUNCTION CTextStream.OpenUnicode (BYREF cbsFileName AS CBSTR, BYVAL IOMode AS LONG = 1, BYVAL bCreate AS BOOLEAN = FALSE) AS HRESULT
   IF m_pTxtStm THEN
      SetResult(m_pTxtStm->Close)
      m_pTxtStm->Release
      m_pTxtStm = NULL
   END IF
   RETURN SetResult(m_pFileSys->OpenTextFile(**cbsFileName, IOMode, bCreate, Tristate_True, @m_pTxtStm))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Closes an open TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Close () AS HRESULT
   IF m_pTxtStm THEN
      RETURN(SetResult(m_pTxtStm->Close))
      m_pTxtStm = NULL
   END IF
END FUNCTION
' ========================================================================================

' ========================================================================================
' Read-only property that returns the current line number in a TextStream file.
' After a file is initially opened and before anything is written, Line is equal to 1.
' ========================================================================================
PRIVATE PROPERTY CTextStream.Line () AS LONG
   DIM nLine AS LONG
   IF m_pTxtStm THEN SetResult(m_pTxtStm->get_Line(@nLine))
   PROPERTY = nLine
END PROPERTY
' ========================================================================================

' ========================================================================================
' Read-only property that returns the column number of the current character position in a
' TextStream file. After a newline character has been written, but before any other character
' is written, Column is equal to 1.
' ========================================================================================
PRIVATE PROPERTY CTextStream.Column () AS LONG
   DIM nColumn AS LONG
   IF m_pTxtStm THEN SetResult(m_pTxtStm->get_Column(@nColumn))
   PROPERTY = nColumn
END PROPERTY
' ========================================================================================

' ========================================================================================
' Returns TRUE if the file pointer is at the end of a TextStream file; FALSE if it is not. Read-only.
' ========================================================================================
PRIVATE FUNCTION CTextStream.EOS () AS BOOLEAN
   DIM nEOS AS VARIANT_BOOL
   IF m_pTxtStm THEN SetResult(m_pTxtStm->get_AtEndOfStream(@nEOS))
   RETURN nEOS
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns TRUE if the file pointer is positioned immediately before the end-of-line marker
' in a TextStream file; FALSE if it is not. Read-only.
' ========================================================================================
PRIVATE FUNCTION CTextStream.EOL () AS BOOLEAN
   DIM nEOL AS VARIANT_BOOL
   IF m_pTxtStm THEN SetResult(m_pTxtStm->get_AtEndOfLine(@nEOL))
   RETURN nEOL
END FUNCTION
' ========================================================================================

' ========================================================================================
' Reads a specified number of characters from a TextStream file and returns the resulting string.
' After a file is initially opened and before anything is written, Line is equal to 1.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Read (BYVAL numChars AS LONG) AS CBSTR
   DIM cbsText AS CBSTR
   IF m_pTxtStm THEN SetResult(m_pTxtStm->Read(numChars, @cbsText))
   RETURN cbsText
END FUNCTION
' ========================================================================================

' ========================================================================================
' Reads an entire line (up to, but not including, the newline character) from a TextStream
' file and returns the resulting string.
' ========================================================================================
PRIVATE FUNCTION CTextStream.ReadLine () AS CBSTR
   DIM cbsText AS CBSTR
   IF m_pTxtStm THEN SetResult(m_pTxtStm->ReadLine(@cbsText))
   RETURN cbsText
END FUNCTION
' ========================================================================================

' ========================================================================================
' Reads an entire TextStream file and returns the resulting string.
' ========================================================================================
PRIVATE FUNCTION CTextStream.ReadAll () AS CBSTR
   DIM cbsText AS CBSTR
   IF m_pTxtStm THEN SetResult(m_pTxtStm->ReadAll(@cbsText))
   RETURN cbsText
END FUNCTION
' ========================================================================================

' ========================================================================================
' Writes a specified string to a TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Write (BYREF cbsText AS CBSTR) AS HRESULT
   IF m_pTxtStm THEN RETURN(SetResult(m_pTxtStm->Write(*cbsText)))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Writes a specified string and newline character to a TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.WriteLine (BYREF cbsText AS CBSTR) AS HRESULT
   IF m_pTxtStm THEN RETURN(SetResult(m_pTxtStm->WriteLine(*cbsText)))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Writes a specified number of newline characters to a TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.WriteBlankLines (BYVAL numLines AS LONG) AS HRESULT
   IF m_pTxtStm THEN RETURN(SetResult(m_pTxtStm->WriteBlankLines(numLines)))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Skips a specified number of characters when reading a TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.Skip (BYVAL numChars AS LONG) AS HRESULT
   IF m_pTxtStm THEN RETURN(SetResult(m_pTxtStm->Skip(numChars)))
END FUNCTION
' ========================================================================================

' ========================================================================================
' Skips the next line when reading a TextStream file.
' ========================================================================================
PRIVATE FUNCTION CTextStream.SkipLine () AS HRESULT
   IF m_pTxtStm THEN RETURN(SetResult(m_pTxtStm->SkipLine))
END FUNCTION
' ========================================================================================

END NAMESPACE

José Roca

Usage examples:


#include "windows.bi"
#include "Afx/AfxScrRun.bi"
#include "Afx/CTextStream.inc"
using Afx

' // Initialize the COM library
CoInitialize NULL

' // Create an instance of the CTextStream class
DIM pTxtStm AS CTextStream PTR = NEW CTextStream
IF pTxtStm = NULL THEN END

' // Create a text stream
DIM wszFile AS WSTRING * MAX_PATH = ExePath & "\Test.txt"
pTxtStm->Create(wszFile, TRUE)

' // Write a string and an end of line to the stream
pTxtStm->WriteLine "This is a test."

' // Write more strings
pTxtStm->Write "This is a string."
pTxtStm->Write "This is a second string."

' // Write two blank lines (the first will serve as an end of line for the previous write instructions)
pTxtStm->WriteBlankLines 2
pTxtStm->WriteLine "This is the end line."

' // Close the file (not needed if we are going to delete the class)
pTxtStm->Close

' // Delete the class
Delete pTxtStm

' // Uninitialize the COM library
CoUninitialize

PRINT
PRINT "Press any key..."
SLEEP



#include "windows.bi"
#include "Afx/AfxScrRun.bi"
#include "Afx/CTextStream.inc"
using Afx

' // Initialize the COM library
CoInitialize NULL

' // Create an instance of the CTextStream class
DIM pTxtStm AS CTextStream PTR = NEW CTextStream
IF pTxtStm = NULL THEN END

' // Create a text stream
DIM wszFile AS WSTRING * MAX_PATH = ExePath & "\Test.txt"
pTxtStm->Create(wszFile, TRUE)

' // Write a string and an end of line to the stream
pTxtStm->WriteLine "This is a test."

' // Write more strings
pTxtStm->WriteLine "This is a string."
pTxtStm->WriteLine "This is a second string."
pTxtStm->WriteLine "This is the end line."

' // Close the file (not needed if we are going to delete the class)
pTxtStm->Close

' // Delete the class
Delete pTxtStm

' // Uninitialize the COM library
CoUninitialize

PRINT
PRINT "Press any key..."
SLEEP



#include "windows.bi"
#include "Afx/AfxScrRun.bi"
#include "Afx/CTextStream.inc"
using Afx

' // Initialize the COM library
CoInitialize NULL

' // Create an instance of the CTextStream class
DIM pTxtStm AS CTextStream PTR = NEW CTextStream
IF pTxtStm = NULL THEN END

' // Create a unicode text stream
DIM wszFile AS WSTRING * MAX_PATH = ExePath & "\Test.txt"
pTxtStm->Create(wszFile, TRUE, TRUE)

' // Write a string and an end of line to the stream
pTxtStm->WriteLine "This is a test."

' // Write more strings
pTxtStm->WriteLine "This is a string."
pTxtStm->WriteLine "This is a second string."
pTxtStm->WriteLine "This is the end line."

' // Close the file (not needed if we are going to delete the class)
pTxtStm->Close

' // Delete the class
Delete pTxtStm

' // Uninitialize the COM library
CoUninitialize

PRINT
PRINT "Press any key..."
SLEEP



#include "windows.bi"
#include "Afx/AfxScrRun.bi"
#include "Afx/CTextStream.inc"
using Afx

' // Initialize the COM library
CoInitialize NULL

' // Create an instance of the CTextStream class
DIM pTxtStm AS CTextStream PTR = NEW CTextStream
IF pTxtStm = NULL THEN END

' // Open file as a text stream
DIM wszFile AS WSTRING * MAX_PATH = ExePath & "\Test.txt"
pTxtStm->OpenUnicode(wszFile, IOMode_ForReading)

' // Read the file sequentially
DO
   ' // Ext if we are at the end of the stream
   IF pTxtStm->EOS THEN EXIT DO
   ' // Current line
   DIM curLine AS LONG = pTxtStm->Line
   ' // Skip the 3rd line
   IF curLine = 3 THEN
      pTxtStm->SkipLine
      curLine + = 1
   END IF
   ' // Skip 10 characters
   pTxtStm->Skip 10
   ' // Current column
   DIM curColumn AS LONG = pTxtStm->Column
   ' // Read 5 characters
   DIM cbsText AS CBSTR = pTxtStm->Read(5)
   ' // Skip the rest of the line
   pTxtStm->SkipLine
   PRINT "Line " & STR(curLine) & ", Column " &  STR(curColumn) & ": " & cbsText
LOOP

' // Close the file (not needed if we are going to delete the class)
pTxtStm->Close

' // Delete the class
Delete pTxtStm

' // Uninitialize the COM library
CoUninitialize

PRINT
PRINT "Press any key..."
SLEEP



#include "windows.bi"
#include "Afx/AfxScrRun.bi"
#include "Afx/CTextStream.inc"
using Afx

' // Initialize the COM library
CoInitialize NULL

' // Create an instance of the CTextStream class
DIM pTxtStm AS CTextStream PTR = NEW CTextStream
IF pTxtStm = NULL THEN END

' // Open file as a text stream
DIM wszFile AS WSTRING * MAX_PATH = ExePath & "\Test.txt"
pTxtStm->Open(wszFile, IOMode_ForReading)

' // Read all the contents of the file
DIM cbsText AS CBSTR = pTxtStm->ReadAll
PRINT cbsText

' // Close the file (not needed if we are going to delete the class)
pTxtStm->Close

' // Delete the class
Delete pTxtStm

' // Uninitialize the COM library
CoUninitialize

PRINT
PRINT "Press any key..."
SLEEP


José Roca

AfxScrRun.bi needs this include file or it will fail in some cases.

#include once "win/ole2.bi"

The attachment contains an updated header.

José Roca

#22
As a proof of concept, I'm working in a wrapper class for IWinHTTP. This interface makes heavy use of optional byval variants, so its use with FB doing straight vtable calls is cumbersome. Therefore, I'm wrapping the methods to avoid the use of variants by hidding the VARIANTs and SAFEARRAYs stuff inside them.

For example:


' ========================================================================================
' Retrieves the response entity body as an array of unsigned bytes. This array contains
' the raw data as received directly from the server.
' Result code (GetLastResult):
' The result code is S_OK on success or an error value otherwise.
' Remarks: This function returns the response data in an array of unsigned bytes. If the
' response does not have a response body, an empty variant is returned. This property can
' only be invoked after the Send method has been called.
' ========================================================================================
PRIVATE FUNCTION CWinHttp.GetResponseBody () AS STRING
   DIM vBody AS VARIANT, buffer AS STRING
   IF m_pWinHttp THEN SetResult(m_pWinHttp->get_ResponseBody(@vBody))
   IF m_Result = S_OK THEN
      DIM pvData AS ANY PTR
      IF vBody.pArray THEN
         DIM lLBound AS LONG, lUBound AS LONG
         SetResult(SafeArrayGetLBound(vBody.pArray, 1, @lLBound))
         SetResult(SafeArrayGetUBound(vBody.pArray, 1, @lUBound))
         DIM cElements AS LONG = lUBound - lLBound + 1
         SafeArrayAccessData(vBody.pArray, @pvData)
         IF pvData THEN
            buffer = SPACE(cElements)
            memcpy STRPTR(buffer), pvData, cElements
         END IF
         SafeArrayUnaccessData(vBody.pArray)
      END IF
   END IF
   VariantClear(@vBody)
   RETURN buffer
END FUNCTION
' ========================================================================================


In the past, I did something similar with PowerBASIC before it added COM support.

Neither the WinHTTP API functions nor the WinHTTP interface are supported in the FB declares.