"Abstract error" 当拖放 TPanel 子项时

"Abstract error" when Drag and drop TPanel child

当我在 TImage 组件中拖放 TPanel 子项时,我正面临 Abstract error

基本上我有一个 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;

有什么问题可以问我

感谢大家的帮助。

没有足够的信息来理解抽象错误是如何产生的,但这里有一些关于简化代码的提示。 当然你的TPanelCargaReleTPanelCargaDimmerTPanelDefinicaoCargaAVTPanelDefinicaoFuncaoSomfy很像,它们都包含相同的字段funcaoCena,所以我们应该使用它,定义一些一般 class:

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;

希望你明白了。重写代码后,更容易理解哪里出了问题。