Btrieve API Programming
The following topics provide information to help you begin developing a Zen application by making direct calls to the Btrieve API. The most common programming tasks are included with sample code and sample structures for Visual Basic and Delphi.
Fundamentals of Btrieve API Programming
The following flow charts demonstrate which Btrieve operations to use to insert, update, and delete records. For more detailed information about APIs, see Btrieve API Guide.
Btrieve API Flow Chart
Inserting Records
1. OPEN (0)
2. INSERT (2) to add record (repeat)
3. CLOSE (1) file
4. STOP (25) to release resources
Updating Records
1. OPEN (0)
2. GET EQUAL (5) or some other single-record retrieval operation to find existing record and establish physical currency
3. Modify record
4. UPDATE (3)
5. CLOSE (1)
6. STOP (25) to release resources
Deleting Records
1. OPEN(0)
2. GET EQUAL(5) or some other single-record retrieval operation to find existing record and establish physical currency
3. DELETE(4)
4. CLOSE(1)
5. STOP (25) to release resources
Visual Basic Notes
When you develop Zen applications with Visual Basic, be aware of the following things.
Visual Basic has a known byte alignment issue with user-defined data types. You can also see the Visual Basic topic regarding the Btrieve API for information about this issue and using the PAln32.DLL, the Btrieve Alignment DLL.
Creating a record class for each type of resulting record facilitates data access as shown in the following steps:
1. Create a class named Record.
2. Create a structure defining the layout of your record:
Type Byte2
  field1 byte
  field2 byte
End Type
Type Rec
  Size As Byte2
  Name As String*30    'SQL Mask = x30
  Salary As String*10  'SQL Mask = zzzzzzz.99
End Type
3. Use iAsciiFlag = 1 and ispacing=0 to read data into an instance of Rec:
Dim instofRec As New Rec
4. Use dot notation to access data:
instofRec.Name="Jeff"
5. Use the record class to handle all the instofRec data manipulation.
Delphi Notes
The following are things to consider when you use Delphi to develop your Zen application.
Unlike older versions of Pascal, the Delphi string type (without a length specifier) is dynamic and null terminated. This means that you are not guaranteed to have memory allocated to the string buffer until you assign it a value. This means when using the type string, you need to pad it large enough to hold the expected results. Using the StringOfChar() function, you can assign a blank string large enough to accommodate the expected return value from Btrieve, as illustrated in the following example:
CustKeyBuffer: string; //long string
CustBufLen : word;
   //MAX_KEY_LEN is 255 since BTRV() always passes 255 for the Key Length :
CustKeyBuffer := StringOfChar(' ', MAX_KEY_LEN);
CustBufLen := SizeOf(CustRec);
Status := BTRV(B_GET_FIRST, CustPosBLock, CustRec, CustBufLen, CustKeyBuffer, 0);
      {CustKeyBuffer now has the value of the key for}
      {the record retrieved}
Not all of the Delphi samples included in this documentation illustrate error reporting. However, you should check return codes after every call.
If you try the samples in this chapter, for the Fetches that use the INTERNAL_FORMAT style, the order of the fields in the query must match the order of members you fetch from the data record. When you use the FillGridHeaders() routine, you must stuff the grid in the same order as the query lists the fields.
Starting a Zen Application
When you are developing a Zen application, you must include the appropriate source module for the specific programming interface.
BTRCONST and BTRAPI32 – source modules needed for Btrieve applications
Adding Zen Source Modules
You need to include either the Btrieve source module into the programming interface in which you are developing your applications.
To add a Btrieve source module in a Visual Basic project
1. Start a new project in Visual Basic.
2. Add an existing standard module to your project, if appropriate.
3. Add the Zen source modules.
To add a Btrieve source module in a Delphi project
1. Start a new project in Delphi.
2. Select Options from the Project menu.
3. Click the Directories tab.
4. Insert the location <path>\INTF\DELPHI in the Search Path data field (path refers to where you installed the Zen SDK components).
5. Include source modules in your USES clause.
Btrieve API Code Samples
This section shows Visual Basic, Delphi, and C/C++ code samples for the following tasks you can perform using the Btrieve API:
Creating a File
The Create (14) operation lets you generate a file from within your application. To create a file, you need to create a structure that contains the necessary information required to build a new Btrieve file.
For specific information about this API, see Btrieve API Guide.
Sample Code
The following sample code illustrates how to create a file using the Create operation.
Visual Basic (Creating a File)
This subroutine creates a file called Orders.
Sub CreateOrdersFile(OrdFileLocation As String)
 
        'The following syntax sets up file specifications.
  OrdFixedRecSize = Len(OrdRecBuf)
  FileDefinitionBuffer.RecLen = OrdFixedRecSize
  FileDefinitionBuffer.PageSize = 4096
  FileDefinitionBuffer.IndxCnt = 2
  FileDefinitionBuffer.FileFlags = VARIABLELENGTH
 
       'Key 0, by order number.
  FileDefinitionBuffer.KeyBuf0.KeyPos = 1
  FileDefinitionBuffer.KeyBuf0.KeyLen = 4
  FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE
  FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC)
 
       'Key 1, by contact number.
  FileDefinitionBuffer.KeyBuf1.KeyPos = 5
  FileDefinitionBuffer.KeyBuf1.KeyLen = 4
  FileDefinitionBuffer.KeyBuf1.KeyFlags = EXTTYPE + MODIFIABLE + DUP
  FileDefinitionBuffer.KeyBuf1.KeyType = Chr$(BUNSGBIN)
 
  BufLen = Len(FileDefinitionBuffer)
  OrdFileLocation = OrdFileLocation & " "
  KeyBufLen = Len(OrdFileLocation)
  CopyMemory OrdKeyBuffer, OrdFileLocation, Len(OrdFileLocation)
  giStatus = BTRCALL(BCREATE, OrdPosBlock, FileDefinitionBuffer, BufLen, _
                     ByValOrdFileLocation, KeyBufLen, 0)
End Sub
Delphi (Creating a File)
The following routine creates a variable-length file called Customer.
function CreateCustomerFile(FileName: String): SmallInt;
var
  CustRec : CustomerRecordType;            //User defined record structure
  CustBufLen : word;
  CustPosBlock : TPositionBlock;           //array[1..128] of byte
  CustFileLocation : String[255];
  CustFixedRecSize : LongInt;
  FileDefinitionBuffer : FileCreateBuffer; //Structure type for creating a file
  FilebufLen : Word;
  KeyNum : ShortInt;
 
begin
    {The following syntax defines file specifications.}
   {calculate the size of just the fixed portion of the record.}
  CustFixedRecSize                        := SizeOf(CustRec) - SizeOf(CustRec.Notes);
  FileDefinitionBuffer.fileSpec.recLen    := CustFixedRecSize;
  FileDefinitionBuffer.fileSpec.PageSize  := 4096;
  FileDefinitionBuffer.fileSpec.IndexCount:= 4;
  FileDefinitionBuffer.fileSpec.FileFlags := VARIABLELENGTH;
 
    {Define key specifications, Key 0 by contact number}
  FileDefinitionBuffer.keyspecArray[0].Position := 1;
  FileDefinitionBuffer.keyspecArray[0].Length   := 4;{4 byte integer}
  FileDefinitionBuffer.keyspecArray[0].Flags    := KFLG_EXTTYPE_KEY +  KFLG_MODX;
  FileDefinitionBuffer.keyspecArray[0].KeyType  := AUTOINCREMENT_TYPE;
 
    {Key 1, by contact name.}
  FileDefinitionBuffer.keyspecArray[1].Position := 5;
  FileDefinitionBuffer.keyspecArray[1].Length   := 30;
  FileDefinitionBuffer.keyspecArray[1].Flags    := KFLG_EXTTYPE_KEY +KFLG_MODX +
                                                   KFLG_DUP;
  FileDefinitionBuffer.keyspecArray[1].KeyType  := STRING_TYPE;
 
    {Key 2, by company name.}
  FileDefinitionBuffer.keyspecArray[2].Position := 35;
  FileDefinitionBuffer.keyspecArray[2].Length   := 60;
  FileDefinitionBuffer.keyspecArray[2].Flags    := KFLG_EXTTYPE_KEY + KFLG_MODX +
                                                   KFLG_DUP;
  FileDefinitionBuffer.keyspecArray[2].KeyType  := STRING_TYPE;
 
    {Key 3 by sales representative, by next contact date.}
  FileDefinitionBuffer.keyspecArray[3].Position := 220;
  FileDefinitionBuffer.keyspecArray[3].Length   := 4;
  FileDefinitionBuffer.keyspecArray[3].Flags    := KFLG_EXTTYPE_KEY + KFLG_MODX +
                                                   KFLG_DUP + KFLG_SEG;
  FileDefinitionBuffer.keyspecArray[3].KeyType  := LSTRING_TYPE;
  FileDefinitionBuffer.keyspecArray[4].Position := 223;
  FileDefinitionBuffer.keyspecArray[4].Length   := 4;
  FileDefinitionBuffer.keyspecArray[4].Flags    := KFLG_EXTTYPE_KEY + KFLG_MODX +
                                                   KFLG_DUP;
  FileDefinitionBuffer.keyspecArray[4].KeyType  := DATE_TYPE;
 
  CustFileLocation   := FileName + #0;   {path and file name of file to create}
  FilebufLen         := sizeof(FileDefinitionBuffer);
  KeyNum             := 0;
  FillChar(CustPosBlock, SizeOf(CustPosBlock), #0);
 
  Result := BTRV(B_CREATE,             //OpCode 14
                 CustPosBLock,         //Position Block (the "cursor" or "handle")
                 FileDefinitionBuffer, //Definition of new file
                 FileBufLen,           //Length of the definition
                 CustFileLocation[1],  //Path and file name
                 keyNum);              //0 (zero) means Overwrite any existing file
end;   {CreateCustomerFile}
C/C++ (Creating a File)
BTI_SINT CreateCustomerFile(LPCTSTR szCustomerFileName)
{
Customer_Record_Type CustRec; //User defined record structure
char CustPosBlock[POS_BLOCK_SIZE]; //"Cursor" into customer file
char CustFileLocation[255];
size_t CustFixedRecSize;
FileDescriptionType FileDefBuf; //Structure type for creating a file
BTI_WORD FilebufLen;
char KeyNum; //1 byte signed int
BTI_SINT iStatus;
 
/* calculate the size of just the fixed portion of the record: */
CustFixedRecSize       = sizeof(CustRec) - sizeof(CustRec.Notes);
FileDefBuf.RecLen      = CustFixedRecSize;
FileDefBuf.PageSize    = 4096;
FileDefBuf.IndxCnt     = 4;
FileDefBuf.DupPointers = 4;
FileDefBuf.FileFlags   = VAR_RECS | BALANCED_KEYS;
/* DEFINE KEY SPECIFICATIONS KEY 0 - BY CONTACT NUMBER */
FileDefBuf.KeyBuf[0].KeyPos   = 1;
FileDefBuf.KeyBuf[0].KeyLen   = 4;
FileDefBuf.KeyBuf[0].KeyFlags = EXTTYPE_KEY | MOD;
FileDefBuf.KeyBuf[0].KeyType = AUTOINCREMENT_TYPE;
/* KEY 1 - BY CONTACT NAME */
FileDefBuf.KeyBuf[1].KeyPos   = 5;
FileDefBuf.KeyBuf[1].KeyLen   = 30;
FileDefBuf.KeyBuf[1].KeyFlags = EXTTYPE_KEY | DUP | MOD ;
FileDefBuf.KeyBuf[1].KeyType = STRING_TYPE;
/* KEY 2 - BY COMPANY NAME */
FileDefBuf.KeyBuf[2].KeyPos = 35;
FileDefBuf.KeyBuf[2].KeyLen = 60;
FileDefBuf.KeyBuf[2].KeyFlags = EXTTYPE_KEY | DUP | MOD;
FileDefBuf.KeyBuf[2].KeyType = STRING_TYPE;
/* KEY 3 - BY SALES REP BY NEXT CONTACT DATE */
FileDefBuf.KeyBuf[3].KeyPos = 220;
FileDefBuf.KeyBuf[3].KeyLen = 3;
FileDefBuf.KeyBuf[3].KeyFlags = EXTTYPE_KEY | DUP | MOD | SEG;
FileDefBuf.KeyBuf[3].KeyType = STRING_TYPE;
FileDefBuf.KeyBuf[4].KeyPos = 223;
FileDefBuf.KeyBuf[4].KeyLen = 4;
FileDefBuf.KeyBuf[4].KeyFlags = EXTTYPE_KEY | DUP | MOD;
FileDefBuf.KeyBuf[4].KeyType = DATE_TYPE;
//
//------------------------------------------------------------------------
FilebufLen = sizeof(FileDefBuf);
KeyNum = 0; // Overwrite trans
strcpy(CustFileLocation, szCustomerFileName);
iStatus = BTRV(B_CREATE,
CustPosBlock,
&FileDefBuf,
&FilebufLen,
CustFileLocation,
KeyNum);
return(iStatus);
} //CreateCustomerFile()
Sample Structures (Creating a File)
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
Visual Basic (Creating a File) – Sample Structure
Declare Function BTRCALL Lib "w3btrv7.dll" (ByVal OP, ByVal Pb$, _
  Db As Any, DL As Long, Kb As Any, ByVal Kl, _
  ByVal Kn) As Integer
 
Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _
  (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
 
Type OrderRecordBufferType
  OrderNumberAs typ_byte4        '4 byte unsigned
  ContactNumber As typ_byte4     '4 byte unsigned
  OrderDateAs DateType
  OrderTotal As typ_byte4        '4 byte real
  NotUsed As String * 64
End Type
 
Type OrderKeyBufferType
  BufferValue(255) As Byte
  OrderNumber As typ_byte4
  CustNumber As typ_byte4
  NotUsed As String * 64
End Type
 
Type FileSpec
  RecLenAs Integer
  PageSize As Integer
  IndxCnt As Integer
  NotUsedAs String * 4
  FileFlags As Integer
  Reserved As String * 2
  Allocation As Integer
  KeyBuf0 As KeySpec
  KeyBuf1 As KeySpec
  KeyBuf2 As KeySpec
  KeyBuf3 As KeySpec
  KeyBuf4 As KeySpec
  KeyBuf5 As KeySpec
End Type
 
Global FileDefinitionBuffer As FileSpec
 
      {The following are the Order table variables.}
Global OrdPosBlock              As Byte(0 to 127)
Global OrdRecPos                As typ_byte4
Global OrdRecBuf                As OrderRecordBufferType
Global OrdKeyBuffer             As OrderKeyBufferType
Global OrdFixedRecSize          As Long
Global OrdFileLocation          As String
Delphi (Creating a File) – Sample Structure
type
  CustomerRecordType = packed record
    Anything you want…
  end; //CustomerRecordType
 
type
  TPositionBlock = array[0..127] of byte;
 
type
  BTI_KEY_DESC = packed record
    Position : BTI_SINT;
    Length : BTI_SINT;
    KeyFlags : BTI_SINT;
    NumUnique : BTI_LONG;
    ExtKeyType: BTI_BYTE;
    NullVal : BTI_BYTE;
    Reserv : array [0..1] of BTI_CHAR;
    KeyNumber : BTI_UBYTE;
    ACSNumber : BTI_UBYTE;
  end;   {BTI_KEY_DESC}
 
  BTI_KEY_ARRAY = array [0..MAX_KEY_SEG - 1] of BTI_KEY_DESC;
  BTI_ACS       = array [0..ACS_SIZE - 1] of BTI_CHAR;
 
type
  FileCreateBuffer = packed record
    RecLen : BTI_SINT;
    PageSize : BTI_SINT;
    NumKeys : BTI_SINT;
    Reserved1 : BTI_LONG;
    FileFlags : BTI_SINT;
    DupPointers: BTI_BYTE;
    Reserved2 : BTI_BYTE;
    Alloc : BTI_SINT;
    Keys : BTI_KEY_ARRAY;
    ACS : BTI_ACS;
  end;   {BTI_FILE_DESC}
Note that the alternate collating sequence (ACS) is placed after the entire Keys array for ease of definition. Because Btrieve expects the ACS to immediately follow the last key segment, the ACS must be moved down to that position within the structure.
C/C++ (Creating a File)– Sample Structure
struct CustRec
{
anything you want…
} //CustRec
struct date_type
{
BTI_BYTE day;
BTI_BYTE month;
BTI_SINT year;
}; //date_type
 
struct KeySpec
{
BTI_SINT KeyPos;
BTI_SINT KeyLen;
BTI_SINT KeyFlags;
BTI_LONG KeyTot;
BTI_CHAR KeyType;
BTI_CHAR NulValue;
BTI_CHAR NotUsed[2];
BTI_BYTE KeyNumber;
BTI_BYTE ACSNum;
}; //KeySpec
struct FileDescriptionType
{
BTI_SINT RecLen;
BTI_SINT PageSize;
BTI_SINT IndxCnt;
BTI_LONG RecTot;
BTI_SINT FileFlags;
BTI_BYTE DupPointers;
BTI_BYTE NotUsed;
BTI_SINT Allocation;
KeySpec KeyBuf[119];
}; //FileDescriptionType
Inserting Records
The Insert (2) operation inserts a record into a file. Before you can make a call to this API:
The file must be open.
The record to be inserted must be the proper length, and the key values must conform to the keys defined for the file.
You can insert a row by calling BINSERT with the row to be inserted in the data buffer. For specific information about this API, see Btrieve API Guide. The following sample code and sample structures illustrate how to perform the Insert operation in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates how to insert a record using the Insert operation.
Visual Basic (Inserting Records)
FillCustBufFromCustomerEdit
 
InsertCustomerRecord  'BtrCallModule Procedure
 
Sub FillCustBufFromCustomerEdit()
  Dim tmplong As Long
  Dim StrDay As String * 2
  Dim StrMonth As String * 2
  Dim StrYear As String * 4
 
  tmplong = CLng(FormCustomerEdit.EdContactNumber.Text)
  CustRecBuf.ContactNumber = ToType4(tmplong)   
'see this function in the Sample Structures (Inserting Records) Sample
  CustRecBuf.ContactName       = FormCustomerEdit.EdContactName.Text
  CustRecBuf.CompanyName       = FormCustomerEdit.EdCompanyName.Text
  CustRecBuf.Address1          = FormCustomerEdit.EdAddress1.Text
  CustRecBuf.Address2          = FormCustomerEdit.EdAddress2.Text
  CustRecBuf.City              = FormCustomerEdit.EdCity.Text
  CustRecBuf.State             = FormCustomerEdit.EdState.Text
  CustRecBuf.ZipCode           = FormCustomerEdit.EdZip.Text
  CustRecBuf.Country           = FormCustomerEdit.EdCountry.Text
  CustRecBuf.SalesRep          = FormCustomerEdit.EdSalesRep.Text
  StrDay                       = Mid$(FormCustomerEdit.EdContactDate.Text, 1, 2)
  StrMonth                     = Mid$(FormCustomerEdit.EdContactDate.Text, 4, 2)
  StrYear                      = Mid$(FormCustomerEdit.EdContactDate.Text, 7, 4)
  CustRecBuf.NextContact.Day   = CByte(StrDay)
  CustRecBuf.NextContact.Month = CByte(StrMonth)
  CustRecBuf.NextContact.Year  = CInt(StrYear)
  CustRecBuf.PhoneNumber       = FormCustomerEdit.EdPhone.Text
  CustRecBuf.Notes             = Trim(FormCustomerEdit.EdNotes.Text) & Chr$(0)
  FormCustomerEdit.EdRecLength = Str(CustBufLength)
End Sub
 
Sub InsertCustomerRecord()
  Dim lCustBufLength As Long
  Dim iKeyNum As Integer
  Dim iKeyBufLen As Integer
  lCustBufLength = Len(CustRecBuf) - MaxNoteFieldSize + _
    Len(Trim(CustRecBuf.Notes))
  ' CustBufLength = 238
  iKeyBufLen = KEY_BUF_LEN
  iKeyNum = CustKeyBuffer.CurrentKeyNumber
  giStatus = BTRCALL(BINSERT, CustPosBlock, CustRecBuf, _
                     lCustBufLength, CustKeyBuffer, iKeyBufLen, iKeyNum)
End Sub
Delphi (Inserting Records)
function InsertCustomerRecord( var CustPosBlock :  TPositionBlock;
                                   CustRec      :  CustomerRecordType)
                                                :  SmallInt;
var
 CustBufLen : Word;
 KeyNum : ShortInt;
 CustKeyBuffer: String[255];
begin
      {Calculate the total size of variable-length record}
 CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) +  Length(CustRec.Notes);
 KeyNum := -1; {specify "No Currency Change" during insert}
 FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); {not needed going in}
 Result := BTRV(B_INSERT,           //OpCode 2
                CustPosBLock,       //Already opened position block
                CustRec,            //record to be inserted
                CustBufLen,         //Length of new record
                CustKeyBuffer[1],   //not needed for NCC insert
                KeyNum);
end;   {InsertCustomerRecord}
C/C++ (Inserting Records)
BTI_SINT InsertCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE],
Customer_Record_Type CustRec)
{
BTI_WORD CustBufLen;
char KeyNum; //signed byte
char CustKeyBuffer[255];
BTI_SINT iStatus;
 
/* Calculate the total size of variable length record : */
CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes);
KeyNum = -1; //specify "No Currency Change" during insert
memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //not needed going in
iStatus = BTRV(B_INSERT, //OpCode 2
CustPosBlock, //Already opened position block
&CustRec, //record to be inserted
&CustBufLen, //Length of new record
CustKeyBuffer, //not needed for NCC insert
KeyNum);
PrintStatus("B_INSERT: status = %d", iStatus);
return(iStatus);
} // InsertCustomerRecord()
Sample Structures (Inserting Records)
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
Visual Basic (Inserting Records) – Sample Structure
Global Const BINSERT = 2
 
    'The following are Customer table data structures.
 
Type CustomerRecordBufferType
  ContactNumber As typ_byte4
  ContactNameAs String * 30
  CompanyName As String * 60
  Address1 As String * 30
  Address2 As String * 30
  City As String * 30
  StateAs String * 2
  ZipCodeAs String * 10
  CountryAs String * 3
  PhoneNumberAs String * 20
  SalesRepAs String * 3
  NextContactAs DateType
  NotUsedAs String * 12
  Notes As String * MaxNoteFieldSize
End Type
 
     'The following are Customer file variables.
Global CustPosBlockAs Byte(0 to 127)
Global CustRecBuf As CustomerRecordBufferType
Global CustKeyBufferAs CustomerKeyBufferType
Global CustFixedRecSize As Long
Global CustFileLocationAs String
Global CustPositionAs typ_byte4
Global CustPosPercent As typ_byte4
 
Function ToInt(vValue As typ_byte4) As Long
  Dim iInt As Long
  CopyMemory iInt, vValue, 4
  ToInt = iInt
End Function
 
Function ToType4(vValue As Long) As typ_byte4
  Dim tmpTyp4 As typ_byte4
  CopyMemory tmpTyp4, vValue, 4
  ToType4 = tmpTyp4
End Function
Delphi (Inserting Records) – Sample Structure
type
  CustomerRecordType = packed record
    Anything you want…
  end; //CustomerRecordType
C/C++(Inserting Records) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Updating Records
The Update (3) operation changes the information in an existing record. To make this Btrieve call, the file must be open and have physical currency established. If you want to update a record within a transaction, you must retrieve the record within the transaction.
For more information about this API, see Btrieve API Guide. The following sample code and sample structures illustrate how to perform the update operation in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates modifying a file using the update operation.
Visual Basic (Updating Records)
FillCustBufFromCustomerEdit
UpdateCustomerRecord      'BtrCallModule Procedure
 
Sub FillCustBufFromCustomerEdit()
  Dim tmplong As Long
  Dim StrDay As String * 2
  Dim StrMonth As String * 2
  Dim StrYear As String * 4
 
  tmplong                      = CLng(FormCustomerEdit.EdContactNumber.Text)
  CustRecBuf.ContactNumber     = ToType4(tmplong)
  CustRecBuf.ContactName       = FormCustomerEdit.EdContactName.Text
  CustRecBuf.CompanyName       = FormCustomerEdit.EdCompanyName.Text
  CustRecBuf.Address1          = FormCustomerEdit.EdAddress1.Text
  CustRecBuf.Address2          = FormCustomerEdit.EdAddress2.Text
  CustRecBuf.City              = FormCustomerEdit.EdCity.Text
  CustRecBuf.State             = FormCustomerEdit.EdState.Text
  CustRecBuf.ZipCode           = FormCustomerEdit.EdZip.Text
  CustRecBuf.Country           = FormCustomerEdit.EdCountry.Text
  CustRecBuf.SalesRep          = FormCustomerEdit.EdSalesRep.Text
  StrDay                       = Mid$(FormCustomerEdit.EdContactDate.Text, 1, 2)
  StrMonth                     = Mid$(FormCustomerEdit.EdContactDate.Text, 4, 2)
  StrYear                      = Mid$(FormCustomerEdit.EdContactDate.Text, 7, 4)
  CustRecBuf.NextContact.Day   = CByte(StrDay)
  CustRecBuf.NextContact.Month = CByte(StrMonth)
  CustRecBuf.NextContact.Year  = CInt(StrYear)
  CustRecBuf.PhoneNumber       = FormCustomerEdit.EdPhone.Text
  CustRecBuf.Notes             = Trim(FormCustomerEdit.EdNotes.Text) & Chr$(0)
  FormCustomerEdit.EdRecLength = Str(CustBufLength)
End Sub
 
Sub UpdateCustomerRecord()
  Dim lCustBufLength As Long
  Dim iKeyBufLen As Integer
  Dim iKeyNum As Integer
 
     'The following syntax updates a customer record.
 
lCustBufLength = Len(CustRecBuf) - MaxNoteFieldSize + _
  Len(Trim(CustRecBuf.Notes))
iKeyBufLen = KEY_BUF_LEN
iKeyNum = CustKeyBuffer.CurrentKeyNumber
giStatus = BTRCALL(bUpdate, CustPosBlock, CustRecBuf, _
                   lCustBufLength, CustKeyBuffer, iKeyBufLen, iKeyNum)
End Sub
Delphi (Updating Records)
function UpdateCustomerRecord( var CustPosBlock: TPositionBlock;
                                   CustRec     : CustomerRecordType)
                                               : SmallInt;
var
 CustBufLen : Word;
 KeyNum : ShortInt;
 CustKeyBuffer : String[255];
begin
 { Calculate the total size of variable length record : }
 CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) +  Length(CustRec.Notes);
 KeyNum := -1; {specify "No Currency Change" during update}
 FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); {not needed going in}
 Result := BTRV(B_UPDATE,           //OpCode 3
                CustPosBLock,       //Already opened position block
                CustRec,            //new record
                CustBufLen,         //Length of new record
                CustKeyBuffer[1],   //not needed for NCC update
                KeyNum);
end;   {UpdateCustomerRecord}
C/C++ (Updating Records)
BTI_SINT UpdateCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE],
Customer_Record_Type CustRec)
{
BTI_WORD CustBufLen;
char KeyNum; //signed byte
char CustKeyBuffer[255];
BTI_SINT iStatus;
/* Calculate the total size of variable length record : */
CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes);
KeyNum = -1; //specify "No Currency Change" during update
memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //not needed going in
iStatus = BTRV(B_UPDATE, //OpCode 3
CustPosBlock, //Already opened position block
&CustRec, //record to be inserted
&CustBufLen, //Length of new record
CustKeyBuffer, //not needed for NCC insert
KeyNum);
PrintStatus("B_UPDATE: status = %d", iStatus);
return(iStatus);
} //UpdateCustomerRecord()
Sample Structures (Updating Records)
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
Visual Basic (Updating Records) – Sample Structure
Global Const bUpdate = 3
See the Sample Structures (Inserting Records) for the Insert operation.
Delphi (Updating Records) – Sample Structure
type
  CustomerRecordType = packed record
    Anything you want…
  end; //CustomerRecordType
C/C++ (Updating Records) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Performing Step Operations
The Step operations (Step First, Step Next, Step Last, Step Previous) allow you to retrieve a record into the data buffer. The MicroKernel does not use a key path to retrieve the record. For more detailed information about these APIs, see Btrieve API Guide.
The following sample code and sample structures illustrate how to perform the Step operations in Delphi and C/C++.
Note:  You should never depend on the order in which the records are returned. The MicroKernel may move a record within the file at any time. Use Get Operations if you need the records in a specific order.
Sample Code
The following sample code illustrates how to retrieve a record using the Step operations.
Delphi (Step Operations)
The following code example returns the record in the first physical location in the file.
  { Get First physical record from file : }
CustBufLen := SizeOf(CustRec);       //Maximum size of the data record
Status     := BTRV(B_STEP_FIRST,     //OpCode 33
                   CustPosBLock,     //Already opened position block
                   CustRec,          //Buffer for record to be returned in
                   CustBufLen,       //Maximum length to be returned
                   CustKeyBuffer[1], //Not needed in Steps
                   CustKeyNumber);   //Not needed in Steps
 
   {Get Second record in file: (no guaranteed order) }
CustBufLen := SizeOf(CustRec);      //Reset - previous Step may have changed it.
Status     := BTRV(B_STEP_NEXT,     //OpCode 24
                   CustPosBLock,
                   CustRec,
                   CustBufLen,
                   CustKeyBuffer[1]
                   CustKeyNumber);
 
    { Back to the First record : }
CustBufLen := SizeOf(CustRec);     //Reset - previous Step may have changed it.
Status     := BTRV(B_STEP_PREV,    //OpCode 35
                   CustPosBLock,
                   CustRec,
                   CustBufLen,
                   CustKeyBuffer[1],
                   CustKeyNumber);
C/C++ (Step Operations)
    /* Get First physical record from file : */
CustBufLen = sizeof(CustRec); //Maximum size of the data record
iStatus = BTRV(B_STEP_FIRST, //OpCode 33
CustPosBLock, //Already opened position block
&CustRec, //Buffer for record to be returned in
&CustBufLen, //Maximum length to be returned
CustKeyBuffer, //Not needed in Steps
KeyNum); //Not needed in Steps
/* Get Second record in file: (no guaranteed order) */
CustBufLen = sizeof(CustRec); //Reset - previous Step may have changed it.
iStatus = BTRV(B_STEP_NEXT, //OpCode 24
CustPosBLock,
&CustRec,
&CustBufLen,
CustKeyBuffer,
KeyNum);
/* Back to the First record : */
CustBufLen = sizeof(CustRec); //Reset - previous Step may have changed it.
iStatus = BTRV(B_STEP_PREVIOUS, //OpCode 35
CustPosBLock,
&CustRec,
&CustBufLen,
CustKeyBuffer,
KeyNum);
Sample Structures
These are the sample structures used in the previous code sample for Delphi and C/C++, respectively.
Delphi (Step Operations) – Sample Structure
type
  CustomerRecordType = packed record
    Anything you want…
  end; //CustomerRecordType
C/C++ (Step Operations) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Performing Get Operations
The Get operations allow you to retrieve a record. These operations require the key buffer parameter to specify which row (or rows) to return. For more detailed information about these APIs, see Btrieve API Guide.
The following sample code and sample structures illustrate how to perform some Get operations in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates how to retrieve a file using the Get operations.
Visual Basic (Get Operations)
Sub LoadContactBox(RecPosition As typ_byte4)
  FormBrowseCustomers.lstContact.Clear
  GetDirectCustomerRecord 'BtrCallModule Procedure
  If giStatus = 0 Then
 
   'The following syntax writes the contact list box string.
  FormatContListBoxString
  If giStatus = 0 Then
    PosIndex = 0
    PosArray(PosIndex) = RecPosition
    FirstRecPosition = RecPosition
  End If
  Else
    FormBrowseCustomers.lblMsg.Caption = "didn't get record"
  End If
 
   'The following syntax fills the rest of list box.
  While giStatus = 0 And PosIndex < CustMaxNumRows - 1
  GetNextCustomerRecord 'BtrCallModule Procedure
  If giStatus = 0 Then
   'write contact listbox string
    FormatContListBoxString
 
   'The following syntax returns the record position.
    GetPositionCustomerRecord'BtrCallModule Procedure
    If giStatus = 0 Then
      PosIndex = PosIndex + 1
      PosArray(PosIndex) = RecPosition
 
   'The following syntax configures the pointers to the array of the record    'positions.
 
      Select Case PosIndex
        Case 1
          SecondRecPosition = RecPosition
        Case 10
          SecToLastRecPosition = RecPosition
        Case 11
          LastRecPosition = RecPosition
      End Select
    End If
  End If
  Wend
  If FormBrowseCustomers.lstContact.ListCount <> 0 Then
  FormBrowseCustomers.lstContact.ListIndex = 0
  End If
End Sub
 
Sub GetDirectCustomerRecord()
  Dim iKeyBufLen As Integer
  Dim iKeyNum As Integer
 
   'The following syntax retrieves the direct record by the Record Position.
 
  BufLen = Len(CustRecBuf)
  iKeyBufLen = MaxKeyBufLen
  iKeyNum = CustKeyBuffer.CurrentKeyNumber
 
   'The following syntax places the address in the data buffer.
 
  CustRecBuf.Notes = "" 'clear variable length area before retrieve
  LSet CustRecBuf = RecPosition
  giStatus = BTRCALL(BGETDIRECT, CustPosBlock, _
  CustRecBuf, BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum)
  DBLen = BufLen
End Sub
 
Sub GetNextCustomerRecord()
  Dim iKeyNum As Integer
  Dim iKeyBufLen As Integer
 
   'The following syntax returns the next customer record.
 
  BufLen = Len(CustRecBuf)
  iKeyBufLen = KEY_BUF_LEN
  iKeyNum = CustKeyBuffer.CurrentKeyNumber
  giStatus = BTRCALL(BGETNEXT, CustPosBlock, CustRecBuf, _
                     BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum)
End Sub
 
Sub GetPositionCustomerRecord()
  Dim iKeyBufLen As Integer
  Dim iKeyNum As Integer
 
'The following syntax returns the record position.
 
  BufLen = MaxDataBufLen
  iKeyBufLen = KEY_BUF_LEN
  iKeyNum = CustKeyBuffer.CurrentKeyNumber
  giStatus = BTRCALL(BGETPOS, CustPosBlock, RecPosition, _
                     BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum)
End Sub
Delphi (Get Operations)
var
 CustKeyBuffer: LongInt;
begin
 CustBufLen := SizeOf(CustRec);
 CustKeyNumber := 0; {In order by Contact ID}
 
   {The following syntax returns the first record from the file using the specified}    {sort order.}
 CustBufLen := SizeOf(CustRec);    //Maximum size of the data record
 Status     := BTRV(B_GET_FIRST,   //OpCode 12
                    CustPosBLock,  //Already opened position block
                    CustRec,       //Buffer for record to be returned in
                    CustBufLen,      //Maximum length to be returned
                    CustKeyBuffer,   //Returns the key value extracted from the record
                    CustKeyNumber);  //Index order to use for retrieval
 
    {The following syntax returns the second record in a file in the specified sort}     {order.}
 CustBufLen := SizeOf(CustRec);  //Reset - previous Get may have changed it.
 Status     := BTRV(B_GET_NEXT,  //OpCode 6
                    CustPosBLock,
                    CustRec,
                    CustBufLen,
                    CustKeyBuffer[1],
                    CustKeyNumber);
 
   {The following syntax returns the previous record in the file.}
 CustBufLen := SizeOf(CustRec);  //Reset - previous Step may have changed it.
 Status     := BTRV(B_GET_PREV,  //OpCode 7
                    CustPosBLock,
                    CustRec,
                    CustBufLen,
                    CustKeyBuffer[1],
                    CustKeyNumber);
C/C++ (Get Operations)
      /* Get First logical record from file : */
CustBufLen = sizeof(CustRec); //Maximum size of the data record
iStatus = BTRV(B_GET_FIRST, //OpCode 12
CustPosBLock, //Already opened position block
&CustRec, //Buffer for record to be returned in
&CustBufLen, //Maximum length to be returned
CustKeyBuffer, //Returns the key value extracted from the record
CustKeyNumber); //Index order to use for retrieval
/* Get Second record in file: in order by chosen key */
CustBufLen = sizeof(CustRec); //Reset - previous Get may have changed it.
iStatus = BTRV(B_GET_NEXT, //OpCode 6
CustPosBLock,
&CustRec,
&CustBufLen,
CustKeyBuffer,
CustKeyNumber);
/* Back to the First record : */
CustBufLen = sizeof(CustRec); //Reset - previous Get may have changed it.
iStatus = BTRV(B_GET_PREVIOUS, //OpCode 7
CustPosBLock,
&CustRec,
&CustBufLen,
CustKeyBuffer,
CustKeyNumber);
Sample Structures (Get Operations)
These are the sample structures used in the previous code sample for Visual Basic and Delphi, respectively.
Visual Basic (Get Operations) – Sample Structure
Global Const BGETNEXT = 6
Global Const BGETDIRECT = 23
Global Const BGETPOS = 22
Delphi (Get Operations) – Sample Structure
type
  CustomerRecordType = packed record
    Anything you want…
  end; //CustomerRecordType
C/C++ (Get Operations) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Chunking, BLOBs, and Variable-Length Records
Btrieve chunk operations allow you to read or write portions of variable-length records and BLOBs. The maximum record length is 64 GB; however, the maximum fixed-record length is 64 KB (65535 bytes). Use chunking when you want to access portions of a record beyond the first 65535 bytes.
Sample Code
The following sample code illustrates how to handle chunking, binary large objects (BLOBs), and variable-length records.
Visual Basic (Chunking/BLOBs/Variable-Length Records)
Private Sub LoadImageFromBtrieve()
 
'The following syntax returns the image stored in Btrieve into the file described
'in the output image text box.
 
  Dim lBytes As Long
  Dim lBytesread As Long
  Dim sLine As String
  Dim lBytesToRead As Long
  Dim iKey As Integer
  Dim lAddressMode As Long
  Dim lNumberOfChunks As Long
  Dim lChunkOffset As Long
  Dim lChunkAddress As Long
  Dim lChunkLength As Long
  Dim iNumChunksRead As Integer
 
  GetEqualGraphicRecord 'gets the record and part of the blob
  On Error GoTo FileNotFound
 
  FormCustomerGraphic.MousePointer = 11
  lNumberOfChunks = 0
  On Error GoTo BMPOpenError
  Open txtOutputImage.Text For Binary Access Write As #1
  lBytesread = (BufLen - 68)    'saves the number of bytes read - fixed length of
                                'graphic record.fixed length = 68 bytes on first
                                'chunk of graphic record (GetEqualGraphicRecord
                                'above).
 
  sLine = Right(ChunkReadBuffer.ChunkArray, lBytesread)
  Put #1, , sLine         'write the first chunk to the bmp file.
  iNumChunksRead = 1
  If giStatus = 22 And (BufLen = MaxChunkSize) Then
    GetPositionGraphicRecord    'you have to have the position of the current record
                                'before you can do a get chunk
    Do
      lNumberOfChunks              = 1
      lChunkOffset                 = 0
      lChunkAddress                = 0
      lChunkLength                 = MaxChunkSize
      iNumChunksRead               = iNumChunksRead + 1
      ChunkGetBuffer.RecordAddress = GrphPosition
 
   'H80000000 (Get random chunk)
 
   'H40000000 (Next in record bias) causes use of intrarecord currency.
 
      ChunkGetBuffer.AddressMode    = ToType4((&H80000000 + &H40000000))
      ChunkGetBuffer.NumberOfChunks = ToType4(lNumberOfChunks)
      ChunkGetBuffer.ChunkOffset    = ToType4(lChunkOffset)
      ChunkGetBuffer.ChunkAddress   = ToType4(lChunkAddress)
      ChunkGetBuffer.ChunkLength    = ToType4(lChunkLength)
 
'The previous syntax uses the read buffer. Subsequent get chunks use the entire
'buffer because the fixed length of the record was read with the first get chunk
'GetEqualGraphicRecord
 
'The following syntax loads the read buffer with the get buffer.
 
   CopyMemory ChunkReadBuffer, ChunkGetBuffer, Len (ChunkGetBuffer)
   GetGraphicChunk
   If giStatus = 0 Then      'you should get a 103 if you read past the end of the
                             'record
        If MaxChunkSize <> BufLen Then
          sLine = Left(ChunkReadBuffer.ChunkArray, BufLen)
          lBytesread = lBytesread + (BufLen)
          Else
          sLine = ChunkReadBuffer.ChunkArray
          Bytesread = lBytesread + MaxChunkSize
        End If
          If Len(sLine) > 0 Then
          Put #1, , sLine
        End If
      End If
    Loop While (giStatus = 0)
  End If
  Close #1
  On Error Resume Next
  Set Image1.Picture = LoadPicture(txtOutputImage.Text)
    FormCustomerGraphic.MousePointer = 0
    NumChunks.Text = iNumChunksRead
    NumBytes.Text = lBytesread
    LastStatus.Text = giStatus
    On Error GoTo 0
Exit Sub
 
      'InvalidPicture:
 
  MsgBox Err.Number & ": " & Err.Description & vbCrLf & "Load from disk and save", vbOKOnly, "Invalid Picture in Graphic file"
  Resume Next
 
FileNotFound:
  MsgBox Err.Number & ": " & Err.Description, vbOKOnly, "Graphic Load Error"
  FormCustomerGraphic.MousePointer = 0
  On Error GoTo 0
 
BMPOpenError:
  MsgBox "Directory for temporary imaging work does not exist. " & vbCrLf & _
 
  "Please select a valid directory for image out.", vbOKOnly, "User path error"
 
  Screen.MousePointer = vbDefault
  On Error GoTo 0
End Sub
 
Sub GetGraphicChunk()
  Dim sKeyBuffer As String
  Dim iKeyBufLen As Integer
 
  BufLen = Len(ChunkReadBuffer)
  sKeyBuffer = Space$(KEY_BUF_LEN)
  iKeyBufLen = KEY_BUF_LEN
 
   {In the following syntax, the key number must be set to -2 for chunking mode.}
 
  giStatus = BTRCALL(BGETDIRECT, GrphPosBlock, ChunkReadBuffer, _ BufLen, ByVal
                     sKeyBuffer, iKeyBufLen, -2)
End Sub
Sample Structures
(Chunking/BLOBs/Variable-Length Records)
These are the sample structures used in the previous code sample for Visual Basic.
Visual Basic (Chunking/BLOBs/Variable-Length Records) – Sample Structure
Type GraphicRecordBufferType
  ContactNumber As typ_byte4
  NotUsed As String * 64
End Type
 
Type GraphicKeyBufferType
  BufferValue(255)As Byte
  CurrentKeyNumberAs Integer
  ContactNumber As typ_byte4
  NotUsed As String * 64
End Type
 
Type ChunkReadDescriptorNext
  ChunkArray As String * MaxChunkSize
End Type
 
Type ChunkGetDescriptor
  RecordAddressAs typ_byte4
  AddressModeAs typ_byte4
  NumberOfChunks As typ_byte4
  ChunkOffsetAs typ_byte4
  ChunkLengthAs typ_byte4
  ChunkAddress As typ_byte4
End Type
 
Global ChunkGetBuffer As ChunkGetDescriptor
Global ChunkReadBuffer As ChunkReadDescriptorNext
 
   ' Graphic Table Variables
Global GrphPosBlock As Byte(0 to 127)
Global GrphRecBuf As GraphicRecordBufferType
Global GrphKeyBuffer As GraphicKeyBufferType
Global GrphFixedRecSize As Long
Global GrphFileLocation As String
Global GrphKeyNumber As Integer
Global GrphPosition As typ_byte4
Working with Segmented Indexes
The following sample code illustrates how to handle segmented indexes.
Sample Code
Visual Basic (Segmented Indexes)
Sub CreateCustomerFile(CustFileLocation As String)
 
   'The following syntax creates the customer file and configures the file
   'specifications.
 
  CustFixedRecSize = Len(CustRecBuf) - Len(CustRecBuf.Notes)
  FileDefinitionBuffer.RecLen = CustFixedRecSize
  FileDefinitionBuffer.PageSize = 4096
  FileDefinitionBuffer.IndxCnt = 4
  FileDefinitionBuffer.FileFlags = VARIABLELENGTH
 
    'The following defines key specifications.
 
    'Key 0, by contact number.
  FileDefinitionBuffer.KeyBuf0.KeyPos = 1
  FileDefinitionBuffer.KeyBuf0.KeyLen = 4
  FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE
  FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC)
 
    'Key 1, by contact name.
  FileDefinitionBuffer.KeyBuf1.KeyPos = 5
  FileDefinitionBuffer.KeyBuf1.KeyLen = 30
  FileDefinitionBuffer.KeyBuf1.KeyFlags = EXTTYPE + MODIFIABLE + DUP
  FileDefinitionBuffer.KeyBuf1.KeyType = Chr$(BSTRING)
 
   'Key 2, by contact name.
  FileDefinitionBuffer.KeyBuf2.KeyPos = 35
  FileDefinitionBuffer.KeyBuf2.KeyLen = 60
  FileDefinitionBuffer.KeyBuf2.KeyFlags = EXTTYPE + MODIFIABLE + DUP
  FileDefinitionBuffer.KeyBuf2.KeyType = Chr$(BSTRING)
 
   'Key 3, by sales representative, by next contact date.
 
   'This is a segmented key:
  FileDefinitionBuffer.KeyBuf3.KeyPos = 220
  FileDefinitionBuffer.KeyBuf3.KeyLen = 3
  FileDefinitionBuffer.KeyBuf3.KeyFlags = EXTTYPE + _ MODIFIABLE + DUP + SEGMENT
  FileDefinitionBuffer.KeyBuf3.KeyType = Chr$(BSTRING)
  FileDefinitionBuffer.KeyBuf4.KeyPos = 223
  FileDefinitionBuffer.KeyBuf4.KeyLen = 4
  FileDefinitionBuffer.KeyBuf4.KeyFlags = EXTTYPE + MODIFIABLE + DUP
  FileDefinitionBuffer.KeyBuf4.KeyType = Chr$(BDATE)
 
  BufLen = Len(FileDefinitionBuffer)
  CustFileLocation = CustFileLocation & " "
  KeyBufLen = Len(CustFileLocation)
  giStatus = BTRCALL(BCREATE, CustPosBlock, FileDefinitionBuffer, _
    BufLen, ByVal CustFileLocation, KeyBufLen, 0)
End Sub
Delphi (Segmented Indexes)
To see code on creating segmented indexes, see "Key 3" in the Delphi (Creating a File) code sample.
var
  CustKeyBuffer : record                //Segmented key buffer
    SalesRep     : array[0..2] of Char;
    NextContact  : DateType;             //Btrieve Date structure
  end;
 
  CustBufLen: Word;
  CustKeyNumber: ShortInt;
begin
  CustKeyNumber := 3;                       //In order by SalesRep/Date
  CustKeyBuffer.SalesRep := 'TO';           //Look for person with initials TO
  CustKeyBuffer.NextContact.Day := 9;       //and NextContact of 9/9/98
  CustKeyBuffer.NextContact.Month := 9;
  CustKeyBuffer.NextContact.Year := 1998;
 
  CustBufLen := SizeOf (CustRec);
 
    {The following syntax gets the first record from the file using the specified}
    {sort order (KeyNum) :}
  Status := BTRV(B_GET_EQUAL,      //OpCode 5
                 CustPosBLock,     //Already opened position block
                 CustRec,          //Buffer for record to be returned in
                 CustBufLen,       //Maximum length to be returned
                 CustKeyBuffer,    //Returns the key value extracted from the record
                 CustKeyNumber);   //Index order to use for retrieval
C/C++ (Segmented Indexes)
struct //Segmented key buffer
{
char SalesRep[3];
date_type NextContact; //Btrieve Date structure
} CustKeyBuffer;
BTI_WORD CustBufLen;
char CustKeyNumber;
CustKeyNumber = 3; //In order by SalesRep/Date
CustKeyBuffer.SalesRep = "TO"; //Look for person with initials TO
CustKeyBuffer.NextContact.Day = 9; // and NextContact of 9/9/98
CustKeyBuffer.NextContact.Month = 9;
CustKeyBuffer.NextContact.Year = 1998;
CustBufLen = sizeof(CustRec);
/* Get First record from file using specified sort order (KeyNum): */
iStatus = BTRV(B_GET_EQUAL, //OpCode 5
CustPosBLock, //Already opened position block
&CustRec, //Buffer for record to be returned in
&CustBufLen, //Maximum length to be returned
CustKeyBuffer, //Specifies the record to look for
CustKeyNumber); //Index order to use for retrieval
Declarations of Btrieve API Functions for Visual Basic
The following are declarations of the Btrieve API functions for Visual Basic.
Declare Function BTRCALL Lib "w3btrv7.dll" (ByVal OP, ByVal Pb$, Db As Any, DL As Long, Kb As Any, ByVal Kl, ByVal Kn) As Integer
 
Declare Function BTRCALLID Lib "w3btrv7.dll" (ByVal OP, ByVal Pb$, Db As Any, DL As Long, Kb As Any, ByVal Kl, ByVal Kn, ByVal ID) As Integer
 
Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
 
Last modified date: 10/31/2023