Forum > General

[SOLVED] Can't access component property

(1/1)

pcurtis:
I am trying to design a component. When I try to set a property at runtime it fails with "unit1.pas(40,26) Error: Argument cannot be assigned to".
What's wrong?


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit mythreaddisplay; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, LResources, Forms, Controls, Graphics, StdCtrls, ExtCtrls, ComCtrls, Dialogs, Buttons, Windows;type  TThreadInfo = record    Position : Integer;    Caption : String;  end;   TMyThreadDisplay = class(TCustomControl)  private    flblLabel : array[0..4] of TLabel;    fprbProgressbar : array[0..4] of TProgressBar;    fThreadInfo : array[0..4] of TThreadInfo;    function GetThreadInfo(Index: Integer): TThreadInfo;    procedure SetThreadInfo(Index: Integer; AValue: TThreadInfo);  protected   public    constructor Create(AOwner : TComponent); override;    property ThreadInfo[Index: Integer]: TThreadInfo read GetThreadInfo write SetThreadInfo;  published    property Align;  end; procedure Register; implementation function TMyThreadDisplay.GetThreadInfo(Index: Integer): TThreadInfo;begin  Result := fThreadInfo[Index];end; procedure TMyThreadDisplay.SetThreadInfo(Index: Integer; AValue: TThreadInfo);begin  if fThreadInfo[Index].Caption <> AValue.Caption then    begin      fThreadInfo[Index].Caption := AValue.Caption;      flblLabel[Index].Caption := AValue.Caption;    end;   if fThreadInfo[Index].Position <> AValue.Position then    begin      fThreadInfo[Index].Position := AValue.Position;      fprbProgressbar[Index].Position := AValue.Position;    end;end; constructor TMyThreadDisplay.Create(AOwner : TComponent);var  iTEMP : Integer;begin  inherited Create(AOwner);   for iTEMP := 4 downto 0 do    begin      fprbProgressbar[iTEMP] := TProgressBar.Create(Self);       with fprbProgressbar[iTEMP] do        begin          fThreadInfo[iTEMP].Position := 0;          Align := alTop;          Parent := Self;          Position := fThreadInfo[iTEMP].Position;        end;       flblLabel[iTEMP] := TLabel.Create(Self);        with flblLabel[iTEMP] do          begin            fThreadInfo[iTEMP].Caption := 'Thread ' + iTEMP.ToString;            Caption := fThreadInfo[iTEMP].Caption;            Align := alTop;            Parent := Self;            ParentFont := True;          end;      end;   Constraints.MinHeight := 205;  Constraints.MinWidth := 100;  SetBounds(0, 0, 100, 205);end; procedure Register;begin  RegisterComponents('Misc', [TMyThreadDisplay]);end; end. 

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls,  mythreaddisplay; type   { TForm1 }   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private   public   end; var  Form1: TForm1;  MyDisplay : TMyThreadDisplay; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);begin  MyDisplay := TMyThreadDisplay.Create(self);  MyDisplay.Left := 8;  MyDisplay.Top := 8;  MyDisplay.Parent := Form1;   MyDisplay.ThreadInfo[1].Caption := 'something';  // fails hereend; end.  

PascalDragon:
If you have a property that is of a record type you must change it as a whole. This avoids people wondering why their code does not work, because the getter only provides a copy (*).

So you need to use this:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  info: TThreadInfo;begin  info := MyDisplay.ThreadInfo[1];  info.Caption := 'something';  MyDisplay.ThreadInfo[1] := info;end;
Alternatively you can use a class instead of a record for TThreadInfo (you need to instantiate them correctly of course). Or your property needs to a pointer to the TThreadInfo.

(*) That is because the compiler would essentially generate code like this:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  tmp: TThreadInfo;begin  // MyDisplay.ThreadInfo[1].Caption := 'something';  tmp := MyDisplay.ThreadInfo[1];  tmp.Caption := 'something'
The tmp record would be a copy, not a reference.

pcurtis:
Thank you.

Navigation

[0] Message Index

Go to full version