- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


3103:BDE Callbacks to Provide Status on Operations

KEYWORDS: BDE Callbacks DbiGetCallBack AREA: Database Programming

This TI demonstrates using a BDE DbiCallBack function
to drive a progress bar during a lengthy batch move
operation under Delphi 2.01.

Additional documentation on BDE function calls can be found
in the file BDE32.HLP (located in the directory where the
32 bit IDAPI is installed).

When you install a callback function to the BDE, the BDE
will "call back" to a function in your application, letting
your application know when certain events take place, and in
some cases, allow your application to return information
back to the BDE.

The BDE defines several callback types that may be installed:

           during large batch operations.
           requests a response from the caller.


This TI details installing a cbGENPROGRESS callback to drive
a progress bar in your application.


To do this, first call the DbiGetCallBack() function to retrieve
the handle to any callback that might already be installed
(and it's parameters), and save this information to a data
structure.  Then install your callback, replacing any previous
callback installed.

You will need to pass a pointer the data structure containing
the information to the previously installed callback to the BDE
when you install your callback, so when your callback function
is executed, you can call the original callback
(if one is installed).

The BDE will call back to your application every so often,
reporting either a text message containing the number of records
it has processed or how far the batch move has progressed,
expressed as an integer percentage. Your callback should be able
to deal with either of these situations. If the percentage field
of the callback structure is greater than -1, then the percentage
is correct and you are free to update your progress bar. If the
percentage reported is less than zero, the callback has received
a text message in the szTMsg field containing a message that
includes the number of records processed. In this case, you will
need to parse the text message and convert the remaining string
to an integer, then calculate the percentage done and update
the progress bar.

Finally, when your batch move is complete, you will need to
un-register your callback, and reinstall the previous callback
function (if it exists).


The following code example is based on a form containing two tables,
a batch move component, a progress bar, and a button.

----- Code Follows ---------

unit Testbc1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables, ComCtrls;

type
  TForm1 = class(TForm)
    Table1: TTable;
    BatchMove1: TBatchMove;
    Table2: TTable;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Bde; {Dbi Types and Procs are located here}

{$R *.DFM}

{data structure  type to save previous callback info}
type TDbiCbInfo = record
  ecbType     : CBType;
  iClientData : longint;
  DataBuffLn  : word;
  DataBuff    : pCBPROGRESSDesc;
  DbiCbFn     : pointer;
end;
type PDbiCbInfo = ^TDbiCbInfo;


{Our callback  function}
function DbiCbFn(ecbType     : CBType;
                 iClientData : Longint;
                 CbInfo      : pointer): CBRType stdcall;
var
  s : string;
begin
 {Check to see if the callback type is what we expect}
  if ecbType = cbGENPROGRESS then begin
   {if iPercentDone is less that zero then extract the number}
   {of records processed from szMsg parameter}
    if pCBPROGRESSDesc(cbInfo).iPercentDone < 0 then begin
      s := pCBPROGRESSDesc(cbInfo).szMsg;
      Delete(s, 1, Pos(': ', s) + 1);
     {Calculate percentage done and set the progress bar}
      Form1.ProgressBar1.Position :=
        Round((StrToInt(s) / Form1.Table1.RecordCount) * 100);
    end else
    begin
     {Set the progress bar}
      Form1.ProgressBar1.Position :=
        pCBPROGRESSDesc(cbInfo).iPercentDone;
    end;
  end;
 {was there a previous callback registered}
 {if so - call it and return}
  if PDbiCbInfo(iClientData)^.DbiCbFn <> nil then
    DbiCbFn :=
      pfDBICallBack(PDbiCbInfo(iClientData)^.DbiCbFn)
        (ecbType,
         PDbiCbInfo(iClientData)^.iClientData,
         cbInfo) else
    DbiCbFn := cbrCONTINUE;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  CbDataBuff: CBPROGRESSDesc; {DBi Structure}
  OldDbiCbInfo : TDbiCbInfo;  {data structure to save previous
                               callback info}
begin
 {Make sure the table we are moving from is open}
  Table1.Open;
 {make sure the table we are batch moving to is closed}
  Table2.Close;
 {get info about any installed callback}
  DbiGetCallBack(Table2.Handle,
                 cbGENPROGRESS,
                 @OldDbiCbInfo.iClientData,
                 @OldDbiCbInfo.DataBuffLn,
                 @OldDbiCbInfo.DataBuff,
                 pfDBICallBack(OldDbiCbInfo.DbiCbFn));
 {register our callback}
  DbiRegisterCallBack(Table2.Handle,
                      cbGENPROGRESS,
                      longint(@OldDbiCbInfo),
                      SizeOf(cbDataBuff),
                      @cbDataBuff,
                      @DbiCbFn);

  Form1.ProgressBar1.Position := 0;
  BatchMove1.Execute;

 {if a previous callback exists - reinstall it else}
 {unregister our callback}
  if OldDbiCbInfo.DbiCbFn <> nil then
    DbiRegisterCallBack(Table2.Handle,
                        cbGENPROGRESS,
                        OldDbiCbInfo.iClientData,
                        OldDbiCbInfo.DataBuffLn,
                        OldDbiCbInfo.DataBuff,
                        OldDbiCbInfo.DbiCbFn) else
    DbiRegisterCallBack(Table2.Handle,
                        cbGENPROGRESS,
                        longint(@OldDbiCbInfo),
                        SizeOf(cbDataBuff),
                        @cbDataBuff,
                        nil);

 {lets show our success!}
  Table2.Open;

end;

end.

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



- - * - Anastasija aka WhiteUnicorn - * - - LJLiveJournal
PFPhotoFile