Good day! My question about forms that are created in runtime.
I need to have a link in Delphi to the form that the script creates. I've created a class
TApplicationForm = class(TScriptForm)
with a Manager property to be able to close all generated forms from the application. I assign this Manager property at the time of creating a new unit:
But I understand that in runtime a new instance of this form "doesn't know" about the Manager (Manager=nil). Tell me please, how to get a link to this instance of TApplicationForm in the main (native) code?
Yes Wagner, I set this value. The forms themselves work fine. The problem is that there are two of them — one in design mode, the other is created by a script. The first one has access and the Manager property is assigned correctly, but I need to access the second).
In fact, I need to somehow get a reference to this constructor:
Hi Vitalii, sorry but I don't understand what you need. Can you please be more specific, or illustrate with some source code? The design-time and runtime forms are created the same way, they are just two different instances.
I am creating a new unit and form TApplicationForm via TIDEEngine.NewFormUnit.
I assign property TApplicationForm(Result).Manager := FFormManager.
Run project.
I press the RESET button, which calls the destructor of the form through the manager:
procedure TApplicationFormItems.CloseAllForms;
var
i: Integer;
begin
for i: = 0 to Count - 1 do
if Assigned(Items[i].Form) then
Items[i].Form.Free;
end;
Result: design-time form (in the editor) is deleted, but the form that the script created is still exists (see screenshot). Of course, I need to delete/close runtime form, not design-time form.
Design-time form: Manager<>nil; runtime form: Manager=nil. I know that design-time and runtime forms are created the same way, but how can I access the runtime form?
Please detail this. NewFormUnit returns a TIDEProjectFile, not a TScriptForm. If you are casting it to TApplicationForm, it's wrong. You should cast Result.Form.
Wagner, the problem is not in this place. I am overriding TIDEEngine.CreateScriptForm method:
function TApplicationEngine.CreateScriptForm: TIDEScriptForm;
begin
Result := inherited CreateScriptForm;
if Assigned(Result) and (Result is TApplicationForm) then
begin
TApplicationForm(Result).Manager := FFormManager;
end;
end;
I also tried the way you wrote it, ie using TIDEEngine.NewFormUnit.Form.
This is not the question. The question is, where do I get a pointer to the runtime form from?
If I understand correctly, this code creates the form:
function TatVirtualMachine.CreateFormRunScript (AForm: TComponent): TatScript;
Is it possible to somehow get a link to the form that the script creates? Just something like this:
"TIDEEngine.NewFormUnit.RuntimeInstanceForm" or "VirtualMachine.RuntimeForm"
Because TIDEEngine.NewFormUnit.Form returns pointer to the design-time form (as my tests show).
A simple test.
We create one form in the designer using the method Form1 := TIDEEngine.NewFormUnit.Form;
If we execute the project, for example, 3 times in a row, we will get 3 runtime forms, right? (see screenshot 1) I understand that it is wrong to run the project more than 1 time, but this is for example. The bottom line is that before re-executing, I need to delete the runtime form (Form.Free).
Question: Where can I find pointers to these runtime forms? To close them, for example. If we now use variable Form1 and execute Form1.Close, then in my case the form is closed in the designer, and all runtime forms are unchanged (screenshot 2). What I'm doing wrong? Sorry for the long discussion :)
Ok, I see that TApplication is the owner of all runtime forms, so we can iterate over the components:
procedure TFormManager.CloseAllForms;
var
i: Integer;
Form: TScriptForm;
begin
for i := Application.ComponentCount - 1 downto 0 do
if Application.Components[i] is TScriptForm then
begin
Form := TScriptForm(Application.Components[i]);
Form.Free;
end;
end;
It will be very good if the engine stores pointers to all created forms somewhere. Then it would be easier to manage them.
Ok, I understand now, sorry. Well, indeed, that's one solution. Scripter doesn't hold pointers to created forms, forms are just like any other regular objects. It doesn't hold pointers or do any memory management, that's up to you indeed.
Yes, you right, but in this case we need to create some global list / collection to hold this info. I think, ideally work only with classes and components, no global variables. Therefore, it is important to have a class that would hold a pointer to the created object. Only from the perspective of the class model)