"Абстрактная ошибка" при перетаскивании дочернего элемента TPanel
Я сталкиваюсь с Abstract error
когда я перетащить ребенка TPanel в TImage
составная часть.
В основном у меня есть Scrollbox
содержать TPanelCargaRele
список, и когда я перетаскиваю эту панель в корзину, я получаю Abstract error
,
Я отладил свой код, но эта проблема возникает в end;
линия процедуры, и я не мог видеть, где проблема.
Вот мой код ниже:
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..
Вот конструктор 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;
Пожалуйста, любые вопросы задавайте мне.
Спасибо за помощь.
1 ответ
Недостаточно информации, чтобы понять, как возникает абстрактная ошибка, но вот несколько советов по упрощению вашего кода. Уверен ваш TPanelCargaRele
, TPanelCargaDimmer
, TPanelDefinicaoCargaAV
а также TPanelDefinicaoFuncaoSomfy
очень похожи, они все содержат одно и то же поле funcaoCena
, поэтому мы должны использовать его, определяя некоторый общий класс:
TPanelWithCena = class (TPanel)
public
funcaoCena: TFuncaoCena;
end;
TPanelCargaRele = class (TPanelWithCena)
....
TPanelCargaDimmer = class (TPanelWithCena)
...
Далее, зачем использовать указатель и приводить его к TObject все время, когда вы можете использовать TObject везде. Таким образом, мы можем переписать первую функцию следующим образом:
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;
Надеюсь, вы поняли идею. После того, как код переписан, было бы намного легче понять, что случилось.