Cancel / abort the creation of a new form in Delphi / C ++ Builder?

Is there a way to cancel or abort form creation from the form of the OnCreate event handler or the C ++ Builder constructor?

Basically, I would like to be able to call Close () from OnCreate or from the constructor and skip it completely. I have several forms that, as part of their initialization, can determine that they should not be displayed at all. (I understand that I could separate this part of the initialization or add additional checks from the calling form or similar, but if there is a way to do it all from within the OnCreate or constructor, this seems simple.)

Edit: In response to a few comments, some of the incompatible logics are user interface logic, not business logic; the form can display a confirmation before showing or use the general dialog box to enter input for the form, and then abort if the user cancels this dialog box. (Some of them are business logic and need refactoring, but it is often difficult to find the time to reorganize everything that needs it.)

+4
source share
5 answers

You can always call Release in the OnCreate handler, but this will lead to the rapid appearance of the form and its closure. Not a very professional thing.

So here is another idea. Let forms have a public function or property to return whether they should really be shown. Then when you will usually have

 TheForm := TSomeForm.Create(Self); TheForm.Show; 

you will have

 TheForm := TSomeForm.Create(Self); if TheForm.ShouldAppear then TheForm.Show else TheForm.Release; 

Having said that - any other way to encode this (so that you will not create a form that will be immediately destroyed) is certainly better. Especially if you want to maintain a clear separation between the user interface and the business layer, it would be much better to have code that decides whether the form should be displayed outside the form. Create a form only after you have made a decision.

+7
source

I would think that it’s better not even to create the form in the first place. IF you execute some logic that determines that the form is not even needed, and this logic contains the state that is important for the form, then refactify the logic into a separate object (or even a data module) and transfer the object to the form as property. Here is a simple example (using the object approach):

UNIT1

 type TOFormTests = class fStateData : string; public function IsForm1Needed( someparam : string) : boolean; property StateData : string read fStateData write fStateData; end; 

UNIT2

 uses : UNIT1; type TForm1 = class(tForm) : procedure SetFormTests(value : tOFormTests); property FormTests : TOFormTests read fFormTests write SetFormTests; end; procedure SetFormTest(Value:TOFOrmTests); begin fFormTests := Value; // perform gui setup logic here. end; 

then somewhere in your code where you want to determine whether to show your gui or not use something like the following:

 var Tests : TOFormTests; begin tests := tOFormTests.create; try if Tests.IsForm1Needed('state data goes here') then begin Form1 := tForm1.create(nil); try Form1.FormTests := Tests; if Form1.ShowModal = mrOk then // handle any save state logic here. ; finally FreeAndNil(Form1); end; end; finally freeAndNil(Tests); end; end; 

This also assumes that the form is NOT on the auto-create list and should be shown modal.

+7
source

Use Undo in the constructor. This causes a silent exception. If the object has an exception in the constructor, the destructor is called and memory is freed. The advantage of Abort is that you don’t have to worry about the exception dialog being displayed unless you add an exception handling code.

+6
source

Add a class function that returns an instance if necessary. Then the method that determines whether the form should be displayed is still in this class, but it can determine if it is necessary before the form is built. Name it as "CreateIfNeeded" and it will work as a constructor, but will not actually create a form if it is not needed. Minimal code changes and maximum flexibility.

+4
source

Just throw an exception in OnCreate. You will also need to override the behavior of the HandleCreateException method (by default, an error message is displayed, and creation is not canceled).

+2
source

All Articles