Question

I'd like to check from Form1.OnCreate event handler procedure if Form1 constructor Create finished the job with populating all the components on Form1. Then would like to use Form1 to loop through the components and change Text property. I have tried:

WHILE NOT Assigned(Form1) DO 
  Sleep(100); 

... but it didn't work.

Now when I try to use Form1, I get Access Violation error.

Was it helpful?

Solution

The OnCreate event is triggered at the end of the construction of a Form object. A Form's components are created during the construction process before the OnCreate event is triggered. There is no need to "check .. if Form1 constructor Create finished the job" as that is basically guaranteed. Once OnCreate is triggered, you can access the components.

If your Form1 object is created via TApplication.CreateForm() at program startup then the Form1 variable will be assigned a valid but uninitialized object before the constructor is called, and thus will point at a valid object in the OnCreate event.

If your Form1 object is created by calling its constructor in your code, then the Form1 variable will not be assigned until after the constructor exits, and thus will not point at a valid object in the OnCreate event.

Either way, you should not be using the Form1 variable inside of the OnCreate event for the Form1 object to begin with. Use the Self pointer instead, or typecast the event's Sender parameter. Both will point at the same Form1 object that was created.

OTHER TIPS

This answers address what I think is the real issue as has become apparent from your comments. You should edit the question to include those details that at the moment appear only in comments.

You appear to be trying to make a procedure run whenever a form is created. As I explained above, no good will come of waiting in the main thread. The thing you are waiting for also runs in the main thread. You'll just block forever.

So I won't attempt to explain how to wait, as you asked, because that can never work. That is not the solution to your real problem.

As I understand your problem, based on your recent questions, you are trying to access Application.MainForm in the constructor of said form, and the MainForm property has not yet been initialised. The reason you do that is because you want to walk over all components owned by Application.

Or you want to use the global Form1 variable which is nil during the creation of the form. But you would be well advised to delete that global Form1 variable anyway. Global variables tend to cause trouble. Since you are inside the a method of your form, in a method handler for OnCreate, you can access the form using Self. Always use Self if it is possible to do so.

But that's the wrong way to solve the problem anyway. It denies the existence of forms created after your program has started. You should do what you need to do, on demand, when any form is created.

This is how I would solve your problem:

  1. Declare a new form, derived from TForm, called, for instance, TMyBaseForm.
  2. Add an AfterConstruction procedure, with the override directive.
  3. Implement TMyBaseForm.AfterConstruction to invoke your text changing code. At this point all the design time control exists and have properties streamed.
  4. Make sure that all forms in your application derive from TMyBaseForm.

This design gives you the opportunity to apply consistent behaviour across all GUI elements in your program.

One final comment. You appear to be relatively inexperienced and novice. That's fine, we were all there once. But you will be more successful if you ask questions about your problem rather than about your proposed solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top