- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


3105:Synchronize a DLL to an Open Dataset

KEYWORDS: Synchronize DLL Dataset DbiSetToCursor DbiSetToCursor AREA: Database

Synchronize a DLL to an Open Dataset

This document demonstrates how to use Object Pascal to link a
DLL dynamically, on-the-fly, into an active Database, thus, giving the
Developer the ability to 'Modularize' features. (Whether at Run-Time or
Design-Time)

The technique of linking a DLL Dynamically into an EXE is useful in
many cases.  Examples include, an Accounting package which offers several
'plug-in' modules (A/R, A/P, General Ledger, etc.) or a Point of Sale
package with Current Stock, FIFO/LIFO Ordering, Vendor Tracking, etc.,
modules.

This TI will provide a solid example of how to do this with one
dll, 'Editdll.dll', but will give the Developer the essentials leading
to extensive modularation in projects.

Prerequisites:
--------------
Familiarity with the TTable component, DLL usage, BDE API, and
BDE hCursor knowledge. *WIN API for Dynamical loading of any DLL's.


                          SAMPLE APPLICATION

The following form, EditForm, is based on the COUNTRY table in the
DBDEMO's directory.  When the user presses the 'Edit' button or
double-clicks a record (row), a dialog box appears, from 'EditDll.dll',
displaying record specific information. At this point, the DLL has
synchronized itself not only with the dataset (& session) but also with
the current record. This mean's, the user can now modify the same data
EditForm is viewing! So, with no ado, let's delve into the sample code.
(For best results, simply cut and paste into appropriate files)

>Main Form Project<
-------------------

{ MAINDB.DPR }
program maindb;

uses
  Forms,
  mainform in 'mainform.pas' {DBMainForm};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TDBMainForm, DBMainForm);
  Application.Run;
end.

>>

{ MAINFORM.PAS }
unit mainform;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, DBGrids, DBTables, Grids, ExtCtrls,
  BDE;

type
  TDBMainForm = class(TForm)
    Table1Name: TStringField;
    Table1Capital: TStringField;
    Table1Continent: TStringField;
    Table1Area: TFloatField;
    Table1Population: TFloatField;
    DBGrid1: TDBGrid;
    DBNavigator: TDBNavigator;
    Panel1: TPanel;
    DataSource1: TDataSource;
    Panel2: TPanel;
    Table1: TTable;
    EditButton: TButton;
    procedure FormCreate(Sender: TObject);
    procedure EditButtonClick(Sender: TObject);
    procedure DBGrid1DblClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  DBMainForm: TDBMainForm;

implementation

{$R *.DFM}

procedure TDBMainForm.FormCreate(Sender: TObject);
begin
  Table1.Open;
end;

// {NOTES: DBHandle is a Handle to the Database & DSHandle is a cursor
//  to the record being viewed. Also, if the purpose is to dynamically
//  load a DLL at run-time, use the LoadLibrary, GetProcAddress, and
//  FreeLibrary API calls in place of the implicit load calls at startup.
//  An Example of the APIcalling convention is: }
// Type
//  {For GetProcAddress}
//  BDEDataSync =
//    function(const DBHandle: HDBIDB; const DSHandle: HDBICur): Boolean;
//             stdcall;
//  {For the trapping of DLL load error's}
//  EDLLLoadError = class(Exception);
// var h: hwnd;
//     p: BDEDataSync;
//     LastError: DWord;
// begin
// UpdateCursorPos;
// Try
//   h := loadLibrary('EDITDLL.DLL');
//   {NOTE to Delphi 1.0 users: Whereas Win32 LoadLibrary returns a
//    NULL if the DLL load was unsuccessful, thus requiring a call to
//    GetLastError to find the error, Win16 LoadLibrary returns
//    an error value (less than HINSTANCE_ERROR) which can be checked
//    in the Win16API SDK as to the reason for the failure.}
//   if h = 0 then begin
//	LastError := GetLastError;
//	Raise EDLLLoadError.create(IntToStr(LastError) +
//                                 ': Unable to load DLL');
// 	end;
//   try
//      p := getProcAddress(h, 'EditData');
//      if p(DBHandle, Handle) then Resync([]);
//   finally
//      freeLibrary(h);
//   end;
// Except
//   On E: EDLLLoadError do
//     MessageDLG(E.Message, mtInformation, [mbOk],0);
// end;
// end;
// {or}
function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
   Boolean;  stdcall external 'EDITDLL.DLL' name 'EditData';

procedure TDBMainForm.EditButtonClick(Sender: TObject);
begin
  with Table1 do
  begin
    UpdateCursorPos;
// Call the EditData Procedure from EditDll.dll.
    if EditData(DBHandle, Handle) then Resync([]);
  end;
end;

procedure TDBMainForm.DBGrid1DblClick(Sender: TObject);
begin
  EditButton.Click;
end;

end.

>>

>EDIT DLL PROJECT<
------------------

{ EDITDLL.DPR }
library editdll;

uses
  SysUtils,
  Classes,
  editform in 'editform.pas' {DBEditForm};

exports
  EditData;

begin
end.

>>

{ EDITFORM.PAS }
unit editform;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, DBTables, Mask, ExtCtrls, BDE;

type
  TTableClone = class;

  TDBEditForm = class(TForm)
    ScrollBox: TScrollBox;
    Label1: TLabel;
    EditName: TDBEdit;
    Label2: TLabel;
    EditCapital: TDBEdit;
    Label3: TLabel;
    EditContinent: TDBEdit;
    Label4: TLabel;
    EditArea: TDBEdit;
    Label5: TLabel;
    EditPopulation: TDBEdit;
    DBNavigator: TDBNavigator;
    Panel1: TPanel;
    DataSource1: TDataSource;
    Panel2: TPanel;
    Database1: TDatabase;
    OKButton: TButton;
  private
    TableClone: TTableClone;
  end;

{ TTableClone }

  TTableClone = class(TTable)
  private
    SrcHandle: HDBICur;
  protected
    function CreateHandle: HDBICur; override;
  public
    procedure OpenClone(ASrcHandle: HDBICur);
  end;

function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
                   Boolean; stdcall;

var
  DBEditForm: TDBEditForm;

implementation

{$R *.DFM}

{ Exports }

function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
                  Boolean; stdcall;
var
  DBEditForm: TDBEditForm;
begin
  DBEditForm := TDBEditForm.Create(Application);
  with DBEditForm do
  try
// Set the handle of the Database1 to that of the currently opened database
    Database1.Handle := DBHandle;
    TableClone := TTableClone.Create(DBEditForm);
    try
      TableClone.DatabaseName := 'DB1';
      DataSource1.DataSet := TableClone;
      TableClone.OpenClone(DSHandle);
      Result := (ShowModal = mrOK);
      if Result then
      begin
        TableClone.UpdateCursorPos;
        DbiSetToCursor(DSHandle, TableClone.Handle);
      end;
    finally
      TableClone.Free;
    end;
  finally
    Free;
  end;
end;

{ TTableClone }

procedure TTableClone.OpenClone(ASrcHandle: HDBICur);
begin
  SrcHandle := ASrcHandle;
  Open;
  DbiSetToCursor(Handle, SrcHandle);
  Resync([]);
end;

function TTableClone.CreateHandle: HDBICur;
begin
   Check(DbiCloneCursor(SrcHandle, False, False, Result));
end;

end.

>>

{ EDITFORM.DFM }
object DBEditForm: TDBEditForm
  Left = 201
  Top = 118
  Width = 354
  Height = 289
  ActiveControl = Panel1
  Caption = 'DBEditForm'
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Position = poScreenCenter
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 346
    Height = 41
    Align = alTop
    TabOrder = 0
    object DBNavigator: TDBNavigator
      Left = 8
      Top = 8
      Width = 240
      Height = 25
      DataSource = DataSource1
      Ctl3D = False
      ParentCtl3D = False
      TabOrder = 0
    end
    object OKButton: TButton
      Left = 260
      Top = 8
      Width = 75
      Height = 25
      Caption = 'OK'
      Default = True
      ModalResult = 1
      TabOrder = 1
    end
  end
  object Panel2: TPanel
    Left = 0
    Top = 41
    Width = 346
    Height = 221
    Align = alClient
    BevelInner = bvLowered
    BorderWidth = 4
    Caption = 'Panel2'
    TabOrder = 1
    object ScrollBox: TScrollBox
      Left = 6
      Top = 6
      Width = 334
      Height = 209
      HorzScrollBar.Margin = 6
      HorzScrollBar.Range = 147
      VertScrollBar.Margin = 6
      VertScrollBar.Range = 198
      Align = alClient
      AutoScroll = False
      BorderStyle = bsNone
      TabOrder = 0
      object Label1: TLabel
        Left = 6
        Top = 6
        Width = 28
        Height = 13
        Caption = 'Name'
        FocusControl = EditName
      end
      object Label2: TLabel
        Left = 6
        Top = 44
        Width = 32
        Height = 13
        Caption = 'Capital'
        FocusControl = EditCapital
      end
      object Label3: TLabel
        Left = 6
        Top = 82
        Width = 45
        Height = 13
        Caption = 'Continent'
        FocusControl = EditContinent
      end
      object Label4: TLabel
        Left = 6
        Top = 120
        Width = 22
        Height = 13
        Caption = 'Area'
        FocusControl = EditArea
      end
      object Label5: TLabel
        Left = 6
        Top = 158
        Width = 50
        Height = 13
        Caption = 'Population'
        FocusControl = EditPopulation
      end
      object EditName: TDBEdit
        Left = 6
        Top = 21
        Width = 135
        Height = 21
        DataField = 'Name'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 0
      end
      object EditCapital: TDBEdit
        Left = 6
        Top = 59
        Width = 135
        Height = 21
        DataField = 'Capital'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 1
      end
      object EditContinent: TDBEdit
        Left = 6
        Top = 97
        Width = 135
        Height = 21
        DataField = 'Continent'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 2
      end
      object EditArea: TDBEdit
        Left = 6
        Top = 135
        Width = 65
        Height = 21
        DataField = 'Area'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 3
      end
      object EditPopulation: TDBEdit
        Left = 6
        Top = 173
        Width = 65
        Height = 21
        DataField = 'Population'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 4
      end
    end
  end
  object DataSource1: TDataSource
    Left = 95
    Top = 177
  end
  object Database1: TDatabase
    DatabaseName = 'DB1'
    LoginPrompt = False
    SessionName = 'Default'
    Left = 128
    Top = 176
  end
end

>>

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



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