This feels like witchcraft, but is there by any chance a way to get the name of the current unit?
Let's say I have simple blank form and I basically want to dynamically during runtime show the Unit Name of that form in the Caption
of the form. How would I do this?
I imagine something like a function that says GetCurrentUnitName()
which returns a string containing the unit name of the file 😅
The reason I want this is because I have an app that should show the Unit Name when it's ran in debug mode. So right now I'm just trying to figure out what the best way is to get the unit name.
So my full form code would look something like this ideally:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := GetCurrentUnitName(); // Shows "Unit1" or maybe "Unit1.pas"
end;
end.
Ideally, I would hope there's a built-in function somewhere and somehow for this. Is there? 😅
If there isn't a built-in method, then any other method is also welcome. Maybe some magic RTTI way of doing it?
I have some ideas of how I could do it, but I'm not really fully happy with my ways. These are the two ways:
Using a Constant.
Problem: It works, but it's hardcoded. So not very nice.
But alas, this is what I'm currently using in the app:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
const
UnitName = 'Unit1';
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := UnitName; // Shows "Unit1"
end;
end.
Using RTTI.
Problem: It shows "Unit1.TForm1" and not just the Unit Name like "Unit1". Also, what if I want to use it outside of a form like in a utilities unit with no classes. Ideally I'd like something that works anywhere.
But anyway here is the RTTI method that I currently have that kinda works:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Rtti;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
function GetUnitName(AClass: TClass): String;
var
RttiContext: TRttiContext;
RttiType: TRttiType;
begin
RttiType := RttiContext.GetType(AClass);
Result := RttiType.QualifiedName;
end;
begin
Caption := GetUnitName(TForm1); // Shows "Unit1.TForm1"
end;
end.
Any better methods out there?
TObject provides a class function UnitName for which the docs say:
Returns the name of the unit where the class is defined.
UnitName can be used to obtain the unit where a specific class is defined. For example, calling UnitName on TButton returns the
Vcl.StdCtrls
string.
Taking your example, the code in FormCreate can simply be:
Caption := UnitName;
If called outside the TForm1 class scope you can use TForm1.UnitName
.