you can build the name..
Label+IntTostr(Your_Random_Integer_Number);
and use TControl(FindComponent(Your_Random_Name)).Caption := IntTOStr(Your_Random_Number);
Something like that.
That puzzles me, if it is known that the labels are on Form1 and we know the name of the one we want to change the caption for, why is it required to use the findcomponent?Because Form1 has "uses Unit2" (for Form2), but unit2 can not have "uses Unit1" (circulary references are forbid to have)
I don't like to call FindComponent. Because I don't like to use the component's Name.Okies, removed FindComponent and Name to get valid labels
KodeZwerg's solution is nice but works only when the label form is the MainForm of the application.I was doing how I thought that the final should do but of course I challenge your statement with an updated approach.
procedure TForm2.Button1Click(Sender: TObject); // remember, the search is case sensitive, you can use LowerCase() or UpperCase() to make it more generic working // updated to work with Tag instead of Name for target labels type TLabels = array of TLabel; var x, y, z: Integer; arr: TLabels; begin // initialize empty array arr := nil; SetLength(arr, 0); // iterate over root of application to find a specific form where we wanna change something for x := 0 to Pred(Application.ComponentCount) do // we searching for a form with a name of "Form1" if (Pos('Form1', Application.Components[x].Name) > 0) then // iterate over found form for y := 0 to Pred((Application.Components[x] as TForm).ComponentCount) do // exclude anything that is not a TLabel and find labels with a "Target" inside name or a matching Tag, just use one(!) way if (((Application.Components[x] as TForm).Components[y] is TLabel) and // compare against a value (((Application.Components[x] as TForm).Components[y] as TLabel).Tag = 666)) then // compare against a name // (Pos('Target', (Application.Components[x] as TForm).Components[y].Name) > 0)) then // we found something, add it to the internal array begin z := Length(arr); SetLength(arr, Succ(z)); arr[z] := ((Application.Components[x] as TForm).Components[y] as TLabel); end; // when we found something if (Length(arr) > 0) then begin // pick one random and rename the caption to an integer x := Random(Length(arr)); arr[x].Caption := IntToStr(Succ(x)); // optional: we do not need the array anymore, kill it (it will get destroyed automagical when running out of scope) SetLength(arr, 0); arr := nil; end; end;
and have no problems.I do have a problem with your way.
Unit2.pas(8,9) Error: Circular unit reference between Unit2 and Unit1
I tried it but it only lists the components on Form2I have no Idea about your projects source details so I attached a demo again that has on form2 a button to random change a "target/666" label from form1 or list everything that form1 has.
So I broke the idea down a bit to try and figure out what is going on, with this little bit of code it is also only listing components from Form2.So if you copy and paste, please do it correct :-*
for i := 0 to ComponentCount-1 do // <<<<< ERROR, you use componentcount for current form and not the one that you searched Memo2.Lines.Add(Components[i].Name); // <<<<< ERROR, you use componentcount for current form and not the one that you searched
Also what is this Pred() I could not find it anywhere.Pred gives back the Value - 1.
Therefore, unless you have a very simple project you should always avoid such a situation.I second that, to me it is very bad code design as it may lead to future bugs.
No, there is no circular unit reference when both units are listed under implementationIIRC one of the unit can be in the interface section if the other one is in the implementation section.
Would you mind explaining a bit what is actually going on...I'd thought I've already comment all enough but I can try to do more ...
BUT: When the project gets bigger and bigger and more and more units are added the interdependence of the units becomes very complicated and there is a chance that such a solution will not compile any more.
Also, you cannot test the project units independently - you always need Form1 if you want to test Form2 (and if Form1 uses other forms and units you will also need those - a huge mess!). Another issue is that unit2 compiles only when the instance of TForm1 is really named "Form1".
Therefore, unless you have a very simple project you should always avoid such a situation.
Therefore, unless you have a very simple project you should always avoid such a situation.I second that, to me it is very bad code design as it may lead to future bugs.