Hallo,
Gestern habe ich sowohl meine eigenen Datensatzmaske als auch die eines
DP Users, welche er mir freundlicherweise zur Verfügung gestellt hat, getesetet.
Dabei erhalte ich eine EAccessviolation, wobei das Programm an der im Kommentar beschribenen Stelle anhält. Die Eigenschaft TWinControl.Parent existiert aber definitiv laut Delphi Hilfe.
Wenn ich deshalb debugge, um die Ursache für die
Exception zu finden, erhalte ich diese an jener Stelle, wo die Eigenschaft DataSoruce zugewiesen wird. In der Methode SetDataSource, wie im Listing unten zu sehen.
Daraufhin habe ich meine eigenen Version der Datensatzmaske getestet und erhalte ebenfalls eine EAccessViolation an jener Stelle, wo
Delphi-Quellcode:
function TCR_DB_Editor.GetRealParent : TWinControl;
var MYDBCtrlGrid : TMYDBCtrlGrid;
tmp :TWinControl;
Flag : boolean;
begin
Flag := false;
tmp := self.Parent;
result := tmp;
//showmessage(result.Name);
while ( tmp.Parent <>
nil )
AND (Flag =false)
do //Hier hält das Programm an und wirft die
begin //Exception aus
if Pos('
dbctrl', lowercase(tmp.ClassName )) > 0
then
begin
MYDBCtrlGrid := TMYDBCtrlGrid(tmp);
result := MYDBCtrlGrid.Panel;
Flag := true;
end;
tmp := tmp.Parent;
end;
end;
procedure TCR_DB_Editor.SeTDataSource(Value: TDataSource);
begin
if value <>
nil then
begin
FDataLink.DataSource := Value;
//Hier hält der Debugger an und wirft die Exception aus
end;
end;
// Hier mein eigener Entwurf:
procedure TDBInputMask.SetDataSource(ADataSource: TDataSource);
var
idx: Integer;
obj: TObject;
edit: TDBInputLine;
chbox: TDBCheckBox;
cobox: TDBComboBox;
clbox: TDBLookUpComboBox;
rdgrp: TDBRadioGroup;
imemo: TMemo;
irich: TRichEdit;
image: TImage;
begin
if FEdits.Count > 0
then FEdits.Clear;
if (ADataSource<>
nil)
and (FDataSource<>ADataSource)
then
begin
//Hier erhalte ich die Exception, aber hier EAbstractError
FDataSource := ADataSource;
FDataSource.DataSet.GetFieldNames(FEdits);
FCount := FDataSource.DataSet.FieldCount;
for idx := 0
to FCount - 1
do
begin
SetLabels(idx, TDBText.Create(self));
//SetInputs(idx, TDBEdit.Create(self));
obj := FInputs[idx];
if obj
is TDBInputLine
then
begin
TDBInputLine(FInputs[idx]).DataSource := FDataSource;
TDBInputLine(FInputs[idx]).DataField := FEdits[idx];
end;
if obj
is TDBCheckBox
then
begin
TDBCheckBox(FInputs[idx]).DataSource := FDataSource;
TDBCheckBox(FInputs[idx]).DataField := FEdits[idx];
end;
end;
end;
procedure Tdbform.OpenDataBase;
begin
if dlgOpen.Execute
then
begin
FFilename := dlgOpen.Filename;
ClientDataSet.LoadFromFile(FFilename);
ClientDataSet.Active := true;
//CreateMask;
FInputMask := TDBInputMask.Create(self);
FInputMask.Top := 312;
FInputMask.Left := 8;
FInputMask.Width := 425;
FInputMask.Height := 145;
FInputMask.DataSource := DataSource;
//Hier erhalte ich EAbstractError;
FInputMask.Parent := self;
end;
end;
Da nund die
Exception in beiden Versionen auftritt, muss ja ein generelles Problem vorliegen. Möglicherweise ist die Methode zur Zuweisung der Datenquelle falsch. Aber wie wird ed dann richtig gemacht?
Sowohl FDataLink.DataSource als auch FDataSource sind doch letztlich nix anderes als Zeiger auf die Datenquelle. Deren Adresse hole ich von außen. Aber warum dann die
Exception?
Gibt es zur Lösung des Problems ein Standardverfahren, das diese
Exception vermeidet?
Bin mit meinem Latein am Ende. Warum funktioniert die Zuweisung nicht. Ich verwende für die Entwicklung Turbo Delphi Exploerer, die kostenlose Version ohne Updates.
In meiner Version erhalte ich nicht EAccessviolation, sondern EAbstractError. Deshalb noch die Definition meiner Basisklasse für meine Eingabemaske:
Delphi-Quellcode:
TCustomInputMask = class(TScrollBox)
private
{ Private-Deklarationen }
protected
{ Protected-Deklarationen }
FCount: Integer;
FInputs: TObjectList;
FLabels: TObjectList;
FMasks: TStrings;
public
{ Public-Deklarationen }
procedure CreateLabel(ACaption: TCaption); virtual;
procedure CreateEdit(AEditMask: String); virtual;
procedure CreateCheckBox(ACaption: String); virtual;
procedure CreateComboBox; virtual;
procedure CreateMask; virtual;
procedure CreateMemo; virtual;
procedure CreateRadioGroup(ACaptions: TStrings); virtual;
procedure CreateRichEdit; virtual;
end;
//Hier noch die Definition meiner eigenen Datensatzmaske.
TDBInputMask = class(TCustomInputMask)
//diese Klasse für Datenbankmasken verwenden
//Feldanzahl, damit Anzahl Edits wird durch die Datenbank bestimmt
private
FDataSource: TDataSource;
FEdits: TStrings; //Feldnamen nach Anzeigereihenfolge
function GetInputs(Index: Integer): TObject;
function GetLabels(Index: Integer): TDBText;
function GetMasks(Index: Integer): String;
function GetDataSource: TDataSource;
procedure SetCount(ACount: Integer);
procedure SetInputs(Index: Integer; AInput: TObject);
procedure SetLabels(Index: Integer; ALabel: TDBText);
procedure SetMasks(Index: Integer; AMask: String);
procedure SetDataSource(ADataSource: TDataSource);
public
constructor Create(AOwner: TComponent);
procedure CreateLabel(ACaption: TCaption); override;
procedure CreateLabelCaptions(ACaptions: TStrings);
procedure CreateEdit(AEditMask: String); override;
procedure CreateCheckBox(ACaption: String); override;
procedure CreateComboBox; override;
procedure CreateMask; override;
procedure CreateMemo; override;
procedure CreateRadioGroup(ACaptions: TStrings); override;
procedure CreateRichEdit; override;
destructor Destroy; override;
property Count: Integer read FCount write SetCount;
property DataSource: TDataSource read GetDataSource write SetDataSource;
property Inputs[Index: Integer]: TObject read GetInputs write SetInputs;
property Masks[Index: Integer]: String read GetMasks write SetMasks; default;
end;
Die virtuellen Methoden waren vorher als virtual; abstract; deklariert. Wegen der EAbstractError
Exception habe ich diese Methoden virtual; definiert und im Implementationsteil stehen leere Methodenrümpfe. Dennoch werde ich die
Exception nicht los.
Weil aber bei der Einen Version die
Exception, wenn auch EAccessviolation, statt EAbstractError, wie bei der Anderen Version während der Zuweisung der Datenquelle ausgelöst wird, habe ich die Frage in diesen Thread gepackt. Denn ich vermute, das die Fehlerursache irgendwo im Softwaredesign liegt. Egal, welche
Exception letzlich ausgelöst wird.
Braucht Ihr, um helfen zu können noch mehr Quelltext? Dann teilt mir das bitte hier mit und ich werde die Quellen liefern. Die Datensatzmaske ist nichts sonderlich geheimes.