dcs
dcs

Reputation: 51

Stack Overflow error on adding component to form

Hi I have just completed a component which implements a Table search on typing in an edit box and showing the results in a drop down dbCtrlGrid. It compiles and installs without any problem. But when placed on a form Delphi (7) I get a Stack Overflow save your work and restart Delphi. I cannot debug it as it is not on the form so can anyone help please?

unit QueryPnl;

interface

uses WinTypes, WinProcs, Messages, SysUtils, Classes, Controls,
Forms, Graphics, Extctrls, Eedit, Stdctrls, ABSMain,
Db, DBCtrls, EDBEdit, dbcgrids;

type
  TQueryPanel = class(TPanel)
   private
    Addressmem : TDBMemo;
    Display : TDBCtrlGrid;
    DsQ1 : TDataSource;
    Head : TLabel;
    FDbase : TABSDatabase;
    FTableName : string;
    FOnInTextChange : TNotifyEvent;
    procedure AutoInitialize;
    procedure AutoDestroy;

   protected
    InText : TEedit;
    NmText : TEDBEdit;
    NumText : TEDBEdit;
    Q1 : TABSQuery;
    procedure InTextChange(Sender : TObject); overload;
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure Click; override;
    procedure KeyPress(var Key : Char); override;
    procedure Loaded; override;
    procedure Paint; override;
    function GetFDbase : TABSDatabase;
    procedure SetFDbase(Value : TABSDatabase);
    function GetFTableName : string;
    procedure SetFTableName(Value : string);
    
   public
    procedure InTextChange;overload;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

   published
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property DBase : TABSDatabase read FDBase write SetFDBase;
    property TableName : String read FTableName write SetFTableName;
    property OnInTextChange : TNotifyEvent read FOnInTextChange write FOnInTextChange;
    
  end;
  
procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Data Controls', [TQueryPanel]);
end;

procedure TQueryPanel.AutoInitialize;
begin
  Addressmem.Parent := Display;
  with Addressmem do
    begin
      Left := 2;
      Top := 50;
      Width := 115;
      Height := 50;
      DataField := 'Address';
      TabOrder := 1;
    end;
  Display.Parent := Self;
  with Display do
    begin
      DataSource:=DsQ1;
      Left := 0;
      Top := 54;
      Width := 138;
      Height := 315;
      Color := $00E8DBCE;
      PanelHeight := 105;
      PanelWidth := 121;
      ParentColor := False;
      TabOrder := 2;
    end;
  DsQ1.DataSet:=Q1;
  Head.Parent := Self;
  with Head do
    begin
      Left := 1;
      Top := 1;
      Width := 136;
      Height := 13;
      Align := alTop;
      Alignment := taCenter;
      Caption := 'Quick Name Search';
      Font.Charset := DEFAULT_CHARSET;
      Font.Color := clRed;
      Font.Height := -12;
      Font.Name := 'MS Sans Serif';
      Font.Style := [fsBold];
      ParentFont := False;
    end;
  InText.Parent := Self;
  with InText do
    begin
      Left := 0;
      Top := 25;
      Width := 121;
      Height := 21;
      TabOrder := 0;
      OnChange := InTextChange;
      UpCaseFirst := True;
      ColorOnFocus := clYellow;
    end;
  NmText.Parent := Display;
  with NmText do
    begin
      Left := 2;
      Top := 8;
      Width := 115;
      Height := 21;
      DataField := 'Name';
      Font.Charset := DEFAULT_CHARSET;
      Font.Color := clWindowText;
      Font.Height := -11;
      Font.Name := 'MS Sans Serif';
      Font.Style := [fsBold];
      ParentFont := False;
      TabOrder := 0;
    end;
  NumText.Parent := Display;
  with NumText do
    begin
      Left := 1;
      Top := 29;
      Width := 115;
      Height := 21;
      DataField := 'Number';
      Font.Style := [fsBold];
      TabOrder := 2;
    end;
  Q1.DatabaseName:=FDBase.Name;
  Q1.RequestLive:=True;
end;

procedure TQueryPanel.AutoDestroy;
begin
  Addressmem.Free;
  Display.Free;
  DsQ1.Free;
  Head.Free;
  InText.Free;
  NmText.Free;
  NumText.Free;
  Q1.Free;
end;

procedure TQueryPanel.DoEnter;
begin
  inherited DoEnter;
  Height := 370;
end;

procedure TQueryPanel.DoExit;
begin
  inherited DoExit;
  Height := 55;
end;

function TQueryPanel.GetFDbase : TABSDatabase;
begin
Result := FDbase;
end;

procedure TQueryPanel.SetFDBase(Value : TABSDatabase);
begin
  FDBase := Value;
  // Other code to do when selecting the database
end;

function TQueryPanel.GetFTableName : string;
begin
  Result := FTableName;
end;

procedure TQueryPanel.SetFTableName(Value : String);
begin
  FTableName := Value;
  // Other code to do when selecting the table
end;

procedure TQueryPanel.InTextChange(Sender : TObject);
begin
  if Assigned(FOnInTextChange) then
  FOnInTextChange(Sender);
  Q1.Close;
  Q1.SQL.Text:='select * from '+FTableName+' where Name like :nem';
  Q1.ParamByName('nem').asString:=InText.Text;
  Q1.Open;
end;

procedure TQueryPanel.Click;
begin
  inherited Click;
end;

procedure TQueryPanel.KeyPress(var Key : Char);
const
  TabKey = Char(VK_TAB);
  EnterKey = Char(VK_RETURN);
begin
  inherited KeyPress(Key);
end;

constructor TQueryPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Addressmem := TDBMemo.Create(Self);
  Display := TDBCtrlGrid.Create(Self);
  DsQ1 := TDataSource.Create(Self);
  InText := TEedit.Create(Self);
  Head := TLabel.Create(Self);
  NmText := TEDBEdit.Create(Self);
  NumText := TEDBEdit.Create(Self);
  Q1 := TABSQuery.Create(Self);
  AutoInitialize;
end;

destructor TQueryPanel.Destroy;
begin
  inherited Destroy;
end;

procedure TQueryPanel.InTextChange;
begin
//
end;

procedure TQueryPanel.Loaded;
begin
  inherited Loaded;
end;

procedure TQueryPanel.Paint;
begin
  inherited Paint;
end;
end.

Upvotes: 1

Views: 401

Answers (3)

dcs
dcs

Reputation: 51

I tracke the error - it was in the TQueryPanel.AutoInitialize; I guess that the line

Q1.DatabaseName:=FDBase.Name;

was in the wrong place so I put in

procedure TQueryPanel.SetDbase(Value : TABSDatabase);
begin
  FDbase:= Value;
  Q1.DatabaseName:=FDBase.DatabaseName;
end;

and it works fine now.Thank you everyone for your help and suggestions

Actually it doesn't. The first panel of the DBCtrlGrid is fine but apparently you have to have the DBCtrlGrid.Panel as parent which is reserved and cannot be accessed. Shame it seemed an ideal solution in a limited space.

Upvotes: 1

fpiette
fpiette

Reputation: 12292

In the private section, add this:

   FDBase : TABSDataBase;
   FTableName : String;

In the published section, add:

   property DBase : TABSDataBase read FDBase write SetDBase;
   property TableName : String read FTableName write SetTableName;

In the implementation, write:

procedure TQueryPanel.SetDBase(Value : TABSDatabase);
begin
  FDBase := Value;
  // Other code to do when selecting the database
end;

procedure TQueryPanel.SetTableName(Value : String);
begin
  FTableName := Value;
  // Other code to do when selecting the table
end;

Where I put comments "Other code...", if there is nothing to do, you don't need the setter at all.

Please keep attention that fields begin by letter F and properties don't.

Upvotes: 1

Many times, StackOverflow errors are due to an infinite recursion.
I think the code of these two procedures causes that:

procedure SetDBase(Value : TABSDatabase);
procedure SetTableName(Value : String);

Use Field like FDBase and FTableName to store the values (for example).
The 2 methods are causing the Set method to be called again infinitely.

Upvotes: 3

Related Questions