views:

129

answers:

2

I'm using Delphi 7. When I try to create an object in FormCreate, it fails (actually it just hangs). When I try to do the same thing in FormShow, it works. Please note, I'm not talking about creating a visual component like a TEdit. It's a database abstraction object. Any ideas why this might happen? Are there any guidelines about this topic?

+2  A: 

My first guess is that you're accessing a DataModule hasn't been created yet. If your project's source looks like the following:

begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.CreateForm(TDataModule1, DataModule1);
    Application.Run;
end.

And your TForm1.FormCreate looks like the following:

begin
    DataModule1.AddUsersToStringList(Self.ComboBox1.Items);
end;

Then FormCreate going to fail because it's is being run as part of the Application.CreateForm(TForm1, Form1); line, and your Data Module hasn't been created yet.

There's 2 solutions:

  1. Defer your processing/initialization until after all the forms and data modules have been created.
  2. Create all the data modules before creating any of your forms. The Application's "Main Form" in Delphi is the first TCustomForm descendant created by Application.CreateForm, not the first object.
afrazier
But that should cause an access violation... not hanging.
Craig Young
@afrazier: In a simple scenario, your answer is correct.. but not in this case. I assure you, the datamodule, queries, and associated clientdataset are already created when this form's FormCreate is called. It's not the applications main form. The datamodule has lond been created.
Sam
@Craig Young: you're absolutely right. That's the thing, it just hangs (like an infinite loop!).
Sam
+2  A: 

1) The reason is because on FormCreate, the handle to Form is not created yet.

If your database object needs a form handle, do this:

Self.HandleNeeded; // on FormCreate time.

2) The other reason is maybe your database component needs to be connected and it's only connected on DFM?

buttercup
`TWinControl.GetHandle` (which is what gets called when you attempt to retrieve a form's handle) calls `HandleNeeded` internally before returning the handle.Also, if a connection component has `Connected = True` stored in the DFM, then the compiled application should connect as soon as the property is streamed in when instantiating the component. The only time this wouldn't be the case is if you have an IDE expert that forces the compiled state to be `Connected = False` in the built executable.
afrazier
the person who asked this question did not state which database object he used. I remember using BTrieve for Windows which is non-TDataSet-based and had this problem.
buttercup
@buttercup: Not #2, but your #1 sounds plausible. That's the kind of answer I was looking for. The object is too big and complex to dig into any further, and I know it works fine if I call it from FormShow. Thanks, I'm accepting this answer and upvoting all contributors.
Sam