5

If I put a component on the form I don't see any code like MyComp:=TMyComponent.Create in unit code. I think the component is created automatically, but when ? And the same happends with the properties that I configured after I put the component on the form. When they are applied at runtime ?

Marus Gradinaru
  • 2,824
  • 1
  • 26
  • 55
  • Which TComponent ? Can you please post a more detailed answer ? – Marus Gradinaru Nov 28 '14 at 13:30
  • 1
    Put a breakpoint on 'classes.TReader.ReadComponent' before you run the application. – Sertac Akyuz Nov 28 '14 at 13:43
  • 1
    If you need to know it, you might be on the wrong track. It is nice to know, but if you use Delphi in the way it is supposed to, there are very few situations where you should use that knowledge. – Hans Nov 28 '14 at 14:06
  • @Hans: there are more situation where you can use component streaming that you think. Are you saying that you've never called `TMemoryStream.ReadComponent()` or `TMemoryStream.WriteComponent()` ? – Abstract type Nov 28 '14 at 14:32
  • @BBaz I've never done that! .dfm files are not exactly, er, well standards compliant. – David Heffernan Nov 28 '14 at 14:40
  • @David Herffernan: True, standards for serialization are **JSON** and **XML**...oh and there is also **YAML** and...[**OGDL**](http://ogdl.org/) which, BTW, is not so far from the dfm format...When there are so much **standards** is there still a **standard** ? That is the question. – Abstract type Nov 28 '14 at 14:50
  • @BBaz: I never 'needed' it, but of course I have only worked professionally with Delphi for 20 years (Since Delphi 1), so I am still learning ;-) – Hans Nov 28 '14 at 21:12
  • @Hans: well, i must be an extra-terrestrial then, I've used it in my last 5 software! Look at the FMX sources the theme system is strongly based on component streaming and it's higly related to your Q. Actually I've learned component streaming with the former product, 4 or 5 years ago. – Abstract type Nov 29 '14 at 15:36

2 Answers2

4

Information about controls and components as well as their properties that you edit while designing in IDE will be stored in your form .dfm file. Creation of that form in run-time will trigger the process of automatic loading of that .dfm file and all controls and components will be initialized at that time.

This is rather simple explanation of what exactly happens, you can start debugger at form creation line and follow what is happening there, but it is quite longish process and you can easily get lost if you are still learning.

You can find form creation code that Delphi automatically writes in .dpr file of your project.

  Application.CreateForm(TForm1, Form1);
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
4

The properties for a form and all the design time components that live on it are streamed in by the framework during the construction of the form. That process is triggered from the form's constructor, in TCustomForm.Create. The pertinent code in there looks like this:

Include(FFormState, fsCreating);
try
  if not InitInheritedComponent(Self, TForm) then
    raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
finally
  Exclude(FFormState, fsCreating);
end;

The key is the call to InitInheritedComponent. That is a function defined in the Classes unit that does the heavy lifting. In a very broad overview it does the following:

  1. Finds the name of the form class and looks for an RT_RCDATA resource of that name. That resource is the .dfm file.
  2. Once the .dfm resource has been located it is parsed.
  3. The .dfm parsing handles the assignment of properties that you set at design-time in the Object Inspector. For instance the parsing might encounter a line like this: Caption = 'My main form' and it turns that into an assignment of the string 'My main form' to the form's property Caption.
  4. The .dfm file is hierarchical. It contains the properties for the various components and controls that are defined at design-time.
  5. As well as setting the properties of the form's design-time components, the .dfm streaming process also instantiates those components.

In order for all of this to work, the streaming framework relies on RTTI. It knows nothing at all at compile time of your classes and components. Hence the need for RTTI. The streaming framework uses the old style RTTI and in fact that is the reason for the existence of old style RTTI. If ever you wonder about why old style RTTI is the way it is, try to view it from the perspective of having been designed to support streaming.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490