Tutorials and Guide to Samples (v11)

Delphi (Btrieve API 用の言語インターフェイス)

ここでは、以下の項目について説明します。

プログラムの例

Web ダウンロードにより提供される以下のプログラム例では、Btrieve の一般的な操作方法を説明します。これらの操作は、MicroKernel との依存関係で要求される順番(ファイルを開いてから I/O を実行するなど)で行われます。

Btrsam32.pas

{********************************************************************* 
** 
**  Copyright 1982-2003 Pervasive Software Inc. All Rights Reserved 
** 
*********************************************************************} 
{********************************************************************* 
  BTRSAM32.DPR 
    これは、目的の環境で、コンパイラ ツールを使用した Btrieve アプリケーションの 
    コンパイル、リンク、実行が可能なことを確認するための簡単なサンプルです。 
 
    このプログラムでは、Btrieve の Delphi インターフェイスを示します。 
    MS Windows NT/2000 および Windows 9x/ME 上の Delphi 2.0、3.0、 
    4.0 および 5.0 で動作します。 
 
    このプログラムでは、サンプル ファイルで以下の操作を行います。 
    - BTRVID を使用して Microkernel Database エンジンのバージョン情報を取得する 
    - sample.btr を開く 
    - Key 0 の既知の値を持つレコードを取得する 
    - 読み込んだレコードを表示する 
    - Stat オペレーションを実行する 
    - 空の sample.btr のクローンを作成して開く 
    - Get Next Extended オペレーションを実行して 
      sample.btr のレコードのサブセットを抽出する 
    - クローン ファイルにこれらのレコードを挿入する 
    - 両ファイルを閉じる 
 
    重要:Btrieve データ ファイルのサンプル sample.btr が保存されている 
    ディレクトリは、フルパスを指定してください。また、それぞれの「重要」項目も 
    参考にしてください。 
 
    Delphi 2.0/3.0/4.0/5.0 Btrieve プロジェクトは、 
    Delphi プロジェクト環境のプルダウン メニューから以下を選択後コンパイルします。 
 
        PROJECT 
           OPTIONS... 
              COMPILER 
                 CODE GENERATION 
                    ALIGNED RECORD FIELDS ( de-select this ) 
 
        これを行わない場合、レコードが正しく出力されません。 
        これは、レコードがバイトパックされていないためです。 
 
        代わりに、(*A-*) コンパイラ命令を使用するか、下に示すように、 
        すべてのレコードを「パック」として宣言します。 
        詳細については、Delphi のマニュアルを参照してください。 
 
      PROJECT FILES: 
         - btr32.dpr       Borland project file 
         - btr32.dof       Borland project file 
         - btrsam32.dfm    Borland project file 
         - btrsam32.pas    Source code for the simple sample 
         - btrapi32.pas    Delphi interface to Btrieve 
         - btrconst.pas    Btrieve constants file 
 
*********************************************************************} 
unit btrsam32; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 
Dialogs, 
  StdCtrls, BtrConst, BtrAPI32; 
 
{********************************************************************* 
   プログラム定数 
*********************************************************************} 
const 
  { プログラム定数 } 
  MY_THREAD_ID        = 50; 
  EXIT_WITH_ERROR     = 1; 
  VERSION_OFFSET      = 0; 
  REVISION_OFFSET     = 2; 
  PLATFORM_ID_OFFSET  = 4; 
 
{********************************************************************* 
   重要:以下を変更し、使用する sample.btr へのフルパスを指定してください。 
 ********************************************************************} 
  FILE_1              = 'c:¥samples¥sample.btr'; 
  FILE_2              = 'c:¥samples¥sample2.btr'; 
 
{********************************************************************* 
  バージョン処理用のレコードの型定義 
*********************************************************************} 
type 
  CLIENT_ID = packed record 
    networkandnode :array[1..12] of char; 
    applicationID  :array[1..3]  of char; 
    threadID       :smallint; 
  end; 
 
  VERSION_STRUCT = packed record 
    version   :smallint; 
    revision  :smallint; 
    MKDEId    :char; 
  end; 
 
{********************************************************************* 
  sample.btr のレコードの定義 
*********************************************************************} 
 
  {* writeln() への対応のため、ゼロ基準のキャラクター配列を使用 *} 
  PERSON_STRUCT = packed record 
    ID          :longint; 
    FirstName   :array[0..15] of char; 
    LastName    :array[0..25] of char; 
    Street      :array[0..30] of char; 
    City        :array[0..30] of char; 
    State       :array[0..2]  of char; 
    Zip         :array[0..10] of char; 
    Country     :array[0..20] of char; 
    Phone       :array[0..13] of char; 
  end; 
 
{********************************************************************* 
  Stat および Create 処理用のレコードの型定義 
*********************************************************************} 
  FILE_SPECS = packed record 
    recLength   :smallint; 
    pageSize    :smallint; 
    indexCount  :smallint; 
    reserved    :array[0..3] of char; 
    flags       :smallint; 
    dupPointers :byte; 
    notUsed     :byte; 
    allocations :smallint; 
  end; 
 
  KEY_SPECS = packed record 
    position    :smallint; 
    length      :smallint; 
    flags       :smallint; 
    reserved    :array[0..3] of char; 
    keyType     :char; 
    nullChar    :char; 
    notUsed     :array[0..1] of char; 
    manualKeyNumber :byte; 
    acsNumber       :byte; 
  end; 
 
  FILE_CREATE_BUF = packed record 
    fileSpecs :FILE_SPECS; 
    keySpecs  :array[0..4] of KEY_SPECS; 
  end; 
 
{********************************************************************* 
  Get Next Extended 処理用のレコードの型定義 
*********************************************************************} 
 
  GNE_HEADER = packed record 
    descriptionLen  :smallint; 
    currencyConst   :array[0..1] of char; 
    rejectCount     :smallint; 
    numberTerms     :smallint; 
  end; 
 
  TERM_HEADER = packed record 
    fieldType       :byte; 
    fieldLen        :smallint; 
    fieldOffset     :smallint; 
    comparisonCode  :byte; 
    connector       :byte; 
    value           :array[0..2] of char; 
  end; 
 
  RETRIEVAL_HEADER = packed record 
    maxRecsToRetrieve   :smallint; 
    noFieldsToRetrieve  :smallint; 
  end; 
 
  FIELD_RETRIEVAL_HEADER = packed record 
    fieldLen        :smallint; 
    fieldOffset     :smallint; 
  end; 
 
  PRE_GNE_BUFFER = packed record 
    gneHeader :GNE_HEADER; 
    term1     :TERM_HEADER; 
    term2     :TERM_HEADER; 
    retrieval :RETRIEVAL_HEADER; 
    recordRet :FIELD_RETRIEVAL_HEADER; 
  end; 
 
  RETURNED_REC = packed record 
    recLen        :smallint; 
    recPos        :longint; 
    personRecord  :PERSON_STRUCT; 
  end; 
 
  POST_GNE_BUFFER = packed record 
    numReturned :smallint; 
    recs        :packed array[0..19] of RETURNED_REC; 
  end; 
 
  GNE_BUFFER_PTR = ^GNE_BUFFER; 
  GNE_BUFFER = packed record 
  case byte of 
    1 : (preBuf  :PRE_GNE_BUFFER); 
    2 : (postBuf :POST_GNE_BUFFER); 
  end; 
 
{********************************************************************* 
  Delphi で作成されたフォームの定義 
*********************************************************************} 
  TForm1 = class(TForm) 
    RunButton  :TButton; 
    ExitButton :TButton; 
    ListBox1   :TListBox; 
    procedure FormCreate(Sender:TObject); 
    procedure ExitButtonClick(Sender:TObject); 
    procedure RunButtonClick(Sender:TObject); 
  private 
  { Private 宣言 } 
    ArrowCursor, 
    WaitCursor    :HCursor; 
    status        :smallint; 
    bufferLength  :smallint; 
    personRecord  :PERSON_STRUCT; 
    recordsRead   :longint; 
    procedure RunTest; 
  public 
    { Public 宣言 } 
  end; 
 
var 
  Form1:TForm1; 
 
 
{********************************************************************* 
  ここからプログラム開始 
*********************************************************************} 
implementation 
 
{$R *.DFM} 
 
{********************************************************************* 
   プログラム変数 
*********************************************************************} 
var 
  { Btrieve 関数パラメーター } 
  posBlock1     :string[128]; 
  posBlock2     :string[128]; 
  dataBuffer    :array[0..255] of char; 
  dataLen       :word; 
  keyBuf1       :string[255]; 
  keyBuf2       :string[255]; 
  keyNum        :smallint; 
 
  btrieveLoaded :boolean; 
  personID      :longint; 
  file1Open     :boolean; 
  file2Open     :boolean; 
  status        :smallint; 
  getStatus     :smallint; 
  i             :smallint; 
  posCtr        :smallint; 
  client        :CLIENT_ID; 
  versionBuffer :array[1..3] of VERSION_STRUCT; 
  fileCreateBuf :FILE_CREATE_BUF; 
  gneBuffer     :GNE_BUFFER_PTR; 
  personRecord  :PERSON_STRUCT; 
 
{********************************************************************* 
   ListBox に書き込むためのヘルパー関数 
*********************************************************************} 
procedure WritelnLB( LB:TListBox; Str:String); 
begin 
  LB.Items.Add(Str); 
end; 
 
procedure TForm1.FormCreate(Sender:TObject); 
begin 
  ArrowCursor    := LoadCursor(0, IDC_ARROW); 
  WaitCursor     := LoadCursor(0, IDC_WAIT); 
end; 
 
{********************************************************************* 
   サンプルのメイン プロシージャ 
*********************************************************************} 
procedure TForm1.RunTest; 
begin 
  ListBox1.Clear; 
  WritelnLB( ListBox1, 'Test started ...' ); 
 
  { 変数の初期化 } 
  btrieveLoaded := FALSE; 
  file1Open := FALSE; 
  file2Open := FALSE; 
  keyNum := 0; 
  status := B_NO_ERROR; 
  getStatus := B_NO_ERROR; 
 
  { クライアント ID のセットアップ } 
  fillchar(client.networkAndNode, sizeof(client.networkAndNode), #0); 
  client.applicationID := 'MT'・+ #0;  { "AA" 以上を設定 } 
  client.threadID := MY_THREAD_ID; 
 
  fillchar(versionBuffer, sizeof(versionBuffer), #0); 
  dataLen := sizeof(versionBuffer); 
 
  status = BTRVID( 
              B_VERSION, 
              posBlock1, 
              versionBuffer, 
              dataLen, 
              keyBuf1[1], 
              keyNum, 
              client); 
 
  if status = B_NO_ERROR then begin 
    writelnLB( ListBox1, '返された Btrieve バージョンは' ); 
    for i := 1 to 3 do begin 
      with versionBuffer[i] do begin 
        if (version > 0) then begin 
          writelnLB(ListBox1, intToStr(version) + '.' + 
                     intToStr(revision) + ' ' + MKDEId); 
        end 
      end 
    end; 
    btrieveLoaded := TRUE; 
  end else begin 
    writelnLB(ListBox1, 'Btrieve B_VERSION status = ' + 
intToStr(status)); 
    if status <> B_RECORD_MANAGER_INACTIVE then begin 
      btrieveLoaded := TRUE; 
    end 
  end; 
 
  { sample.btr を開く } 
  if status = B_NO_ERROR then begin 
    fillchar(dataBuffer, sizeof(dataBuffer), #0); 
    fillchar(keyBuf1, sizeof(keyBuf1), #0); 
    keyNum  := 0; 
    dataLen := 0; 
 
    keyBuf1 := FILE_1 + #0; 
    keyBuf2 := FILE_2 + #0; 
 
    status = BTRVID( 
                  B_OPEN, 
                  posBlock1, 
                  dataBuffer, 
                  dataLen, 
                  keyBuf1[1], 
                  keyNum, 
                  client); 
 
    writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status)); 
    if status = B_NO_ERROR then begin 
      file1Open := TRUE; 
    end 
  end; 
 
  {* B_GET_EQUAL を使用して key 0 が既知の値であるレコードを取得 *} 
  if status = B_NO_ERROR then begin 
    fillchar(personRecord, sizeof(personRecord), #0); 
    dataLen := sizeof(personRecord); 
    personID := 263512477;  {* 実際これは社会保障番号 *} 
 
    status = BTRVID( 
                B_GET_EQUAL, 
                posBlock1, 
                personRecord, 
                dataLen, 
                personID, 
                keyNum, 
                client); 
 
    writelnLB(ListBox1, 'Btrieve B_GET_EQUAL status = ' + 
intToStr(status)); 
    if status = B_NO_ERROR then with personRecord do begin 
      writelnLB(ListBox1, ''); 
      writelnLB(ListBox1, 'Selected fields from the retrieved record 
are:'); 
      writelnLB(ListBox1, 'ID:' + intToStr(ID)); 
      writelnLB(ListBox1, 'Name:' + FirstName + ' ' + LastName); 
      writelnLB(ListBox1, 'Street:' + Street); 
      writelnLB(ListBox1, 'City:' + City); 
      writelnLB(ListBox1, 'State:' + State); 
      writelnLB(ListBox1, 'Zip:' + Zip); 
      writelnLB(ListBox1, 'Country:' + Country); 
      writelnLB(ListBox1, 'Phone:' + Phone); 
      writelnLB(ListBox1, ''); 
    end; 
  end; 
 
  { Stat オペレーションを実行し、CreateBuffe(作成バッファー)を取得 } 
  fillchar(fileCreateBuf, sizeof(fileCreateBuf), #0); 
  dataLen := sizeof(fileCreateBuf); 
  keyNum  := -1; 
  status := BTRVID(B_STAT, 
                posBlock1, 
                fileCreateBuf, 
                dataLen, 
                keyBuf1[1], 
                keyNum, 
                client); 
 
  if (status = B_NO_ERROR) then begin 
    { sample2.btr を作成して開く } 
    keyNum  := 0; 
    dataLen := sizeof(fileCreateBuf); 
    status := BTRVID(B_CREATE, 
                  posBlock2, 
                  fileCreateBuf, 
                  dataLen, 
                  keyBuf2[1], 
                  keyNum, 
                  client); 
 
    writelnLB(ListBox1, 'Btrieve B_CREATE status = ' + 
intToStr(status)); 
  end; 
 
  if (status = B_NO_ERROR) then begin 
    keyNum  := 0; 
    dataLen := 0; 
 
    status = BTRVID( 
                B_OPEN, 
                posBlock2, 
                dataBuffer, 
                dataLen, 
                keyBuf2[1], 
                keyNum, 
                client); 
    writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status)); 
    if (status = B_NO_ERROR) then begin 
      file2Open := TRUE; 
    end; 
  end; 
 
  { 元のファイルからデータを抽出し、新しいファイルへ挿入 } 
  if (status = B_NO_ERROR) then begin 
    { getFirst を実行してカレンシーを確立 } 
    keyNum := 2; { STATE-CITY index } 
    fillchar(personRecord, sizeof(personRecord), #0); 
    fillchar(keyBuf1, sizeof(keyBuf1), #0); 
    dataLen := sizeof(personRecord); 
 
    getStatus := BTRVID( 
                   B_GET_FIRST, 
                   posBlock1, 
                   personRecord, 
                   dataLen, 
                   keyBuf1[1], 
                   keyNum, 
                   client); 
 
    writelnLB(ListBox1, 'Btrieve B_GET_FIRST status = ' + 
intToStr(GETstatus)); 
    writelnLB(ListBox1, ''); 
  end; 
 
  { ヒープ メモリの割り当て } 
  gneBuffer := new(GNE_BUFFER_PTR); 
  fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0); 
 
  strPCopy(gneBuffer^.preBuf.gneHeader.currencyConst, 'UC'); 
  while (getStatus = B_NO_ERROR) do begin 
    gneBuffer^.preBuf.gneHeader.rejectCount := 0; 
    gneBuffer^.preBuf.gneHeader.numberTerms := 2; 
    posCtr := sizeof(GNE_HEADER); 
 
    { 最初の条件を代入 } 
    gneBuffer^.preBuf.term1.fieldType := 11; 
    gneBuffer^.preBuf.term1.fieldLen := 3; 
    gneBuffer^.preBuf.term1.fieldOffset := 108; 
    gneBuffer^.preBuf.term1.comparisonCode := 1; 
    gneBuffer^.preBuf.term1.connector := 2; 
 
    strPCopy(gneBuffer^.preBuf.term1.value, 'TX'); 
    inc(posCtr, (sizeof(TERM_HEADER))); 
 
    { 2 つ目の条件を代入 } 
    gneBuffer^.preBuf.term2.fieldType := 11; 
    gneBuffer^.preBuf.term2.fieldLen := 3; 
    gneBuffer^.preBuf.term2.fieldOffset := 108; 
    gneBuffer^.preBuf.term2.comparisonCode := 1; 
    gneBuffer^.preBuf.term2.connector := 0; 
    strPCopy(gneBuffer^.preBuf.term2.value, 'CA'); 
    inc(posCtr, sizeof(TERM_HEADER)); 
 
    { プロジェクション ヘッダーを設定してレコード全体を読み込む } 
    gneBuffer^.preBuf.retrieval.maxRecsToRetrieve := 20; 
    gneBuffer^.preBuf.retrieval.noFieldsToRetrieve := 1; 
    inc(posCtr, sizeof(RETRIEVAL_HEADER)); 
    gneBuffer^.preBuf.recordRet.fieldLen := sizeof(PERSON_STRUCT); 
    gneBuffer^.preBuf.recordRet.fieldOffset := 0; 
    inc(posCtr, sizeof(FIELD_RETRIEVAL_HEADER)); 
    gneBuffer^.preBuf.gneHeader.descriptionLen := posCtr; 
 
    dataLen := sizeof(GNE_BUFFER); 
    getStatus := BTRVID( 
                   B_GET_NEXT_EXTENDED, 
                   posBlock1, 
                   gneBuffer^, 
                   dataLen, 
                   keyBuf1, 
                   keyNum, 
                   client); 
 
    writelnLB(ListBox1, 'Btrieve B_GET_NEXT_EXTENDED status = ' + 
intToStr(getStatus)); 
 
    { Get Next Extended は、ファイルの終わりまで到達してもレコードを } 
    { 返すことがあります } 
    if ((getStatus = B_NO_ERROR) or (getStatus = B_END_OF_FILE)) then 
begin 
      writelnLB(ListBox1, 'GetNextExtended returned ' + 
                intToStr(gneBuffer^.postBuf.numReturned) + ' records.'); 
      for i := 0 to gneBuffer^.postBuf.numReturned - 1 do begin 
        dataLen := sizeof(PERSON_STRUCT); 
        personRecord := gneBuffer^.postBuf.recs[i].personRecord; 
        status = BTRVID( 
                    B_INSERT, 
                    posBlock2, 
                    personRecord, 
                    dataLen, 
                    keyBuf2, 
                    -1,   { カレンシー変更なし } 
                    client); 
        if (status <> B_NO_ERROR) then begin 
          writelnLB(ListBox1, 'Btrieve B_INSERT status = ' + 
intToStr(status)); 
          break; 
        end; 
      end; 
 
      writelnLB(ListBox1, 'Inserted ' + 
intToStr(gneBuffer^.postBuf.numReturned) + 
                ' records in new file, status = ' + intToStr(status)); 
      writelnLB(ListBox1, ''); 
    end; 
    fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0); 
    gneBuffer^.preBuf.gneHeader.currencyConst := 'EG'; 
  end; 
  dispose(gneBuffer); 
 
  { 開いているファイルを閉じる } 
  keyNum  := 0; 
  if file1Open = TRUE then begin 
    dataLen := 0; 
 
    status = BTRVID( 
                B_CLOSE, 
                posBlock1, 
                dataBuffer, 
                dataLen, 
                keyBuf1[1], 
                keyNum, 
                client); 
 
    writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample.btr) = ' + 
intToStr(status)); 
  end; 
 
  if file2Open = TRUE then begin 
    dataLen := 0; 
 
    status = BTRVID( 
                B_CLOSE, 
                posBlock2, 
                dataBuffer, 
                dataLen, 
                keyBuf2[1], 
                keyNum, 
                client); 
 
    writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample2.btr) = ' + 
intToStr(status)); 
  end; 
 
  { リソース解放 } 
  dataLen := 0; 
  status := BTRVID(B_STOP, posBlock1, DataBuffer, 
               dataLen, keyBuf1[1], 0, client); 
  WritelnLB(ListBox1, 'Btrieve B_STOP status = ' + intToStr(status) ); 
 
end; 
 
procedure TForm1.ExitButtonClick(Sender:TObject); 
begin 
  Close; 
end; 
 
procedure TForm1.RunButtonClick(Sender:TObject); 
begin 
  SetCursor(WaitCursor); 
  RunTest; 
  SetCursor(ArrowCursor); 
end; 
 
end. 

サンプル プログラムのコンパイル、リンク、実行

Delphi 3、4、5 では、サンプル プログラムのコンパイル、リンク、実行を、以下の方法で行います。

  1. ファイル]メニューの[プロジェクトを開く]を選択し、¥Intf¥Delphi ディレクトリの Btr32.dpr プロジェクト ファイルを開きます。
  2. BtrSam32.pas ファイルで、Sample.btr および Sample2.btr のパスを適切なものに変更します。
  3. ツール バーの[実行]ボタンをクリックします。
    サンプル プログラムがコンパイル、リンク、実行されます。
  4. [Btrieve Sample Application]ウィンドウの[Run Test]ボタンをクリックします。
    サンプル プログラムが、Btrieve エンジンに対してテストを行います。

Delphi 1 では、サンプル プログラムのコンパイル、リンク、実行を、以下の方法で行います。

  1. File]メニューの[Open Project]を選択し、¥Intf¥Delphi ディレクトリに Btr16.dpr プロジェクト ファイルを開きます。
  2. BtrSam16.pas ファイルで、Sample.btr および Sample2.btr のパスを適切なものに変更します。
  3. ツール バーの[実行]ボタンをクリックします。
    サンプル プログラムがコンパイル、リンク、実行されます。
  4. [Btrieve Sample Application]ウィンドウの[Run Test]ボタンをクリックします。
    プログラムが、Btrieve エンジンに対してテストを行います。

COBOL (Btrieve API 用の言語インターフェイス)

Pascal (Btrieve API 用の言語インターフェイス)