Jump to content
LordJonas

Incompatible types bug in D11.1

Recommended Posts

I think i've just found a bug in Delphi 11.1....

 

In this piece of code i'm getting the error "E2010 Incompatible types: 'TShape' and 'Integer'"

 

image.thumb.png.073782df166bc8874f403f8e8efb162b.png

 

but if we take a closer look both types are Integer:

 

image.thumb.png.db7edc029aaf277fd07500b6d26f2ceb.pngimage.thumb.png.bc05c9c5192987fe92b298313c590038.png

 

 

Share this post


Link to post
unit SIGR.Front.View.Principal;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.Imaging.jpeg,
  Vcl.ExtCtrls,
  Vcl.Imaging.pngimage;

type
  TfrmViewMain = class(TForm)
    pnlViewMain: TPanel;
    imgBack: TImage;
    pnlViewMainTopo: TPanel;
    pnlViewMainBottom: TPanel;
    pnlViewMainLateral: TPanel;
    pnlViewMainCliente: TPanel;
    pnlViewMainLogo: TPanel;
    imgLogo: TImage;
    pnlViewMainTopoClient: TPanel;
    pnlViewMainTopoLinha: TPanel;
    pnlViewMainSair: TPanel;
    pnlViewMainConfig: TPanel;
    pnlViewMainUtils: TPanel;
    pnlViewMainTbls: TPanel;
    pnlViewMainOper: TPanel;
    pnlViewMainResid: TPanel;
    pnlViewMainGest: TPanel;
    pnlViewMainEmpr: TPanel;
    shpLinhaTopo: TShape;
    procedure pnlViewMainSairClick(Sender: TObject);
    procedure pnlViewMainEmprClick(Sender: TObject);
    procedure pnlViewMainGestClick(Sender: TObject);
    procedure pnlViewMainResidClick(Sender: TObject);
    procedure pnlViewMainOperClick(Sender: TObject);
    procedure pnlViewMainTblsClick(Sender: TObject);
    procedure pnlViewMainUtilsClick(Sender: TObject);
    procedure pnlViewMainConfigClick(Sender: TObject);
  private
    { Private declarations }
    procedure MoveShapeItem(Value: TPanel);
  public
    { Public declarations }
  end;

var
  frmViewMain: TfrmViewMain;

implementation

{$R *.dfm}

procedure TfrmViewMain.MoveShapeItem(Value: TPanel);
begin
  TThread.CreateAnonymousThread(
  procedure
  begin
    while shpLinhaTopo.Left <> Value.Left do
    begin
      if shpLinhaTopo.Left > Value.Left then
         shpLinhaTopo.Left := shpLinhaTopo.Left - 1
      else
         shpLinhaTopo := shpLinhaTopo.Left + 1;
    end;
  end
  ).Start;
end;

procedure TfrmViewMain.pnlViewMainConfigClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainEmprClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainGestClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainOperClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainResidClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainSairClick(Sender: TObject);
begin
  Close;
end;

procedure TfrmViewMain.pnlViewMainTblsClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

procedure TfrmViewMain.pnlViewMainUtilsClick(Sender: TObject);
begin
  MoveShapeItem(TPanel(Sender));
end;

end.

 

Share this post


Link to post

The reason I asked for a minimal reproduction is that by making one, and making it minimal, you'd have learnt a good debugging technique. Instead you posted loads of spurious code. But the act of curltting it down to a minimal reproduction would have led you to the error.

 

Then again, the compiler told you which line the error was on and somehow you missed that information. 

Share this post


Link to post

The error message is correct, but the IDE is flagging the wrong line of code.  It flagged line 58, but the error is actually on line 63:

shpLinhaTopo := shpLinhaTopo.Left + 1;

You are assigning an Integer to a TShape, not a property of the TShape. That line should be this instead:

shpLinhaTopo.Left := shpLinhaTopo.Left + 1;

That being said, your movement code is wrong in general, because it is accessing UI controls from the context of a worker thread without synchronizing with the main UI thread.  The VCL is not thread-safe, you must synchronize, eg:

procedure TfrmViewMain.MoveShapeItem(Value: TPanel);
begin
  TThread.CreateAnonymousThead(
  procedure
  begin
    TThread.Synchronize(nil,
    procedure
    begin
      while shpLinhaTopo.Left <> Value.Left do
      begin
        if shpLinhaTopo.Left > Value.Left then
          shpLinhaTopo.Left := shpLinhaTopo.Left - 1
        else
          shpLinhaTopo.Left := shpLinhaTopo.Left + 1;
      end;
    end
    );
  end
  ).Start;
end;

Which defeats the whole purpose of using a worker thread.  So, in this case, you can use TThread.ForceQueue() instead, eg:

procedure TfrmViewMain.MoveShapeItem(Value: TPanel);
begin
  TThread.ForceQueue(nil,
  procedure
  begin
    while shpLinhaTopo.Left <> Value.Left do
    begin
      if shpLinhaTopo.Left > Value.Left then
        shpLinhaTopo.Left := shpLinhaTopo.Left - 1
      else
        shpLinhaTopo.Left := shpLinhaTopo.Left + 1;
    end;
  end
  );
end;

Though, in either case, your while loop won't exit until the TShape meets the TPanel, and you are not likely to see each movement being redrawn onscreen, so you may as well just get rid of the loop altogether:

procedure TfrmViewMain.MoveShapeItem(Value: TPanel);
begin
  TThread.ForceQueue(nil,
  procedure
  begin
    shpLinhaTopo.Left := Value.Left;
  end
  );
end;

If you want to visually see the TShape move around, you need a delay between each move, eg:

procedure TfrmViewMain.MoveShapeItem(Value: TPanel; AStepDelay: Integer = 100);
begin
  TThread.ForceQueue(nil,
  procedure
    if shpLinhaTopo.Left <> Value.Left then
    begin
      if shpLinhaTopo.Left > Value.Left then
        shpLinhaTopo.Left := shpLinhaTopo.Left - 1
      else
        shpLinhaTopo.Left := shpLinhaTopo.Left + 1;
      MoveShapeItem(Value, AStepDelay);
    end;
  end,
  AStepDelay
  );
end;

 

Edited by Remy Lebeau

Share this post


Link to post

How to name

  Consider numerous Excel users that do not name the ranges.
  Naming allows the formulas to be readable and robust.
  In excel a name could refer to the cell that a spin control is assigned to.


  In Delphi the default naming scheme reflects what control or control property we are using.

  Knowing what slows down many XL users, one could change the arguments passed to fit the names of what is wanted or needed.
 

  procedure TfrmViewMain.MoveShapeItem(Value: TPanel; AStepDelay: Integer = 100);

  //Value should only used inside a TComponent in Property.setter IMHO
  //reflect name of thing wanted.
  procedure TfrmViewMain.MoveShapeItem(Panel: TPanel; AStepDelay: Integer = 100);

  // a good start
  procedure TfrmViewMain.MoveShapeItem(MovetoRight, LeftFence: TControl; AStepDelay: Integer = 100);

  //or may be a little much

  procedure TfrmViewMain.MoveShapeItem(var MovetoRight.Left, LeftFence.Left:Integer; AStepDelay: Integer = 100);


  //for intent use Control-J summary template to roll your poppy.
  //for errors look at left view mirroe in Structure
  

 

Edited by Pat Foley
Note Last procedure arguments need some special markup to work properly

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×