-1

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.

pedro.olimpio
  • 1,478
  • 2
  • 22
  • 43
  • 1
    Try some debugging – David Heffernan Mar 28 '16 at 17:58
  • This code is horrendous, and it's missing all of the class definitions that are necessary to try and recreate the issue. You'll need to debug this yourself by stepping into methods until you narrow down the issue. – Ken White Mar 28 '16 at 18:08
  • Why is this doing using such ugly `Pointer` type-casts and `ClassType` comparisons, instead of using actual typed variables and `is`/`as` operators? – Remy Lebeau Mar 28 '16 at 19:31
  • 1
    You should throw the code away and unlearn everything you think you know. This code is beyond the pale and cannot be redeemed. – David Heffernan Mar 28 '16 at 21:44
  • I'm not surprised that your code contains error, but it's really strange to get abstract error here! When error arises at the end of procedure, it usually means it happened somewhere inside VCL and you didn't enable "use debug DCUs" in project options / compiler. You should look, is there any abstract methods in your classes? First of all, show us how TFuncaoCena class looks like and what is listaFuncoesTemp? – Yuriy Afanasenkov Mar 28 '16 at 22:39
  • Hmmm... to me, this looks like ideal for code using either a virtual method `getFuncaoCena` or even classes implementing an interface with a method of that name. Anyway, abstract errors happen if an abstratc method was not properly overridden. – Rudy Velthuis Mar 29 '16 at 09:38

1 Answers1

1

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.

Yuriy Afanasenkov
  • 1,440
  • 8
  • 12
  • Thank you for your help. Instead of others you try to help me. Thank you very much. – pedro.olimpio Mar 29 '16 at 17:18
  • We are all helping you. If you want us to tell you that your code will be fine with a couple of tweaks, that won't help you. That will make things worse, prolong the agony. Your code is an unmitigated disaster and you have a number of gross knowledge deficits. The sooner you acknowledge that, the sooner you can start correcting them. – David Heffernan Mar 30 '16 at 06:24