I'm facing the Abstract error
when i Drag and Dropping a TPanel child in a TImage
component.
Basically i have a Scrollbox
contain a TPanelCargaRele
list and when i drag and drop this panel to the Trash i get the Abstract error
.
I've debugged my code, but this problem happens in end;
line of the procedure and I couldn't see where the problem is.
Here is my code below:
procedure TFormCenas.imgLixeiraDragDrop(Sender, Source: TObject; X,
Y: Integer);
function getFuncaoCena(p: Pointer): TFuncaoCena;
begin
if Assigned(p) then
begin
if ((TObject(p).ClassType = TPanelCargaRele) or
(TObject(p).ClassType = TPanelCargaDimmer) or
(TObject(p).ClassType = TPanelDefinicaoCargaAV) or
(TObject(p).ClassType = TPanelDefinicaoFuncaoSomfy)) and
(TObject(p).InheritsFrom(TWinControl))
then
begin
if (TObject(p).ClassType = TPanelCargaRele) then
Result := TPanelCargaRele(p).funcaoCena
else if (TObject(p).ClassType = TPanelCargaDimmer) then
Result := TPanelCargaDimmer(p).funcaoCena
else if (TObject(p).ClassType = TPanelDefinicaoCargaAV) then
Result := TPanelDefinicaoCargaAV(p).funcaoCena
else if (TObject(p).ClassType = TPanelDefinicaoFuncaoSomfy) then
Result := TPanelDefinicaoFuncaoSomfy(p).funcaoCena;
end
else if TObject(p).InheritsFrom(TWinControl) then
begin
Result := getFuncaoCena(TWinControl(p).Parent);
end
else
Result := nil;
end
else
Result := nil;
end;
function getObject(p: Pointer): Pointer;
begin
if Assigned(p) then
begin
if ((TObject(p).ClassType = TPanelCargaRele) or
(TObject(p).ClassType = TPanelCargaDimmer) or
(TObject(p).ClassType = TPanelDefinicaoCargaAV) or
(TObject(p).ClassType = TPanelDefinicaoFuncaoSomfy)) and
(TObject(p).InheritsFrom(TWinControl))
then
begin
Result := p;
end
else if TObject(p).InheritsFrom(TWinControl) then
begin
Result := getObject(TWinControl(p).Parent);
end
else
Result := nil;
end
else
Result := nil;
end;
var
funcaoCena: TFuncaoCena;
panel: Pointer;
begin
inherited;
funcaoCena := getFuncaoCena(Source);
if Assigned(funcaoCena) then
begin
listaFuncoesTemp.Remove(funcaoCena);
panel := getObject(Source);
if Assigned(panel) then
begin
TWinControl(panel).Visible := False;
FreeAndNil(TWinControl(panel));
end;
end;
end; //the error happens here..
Here is the constructor of the TPanelCargaRele
:
TPanelCargaRele = class(TPanel)
.
.
.
constructor TPanelCargaRele.Create(AOwner: TComponent; aIndice: Integer; item: Pointer);
begin
inherited Create(AOwner);
Parent := TWinControl(AOwner);
//ReleRadio0
fReleRadio := TRadioGroup.Create(Self);
fPanelChecked := TPanel.Create(Self);
fBotaoChecked := TPNGButtonSimple.Create(Self);
fBevelRodape := TBevel.Create(Self);
fEditDelay := TEdit.Create(Self);
//Panel1
Self.Left := 0;
Self.Width := 400;
Self.Height := 40;
Self.Top := aIndice * (Self.Height + 5);
Self.Align := alTop;
Self.BevelInner := bvNone;
Self.BevelOuter := bvNone;
Self.Color := clWhite;
Self.TabOrder := 0;
Self.DragMode := dmAutomatic;
fPanelChecked.Parent := Self;
fPanelChecked.Top := 12;
fPanelChecked.Left := 30;
fPanelChecked.Width := 100;
fPanelChecked.Alignment := taLeftJustify;
fPanelChecked.Height := 13;
fPanelChecked.ParentColor := True;
fPanelChecked.BevelOuter := bvNone;
fPanelChecked.BevelInner := bvNone;
fPanelChecked.Font.Size := 8;
fPanelChecked.DragMode := dmAutomatic;
fPanelChecked.OnDblClick := OnDblClickPanelNome;
// fPanelChecked.OnDblClick := OnDblClickPanelNome;
//
fBotaoChecked.Parent := Self;
fBotaoChecked.Left := 5;
fBotaoChecked.Top := 7;
fBotaoChecked.Width := 20;
fBotaoChecked.ButtonStyle := pbsNoFrame;
fBotaoChecked.ButtonLayout:= pbsImageCenter;
fBotaoChecked.ImageNormal.LoadFromResourceName(HInstance,'CARGAS_CHECK_VAZIO');
fBotaoChecked.ImageDown.LoadFromResourceName(HInstance,'CARGAS_CHECK_AZUL');
//ReleRadio0
fReleRadio.Parent := Self;
fReleRadio.Left := 130;
fReleRadio.Top := 2;
fReleRadio.Width := 260;
fReleRadio.Height := 30;
fReleRadio.ParentColor := True;
fReleRadio.ParentFont := False;
fReleRadio.TabOrder := 1;
fReleRadio.TabStop := True;
fReleRadio.Font.Size := 7;
fReleRadio.OnClick := OnClickRadioRele;
fReleRadio.Items.Clear;
fReleRadio.Items.Add(LB_CENA_RELE_ACAO_DESLIGAR);
fReleRadio.Items.Add(LB_CENA_RELE_ACAO_LIGAR);
fReleRadio.Items.Add(LB_CENA_RELE_ACAO_INVERTER);
fReleRadio.Items.Add(LB_CENA_RELE_ACAO_PULSAR);
fEditDelay.Parent := Self;
fEditDelay.Left := 400;
fEditDelay.Top := 7;
fEditDelay.Width := 50;
fEditDelay.Height := 24;
fEditDelay.BevelKind := bkFlat;
fEditDelay.Text := '0,0';
fEditDelay.BorderStyle := Forms.bsNone;
fEditDelay.OnKeyPress := EditDelayKeyPress;
fEditDelay.OnExit := EditDelayExit;
fReleRadio.Columns := 4;
fBevelRodape.Parent := Self;
fBevelRodape.Left := 28;
fBevelRodape.Top := 35;
fBevelRodape.Width := 422;
fBevelRodape.Height := 5;
fBevelRodape.Shape := bsBottomLine;
fBevelRodape.Style := bsRaised;
if Assigned(item) then
begin
if TObject(item).ClassType = TFuncaoCena then
begin
funcaoCena := TFuncaoCena(item);
if Trim(TFuncaoCena(item).Nome) <> '' then
fPanelChecked.Caption := TFuncaoCena(item).Nome
else
fPanelChecked.Caption := LB_CARGA+' ' + IntToStr(aIndice + 1);
ReleRadio.ItemIndex := TFuncaoCena(item).Valor;
EditDelay.Text := FormatFloat('##,##0',TFuncaoCena(item).Delay);
if (TFuncaoCena(item).Ativo) then
fBotaoChecked.Checked := True;
end
else if TObject(item).ClassType = TCarga then
begin
Carga := TCarga(item);
if Trim(TCarga(item).Nome) <> '' then
fPanelChecked.Caption := TCarga(item).Nome
else
fPanelChecked.Caption := LB_CARGA+' ' + IntToStr(aIndice + 1);
ReleRadio.ItemIndex := TCarga(item).Valor;
if (TCarga(item).Ativo) then
fBotaoChecked.Checked := True;
end;
end;
fBotaoChecked.Refresh();
Indice := aIndice;
end;
Please, any questions ask me.
Thanks for all help.
There is not enough information to understand, how abstract error arises, but here are some hints about simplifying your code.
Sure your TPanelCargaRele
, TPanelCargaDimmer
, TPanelDefinicaoCargaAV
and TPanelDefinicaoFuncaoSomfy
are so much alike, they all contain the same field funcaoCena
, so we should use it, defining some general class:
TPanelWithCena = class (TPanel)
public
funcaoCena: TFuncaoCena;
end;
TPanelCargaRele = class (TPanelWithCena)
....
TPanelCargaDimmer = class (TPanelWithCena)
...
Next, why use pointer and cast it to TObject all the time when you can use TObject everywhere. So we can rewrite first function like this:
function getFuncaoCena(p: TObject): TFuncaoCena;
begin
if Assigned(p) then
begin
if p is TPanelWithCena then
Result:=TPanelWithCena(p).funcaoCena
else if p is TWinControl then
Result:=getFuncaoCena(TWincontrol(p).Parent)
else
Result:=nil;
else
Result := nil;
end;
Hope you get the idea. After code is rewritten, it would be much easier to understand what's wrong.