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