Search code examples
delphidelphi-7tpanel

"Abstract error" when Drag and drop TPanel child


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.


Solution

  • 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.