Author: Jonas Bilinkevicius
In Access and PB applications, I have implemented menus based on database tables.
Ie., you select a particular entry and it load a particular form based on the text
in the table. The question is, how do I do something similar in Delphi?
Answer:
Solve 1:
Let's assume that you want to show one of the forms of class TForm1, TForm2 or
TForm3 and that the classname is held in a string called FormString.
Add the units holding the forms to a Uses statement - implementation section if
possible (i.e Uses Form1, Form2, Form3)
Add an initialization section (before final end.):
1 initialization
2 RegisterClasses([TForm1, TForm2, TForm3]);
3 end.
4
5 write a procedure to show a form. for example:
6
7 procedure TForm1.ShowForm(const fname: string);
8 begin
9 with TFormClass(FindClass(fname)).Create(Application) do
10 try
11 ShowModal;
12 finally
13 Free;
14 end;
15 end;
Thus you would call this via:
ShowForm(FormString);
Solve 2:
Yes, you can do this. The requirement is that you register all your forms (at least
those that need to be created by name) using the RegisterClass method. That adds
the form class and its name to an internal list maintained by the VCL. You can now
call FindClass or GetClass to get the class reference back using the class name.
16 var
17 fc: TFormClass; {class of TForm, a class reference type}
18 form: TForm;
19 begin
20 fc := TFormClass(getClass(formclassnamefromdatabase));
21 if Assigned(fc) then
22 begin
23 form := fc.Create(Application);
24 try
25 form.ShowModal
26 finally
27 form.free
28 end;
29 end;
30 end;
The main problem here is that you cannot use the default form variables the IDE
puts into the form units Interface, so better delete them to prevent accidental
references to them. There is no mechanism to find a variable by name build into the
VCL, but if you really need to use the form variables you could build your own
registration mechanism that would build a list associating form class name, the
form class, and the address of the form variable.
Once the form is created you can find a reference to it from elsewhere in the app
by iterating through the Screen.Forms array, looking for a form with a specific
class name.
Solve 3:
Here are a couple of approaches. As long as you are only accessing Methods and
Properties common to TForm, the following will work for you. Pay special attention
to the RegisterClasses call in the initialization section:
31 unit GenericFormCreate;
32
33 interface
34
35 uses
36 Windows, Messages, SysUtils, Classes, Graphics, Controls,
37 Forms, Dialogs, StdCtrls, FileCtrl, Buttons, ExtCtrls;
38
39 type
40 TFrmGenericFormCreate = class(TForm)
41 BtnCreateFromString: TButton;
42 BtnCreateFromClass: TButton;
43 RgrSelect: TRadioGroup;
44 procedure FormCreate(Sender: TObject);
45 procedure BtnCreateFromStringClick(Sender: TObject);
46 procedure BtnCreateFromClassClick(Sender: TObject);
47 private
48 procedure CreateFromClass(AForm: TClass);
49 procedure CreateFromClassName(AForm: string);
50 public
51 end;
52
53 var
54 FrmGenericFormCreate: TFrmGenericFormCreate;
55
56 implementation
57
58 {$R *.DFM}
59
60 uses
61 Unit2, Unit3;
62
63 procedure TFrmGenericFormCreate.FormCreate(Sender: TObject);
64 begin
65 RgrSelect.ItemIndex := 0;
66 end;
67
68 procedure TFrmGenericFormCreate.CreateFromClass(AForm: TClass);
69 begin
70 with TFormClass(AForm).Create(Application) do
71 try
72 ShowModal;
73 finally
74 Release;
75 end;
76 end;
77
78 procedure TFrmGenericFormCreate.CreateFromClassName(AForm: string);
79 begin
80 try
81 with TFormClass(FindClass(AForm)).Create(Application) do
82 try
83 ShowModal;
84 finally
85 Release;
86 end;
87 except
88 ShowMessage(Format('Class %s not found', [AForm]));
89 end;
90 end;
91
92 procedure TFrmGenericFormCreate.BtnCreateFromStringClick(Sender: TObject);
93 begin
94 CreateFromClassName('TForm' + IntToStr(RgrSelect.ItemIndex + 2));
95 RgrSelect.SetFocus;
96 end;
97
98 procedure TFrmGenericFormCreate.BtnCreateFromClassClick(Sender: TObject);
99 begin
100 case RgrSelect.ItemIndex of
101 0: CreateFromClass(TForm2);
102 1: CreateFromClass(TForm3);
103 end;
104 RgrSelect.SetFocus;
105 end;
106
107 initialization
108 RegisterClasses([TForm2, TForm3]);
109 end.
|