Technical Information Database TI1327D.txt - BDE Callbacks to Provide Status on Operations Category :Database Programming Platform :All-32Bit Product :All32Bit, Description: This TI demonstrates using a BDE DbiCallBack function to drive a progress bar during a lengthy batch move operation under the 32-bit versions of Delphi. 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. Reference: 3/30/99 11:26:29 AM
Last Modified: 01-SEP-99