Reputation: 51
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
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
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
Reputation: 6848
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