I have added some units to the uses part of my parent TForm.
Then I went to File > New... and created a form inhering my form which has the usages.
The child form seems not to have access to the units used in the parent form.
Is this the correct behavior or is it possible to inherit the uses?
This behaviour is correct. The units listed in a uses clause are made available to that unit only.
If your other unit, containing he derived class, requires symbols from other units, it must list those units in its own uses clause.
Related
I have defined a base VCL form class with a (non-visual) designtime component on it that contains a collection of styles.
I want to prevent developers (and myself) to change those styles in the forms that are derived from my base form. To speak in C# terms, I would like the component to be sealed in the base VCL form.
How can I achieve that?
On a side note: I never did understand the declaration of designtime components on a form in Delphi.. kinda public but not placed in the public section of the class declaration. Can anybody explain the reason for this?
Well, short answer you can't. In case you really need it I would suggest to create the component in run-time and make it private. If you are using GExpert (click here) you may use "Components to Code" command to get the required code. If you need more details, please share your DFM file and I will post the corresponding code here.
As for your side note, the components are declared as published. See Visibility of Class Members quote
If a member's declaration appears without its own visibility
specifier, the member has the same visibility as the one that precedes
it. Members at the beginning of a class declaration that do not have a
specified visibility are by default published, provided the class is
compiled in the {$M+} state or is derived from a class compiled in the
{$M+} state; otherwise, such members are public
NB TForm is a descendant of TPersistent which is compiled with {$M+} directive
PS the published declaration is required for TComponent.SetName (actually TComponent.SetReference) which should assign the component reference to the corresponding field when you modifying the component Name property.
hi to all In advance Sorry for my english.
I'm explain my problem. For an OpenGL library. I have a generic Shader component (TGLCustomGLSLShader). I'd like to make a Shader Library collection. At this time i can add TGLCustomGLSLShader in my collection. But i'd like also add descendant of TGLCustomGLSLShader. for Example : I create specific shader like TGLBumpMapShader, a TGLWaterShader ect.... with differents custom properties in each and are not present in the base class. I'd like to add this new classes in my collection and view there custom properties at design-time. It is possible ?
How can make this ? Have you some links ? I tried to search with google, but i don't find any clues.
Best regards
There are two ways to implement this with full design-time and DFM support:
Have the common base class (TGLCustomGLSLShader) derive from TCollectionItem, and then create a TOwnedCollection published property in your main Library component to hold them. Users will not be able to drop shaders on the Form at design-time, but the native collection editor should be able to delete/edit the shader objects normally. You can create a custom design-time editor that allows users to create instances of your shader classes, passing the TOwnedCollection object to their constructor. You will also have to implement custom DFM streaming for the Library component so it will create instances of the appropriate shader classes when loading a DFM, otherwise it will create TGLCustomGLSLShader objects instead of derived objects.
Have the common base class derive from TComponent, thus allowing users to drop shaders on the Form and configure their properties like normal components. Then, in your Library component, create a TOwnedCollection published property, and define a custom TCollectionItem class for it that has a published TGLCustomGLSLShader property. This will allow the user to use the native collection editor to add items and then manually link them to the desired shader components as needed. While this requires more objects and more user setup, it is friendlier on the native design-time editors and DFMs, as it allows default behaviors to act normally and does not require any custom design-time editors to manage the objects.
I'm working on some components in XE2. Is it possible to have more than the component's unit added to the uses clause of the form it's dropped on?
Example:
When I choose the TCustomComponent from a package I've built and installed the unit CustomComponent is added to the form's uses clause. I would like to also add the unit GlobalConstants.
Does anyone know if this can be done?
Create a design-time package for your component (if you do not already have one). In that package, create a class that implements the ISelectionEditor interface (the easiest way is to derive from the TSelectionEditor class), overriding its virtual RequiresUnits() method to report any additional units you want to appear in the uses clause of any Form/Frame/DataModule that uses your component. Then, have your package's Register() function register that class by calling RegisterSelectionEditor() (in addition to RegisterComponents()).
Indy 10 does exactly this for its TIdTCPServer, TIdCmdTCPClient, and TIdUDPServer components, to make sure the IdContext and IdSocketHandle units get added to uses clauses. Look at the IdCoreSelectionEditors.pas and IdRegisterCore.pas units to see how Indy implements this.
Update: the IdCoreSelectionEditors.pas and IdProtocolsSelectionEditors.pas units were removed from Indy 10 in March 2014. All of the per-component SelectionEditor classes were replaced with a new single class implemented in the IdRegisterCore unit itself. This new SelectionEditor class is registered for all Indy components, and it looks for all instances of any Indy component that has been placed at design-time, using RTTI of the data types of all parameters and return values for any assigned event handlers to know which units to report for inclusion in the uses clause.
Google is useless for these sorts of searches, because you get hundreds of millions of results absolutely none of which relate to the specific question.
The question is simply this:
Is it possible to have a Class Reference Property in Delphi?
If so, how?
Here's what I've tried...
type
TMyObject = class
// ...
end;
TMyObjectClass = class of TMyObject
TMyObjectA = class(TMyObject)
// specifics here
end;
TMyObjectB =class(TMyObject)
// specifics here
end;
TMyComponent = class(TComponent)
private
FObjectType: TMyObjectClass;
published
property ObjectType: TMyObjectClass read FObjectType write FObjectType;
end;
The above code compiles fine, however the Object Inspector does not show the ObjectType property at all.
My objective here (if you haven't already guessed) is to make it so that I can select a class descendant from a specific base class, to make the same component behave in a different way.
I want to do it this way so that the component doesn't need to know about the sub-classes directly (it needs to be fully modular).
Let me just make this bit clear: I cannot use an Enum to choose between the sub-class types as the component cannot directly link to the sub-class types (It's simply not possible in this particular case)
Anyway... thanks in advance!
You can find all classes that descend from a particular base class: Delphi: At runtime find classes that descend from a given base class? and make this a special property with list of values using TPropertyEditor.
If you were going to do this then you would need to provide a property editor. The IDE does not come with property editors for class type properties. You would also need to handle .dfm persistence. You would write the class type out to the .dfm file as a string and when the .dfm file is read, you would need to fixup the reference. New style RTTI could do that.
However, I don't think any of this is actually viable for the following reason. Your design time code runs in a package inside the IDE and does not have access to the class types in the active project in the IDE. Those class types only exist when that project runs. So the ObjectType property in the code in your question cannot be assigned to anything meaningful in the design time package. Well, you could use it for classes defined in the VCL and any other packages installed in your IDE but I rather imagine you'd want to use it on classes defined in the active project.
I think all this means that you should instead use a simple string property and fixup the class type references only at runtime.
Almost all of the Delphi code I have read has all the class type definitions in the units interface section, but I have seen occasional use of type definitions within the implementation section.
What exactly is the difference between these, and why would I use this?
It's pretty simple: types defined in implementation only are only visible within the implementation, so they cannot be used as types of arguments or return values in the interface. So, position your type definitions (like anything else;-) based on whether those types are only an implementation detail, or something you want to make visible externally, i.e., through the interface!
Scope. Interface declarations are public and availabe to other units when that unit is include in the Uses clause. Implementation declarations are private and only available within that specific Unit.
There is a general difference between code changes in interface and the code changes implementation during compilation. If you add a class to or change an existing class in the interface section then every unit that references the changed unit will need to be recompiled. However a change in the implementation section (a new subclass or code changes) will only required the recompilation of that unit and the IDE will link the previously compiled DCU plus the new one together to create the EXE file.
Overall the major benefit, is that it allows you to design you code to hide implementation details - define the parent class in the interface and any subclasses in the implementation. Or define classes in the implementation if they are solely needed to implement the behavious of a class/method available in the interface section.