uses
TypInfo, RTTI;
procedure ListAllFormClasses(Target: TStrings);
var
aClass: TClass;
context: TRttiContext;
types: TArray<TRttiType>;
aType: TRttiType;
begin
context := TRttiContext.Create;
types := context.GetTypes;
for aType in types do begin
if aType.TypeKind = tkClass then begin
aClass := aType.AsInstance.MetaclassType;
if (aClass <> TForm) and aClass.InheritsFrom(TForm) then begin
Target.Add(aClass.ClassName);
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
Memo1.Lines.Clear;
for I:= 0 to Screen.CustomFormCount - 1 do
Memo1.Lines.Add(Screen.Forms[I].Caption);
end;
unit Unit1;
interface
uses
Classes
, Forms
, SysUtils
;
procedure RegisterForm(aName: string; aClass: TFormClass);
procedure ListForms(aNames: TStrings);
function InstantiateForm(aName: string): TCustomForm;
implementation
var
FormRegistry: TStringList;
procedure RegisterForm(aName: string; aClass: TFormClass);
begin
FormRegistry.AddObject(aName, Pointer(aClass));
end;
procedure ListForms(aNames: TStrings);
var
i: Integer;
begin
for i := 0 to FormRegistry.Count - 1 do begin
aNames.Add(FormRegistry[i]);
end;
end;
function InstantiateForm(aName: string): TCustomForm;
var
idx: Integer;
frmClass: TFormClass;
begin
Result := nil;
idx := FormRegistry.IndexOf(aName);
if idx > -1 then begin
frmClass := TFormClass(FormRegistry.Objects[idx]);
Result := frmClass.Create(nil);
end;
end;
initialization
FormRegistry := TStringList.Create;
FormRegistry.Duplicates := dupError;
FormRegistry.Sorted := True;
finalization
FreeAndNil(FormRegistry);
end.
procedure ListForms(lbForms:TListBox);
var
i,j:integer;
begin
for i:=0 to application.ComponentCount-1 do
if application.components[i] is tform then
begin
lbForms.add(tform(application.components[i]).Name);
end;
end;
procedure ListBox1Click(Sender:TObject);
var
ix,j,i:integer;
begin
ix:=ListBox1.ItemIndex;
if ix>=0 then
begin
for i:=0 to application.componentcount-1 do
if application.components[i] is tform then
begin
if tform(application.components[i]).name=listbox1.items.strings[ix] then
begin
for j:=0 to tform(application.components[i]).controlcount - 1 do
if tform(application.components[i]).controls[i] is tbutton then
begin
listbox2.add(tbutton(tform(application.components[i]).controls[i]).caption);
end;
break;
end;
end;
end;
end;
6条答案
按热度按时间huus2vyu1#
如果你在 Delphi 2010上,你可以使用RTTI来列出所有注册的(=在应用程序中以某种方式使用的)表单类:
你必须注意这个类不能被链接器完全删除(因此上面的 registered 提示),否则你不能用描述的方法得到这个类。
aemubtdh2#
窗体通常使用Screen.Forms属性列出,例如:
qeeaahzv3#
arslan的答案是在运行时找到所有示例化的表单。
在评论中,Hamid也要求找到未赋值的表单。假设他所说的未赋值是指未示例化的表单,那么只有一种方法可以做到这一点,那就是在vcl流系统使用的类注册表中迭代,当dfm被流入时,按名称示例化组件。
但是,IIRC表单不会自动添加到注册表中。OP当然可以自己为项目中的每一个窗体添加这些窗体,但是,这留下了这样的问题,即流式传输系统所使用的类注册表是使用类单元的实现部分中的var来实现的。因此不能(轻易地)从外部进行迭代。
因此,解决方案是使用项目中所有表单单元的初始化部分,在“roll-your-own”注册表中注册每个表单,并使用它们的名称和类,让注册表提供迭代已注册表单的方法。这些方法可用于填充OP提到的列表框。
要获得表单上的TButton,需要示例化表单(它可能保持隐藏),并使用类似sabri.arslan的代码迭代组件,以找到TButton示例。
示例化窗体需要根据在列表框中选择的窗体名称从注册表中获取窗体的类。
一个简单的自卷窗体注册表示例:
xkrw2x1b4#
您可以使用“for”循环。
aelbi1ox5#
没有办法(容易)找到包含的表格。
但是如果你遍历资源的RCdata(参见(1)(2)(3)),你可以找到表单的名称,但是这并不能帮助你创建表单。
为了使表单“可查找”,必须自己“注册”它们,使用RegisterCLAass,然后使用FindClass再次查找它们。请参见此处的示例:http://www.obsof.com/delphi_tips/delphi_tips.html#Button
kyxcudwk6#
您是否需要在运行时构建此信息,或者编译时信息是否对您有用?
在最近的版本( Delphi 2006和更高版本?)中,您可以设置编译器选项来为项目生成XML文档。为每个单元生成一个单独的XML文件。您可以解析此XML以查找和表单,并查看任何按钮的成员。