【问题标题】:"Abstract error" when Drag and drop TPanel child [closed]拖放TPanel子项时出现“抽象错误”[关闭]
【发布时间】:2016-03-28 17:44:36
【问题描述】:

当我在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;

有什么问题可以问我。

感谢大家的帮助。

【问题讨论】:

  • 尝试一些调试
  • 这段代码太可怕了,它缺少尝试重新创建问题所需的所有类定义。您需要自己调试方法,直到缩小问题范围。
  • 为什么要使用如此丑陋的Pointer 类型转换和ClassType 比较,而不是使用实际的类型变量和is/as 运算符?
  • 你应该把代码扔掉,忘掉你认为你知道的一切。此代码超出范围,无法兑换。
  • 您的代码包含错误我并不感到惊讶,但是在这里出现抽象错误真的很奇怪!当程序结束时出现错误时,通常意味着它发生在 VCL 内部的某个地方,并且您没有在项目选项/编译器中启用“使用调试 DCU”。你应该看看,你的类中是否有任何抽象方法?首先,给我们展示一下 TFuncaoCena 类长什么样,listaFuncoesTemp 是什么?

标签: delphi delphi-7 tpanel


【解决方案1】:

没有足够的信息来理解抽象错误是如何产生的,但这里有一些关于简化代码的提示。 当然你的TPanelCargaReleTPanelCargaDimmerTPanelDefinicaoCargaAVTPanelDefinicaoFuncaoSomfy非常相似,它们都包含相同的字段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;

希望您能理解。代码重写后,更容易理解问题所在。

【讨论】:

  • 感谢您的帮助。你试图帮助我而不是其他人。非常感谢。
  • 我们都在帮助你。如果您希望我们告诉您,您的代码只需稍作调整就可以了,那对您没有帮助。那会让事情变得更糟,延长痛苦。您的代码是一场彻底的灾难,并且您有许多严重的知识缺陷。你越早承认这一点,你就能越早开始纠正它们。
猜你喜欢
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
相关资源
最近更新 更多