Within a custom TComponent
, I need to get the path of the *.dfm
or *.pas
file where the TComponent
is used. Obviously, this is only required at design-time.
Context
Similar to a previous question:
How to detect the dfm/project path from a custom control while in the designer?
I created a custom TControl similar to TImageCollection but with a shared database of images for all the application. For this, the control reads a project meta-file which is an XML containing the list of images to include in the image collection. When in the designer, images are read directly from the image files, but at runtime, images are in the resource (*.res) file generated during the compilation.
if csDesigning in Self.ComponentState then loadImagesFromFiles(...) else loadImagesFromResource(...)
In the previous version (for the other question linked above), I tried to get the path of the project, and while this seems not possible, I found a way to get the path to the active project. However, this is very problematic when the IDE has several projects open.
I decided to switch to another approach, where I use a path relative to the DFM where the component is used. This should be more reliable.
Unfortunately, it seems not that easy for a custom TComponent
placed on a DFM to know where that DFM is located.
Solutions (half)
I tried several solutions with IOTA
, but could not get anything working yet.
The approach provided here returns the path to the TComponent
itself, not to the DFM where it's used.
I managed to iterate Modules following the same strategy, but finding which Module contains the given TComponent
is not trivial:
function GetCurrentDfmPath(AComponent: TComponent): String;
var
ModuleServices: IOTAModuleServices;
Module: IOTAModule;
idx: integer;
begin
Result := '';
SourceEditor := nil;
if SysUtils.Supports(BorlandIDEServices, IOTAModuleServices,
ModuleServices) then
begin
for idx := 0 to ModuleServices.ModuleCount - 1 do
begin
Module := ModuleServices.Modules[idx];
// Needs to match the module that contains AComponent.?
end;
end;
end;
At design-time, your component's
Owner
should be the parent Form (all components dropped on a Form at design-time are owned by the Form by default).If your component is derived from
TControl
, it can alternatively find its parent Form by using theForms.GetParentForm()
function.TCustomForm
has aDesigner
property of typeIDesignerHook
that is non-nil at design-time.Query the
IDesignerHook
forIDesigner
using theas
operator (do not use a hard cast!).IDesigner
has aModuleFileNames()
method to retrieve the filenames associated with the object being designed, which in this case will be theTCustomForm
so theFormFileName
parameter will output the filename of the.dfm
(VCL) or.xfm
(FMX).