2008. május 14., szerda
Open a form based on a text value
Problem/Question/Abstract:
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.):
initialization
RegisterClasses([TForm1, TForm2, TForm3]);
end.
Write a procedure to show a form. For example:
procedure TForm1.ShowForm(const fname: string);
begin
with TFormClass(FindClass(fname)).Create(Application) do
try
ShowModal;
finally
Free;
end;
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.
var
fc: TFormClass; {class of TForm, a class reference type}
form: TForm;
begin
fc := TFormClass(getClass(formclassnamefromdatabase));
if Assigned(fc) then
begin
form := fc.Create(Application);
try
form.ShowModal
finally
form.free
end;
end;
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:
unit GenericFormCreate;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, FileCtrl, Buttons, ExtCtrls;
type
TFrmGenericFormCreate = class(TForm)
BtnCreateFromString: TButton;
BtnCreateFromClass: TButton;
RgrSelect: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure BtnCreateFromStringClick(Sender: TObject);
procedure BtnCreateFromClassClick(Sender: TObject);
private
procedure CreateFromClass(AForm: TClass);
procedure CreateFromClassName(AForm: string);
public
end;
var
FrmGenericFormCreate: TFrmGenericFormCreate;
implementation
{$R *.DFM}
uses
Unit2, Unit3;
procedure TFrmGenericFormCreate.FormCreate(Sender: TObject);
begin
RgrSelect.ItemIndex := 0;
end;
procedure TFrmGenericFormCreate.CreateFromClass(AForm: TClass);
begin
with TFormClass(AForm).Create(Application) do
try
ShowModal;
finally
Release;
end;
end;
procedure TFrmGenericFormCreate.CreateFromClassName(AForm: string);
begin
try
with TFormClass(FindClass(AForm)).Create(Application) do
try
ShowModal;
finally
Release;
end;
except
ShowMessage(Format('Class %s not found', [AForm]));
end;
end;
procedure TFrmGenericFormCreate.BtnCreateFromStringClick(Sender: TObject);
begin
CreateFromClassName('TForm' + IntToStr(RgrSelect.ItemIndex + 2));
RgrSelect.SetFocus;
end;
procedure TFrmGenericFormCreate.BtnCreateFromClassClick(Sender: TObject);
begin
case RgrSelect.ItemIndex of
0: CreateFromClass(TForm2);
1: CreateFromClass(TForm3);
end;
RgrSelect.SetFocus;
end;
initialization
RegisterClasses([TForm2, TForm3]);
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése