Choose MainForm from a list of available forms - delphi

Is it possible to choose a form (as a mainform) from a list of "available" forms after connecting to the database ? I have a datamodule with 3 'available' forms.No mainform for the time being.Datamodule is created first. Now, I would like to select the form depending on the database the user logs in to, and make it the mainform. Can this be done and how ?

You can easily do something like that in the DPR.
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {DM1: TDataModule},
Unit3 in 'Unit3.pas' {Form2};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TDM1, DM1);
case DM1.ChooseForm of
1: Application.CreateForm(TForm1, Form1);
else Application.CreateForm(TForm2, Form2);
end;
Application.Run;
end.
In this example you first create the datamodule. When it's created you can use the logic in the datamodule. In the datamodule I made a public function that returns an integer to determine which form to load. (In practice I would not rely on magic numbers)

The main form is deemed to be the first form created by a call to Application.CreateForm. So add your selection logic to the .dpr file code, and then call Application.CreateForm to create whichever form the user selects.
// .dpr code
begin
Application.Initialize;
CreateMainForm;
Application.Run;
end.
Here, CreateMainForm is provided by you and implements the user form selection. It might go like this:
procedure CreateMainForm;
var
Form: TForm;
FormClass: TFormClass;
begin
FormClass := ChooseMainFormClass;
Application.CreateForm(FormClass, Form);
end;
Again, ChooseMainFormClass is provided by you.

Related

MDIChild form cannot be created

Have a main form (Form1) where is created a MDIForm (Form2) and a MDIChild (Form3) form respectivelly in execution time. In my tests the MDIForm (Form2) is show like expected but when try show the MDIChild (Form3) i get the following error that say:
Cannot create form. No mdi forms are currently active
Some idea about how fix this?
program Project1;
uses
Vcl.Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2},
Unit3 in 'Unit3.pas' {Form3};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Form:
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Unit2, Unit3;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(Self);
Form2.Show;
Form3 := TForm3.Create(Form2);
Form3.Show;
end;
end.
The VCL (not the Win32 API) is hard-coded to allow only the Application.MainForm to be set to fsMDIForm for hosting fsMDIChild Forms. Your MainForm is not the fsMDIForm parent Form, which is why you are getting the error.
Using a secondary Form as the fsMDIForm parent is technically possible, but not out of the box. It requires a bit of manual work hacking up the VCL's internals to make it work, and even then there are holes and gotchas. See my Multiple MDI Parent Forms in a single Application submission on CodeCentral for an example (I haven't updated it in over a decade, so it may need some tweaking for modern VCL versions). The old Quality Central (not Quality Portal!) ticket it refers to can be found on archive.org: #12006: Hosting MDI child forms in non-MainForm forms.
That being said, MDI is a dead technology, Microsoft abandoned it a long time ago, and modern Windows versions have poor support for MDI, especially when Visual Styles are used. You are best off not even bothering with MDI in modern software, there are other/better UI design choices available.

TChromium : How to keep session alive

When using DCEF3 TChromium, how can i keep the session alive ?
For instance, if i go to a web-site and login on it, when i close my app and open it again, i need to login again. I want to keep the session alive, just like it would be if i use Google Chrome.
I tried to add 'CefLib' on my app 'uses' clause and set 'CefCache' like the code below, but although i can see files being stored on 'cookies' folder, it seems to make no difference in keeping the session alive :
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
ceflib in 'C:\app\dcef\src\ceflib.pas';
{$R *.res}
begin
CefCache := 'cookies';
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Thanks in advance.
A guy form the official's DCEF3 forum provided the solution below, tested and approved !
CookieManager: ICefCookieManager;
FormCreate:
begin
CookiesPath := ExtractFilePath(Application.ExeName) + 'cookies';
CookieManager := TCefCookieManagerRef.Global(nil);
CookieManager.SetStoragePath(CookiesPath, True, nil);
end;
FormClose:
begin
CookieManager.FlushStore(nil);
end

COM Server application and GetObject - reusing the running application

I'm trying to automate an application (Windows 8, Delphi XE.) For my testing I'm doing the following:
Created a small test application, consisting of a form and a memo (Form1)
Added a new ActiveX Object, CoClass name TestOLE, Threading mode Apartment, Instancing Multiple (as per this article.)
Added one method Method1 which only adds some text to the memo control in Form1
I then start the application and double click on a file named test.vbs which contains the following code:
dim obj
set obj = GetObject("", "Project1.TestOLE")
obj.AddSomeText "Hola mundo"
When the application is running, I see that a new form is created, the text is added and then it exits.
What I want to accomplish is that the opened application should have its memo text changed.
I've repeated creating new projects with both MultipleInstance and SingleInstance, and in an outburst of heuristic anger, I even changed the threading model to single, to no avail.
I see two flags in the type library editor: "Replaceable" and "Aggregatable." However, selecting "Replaceable" ends up in an error in the generated RIDL file.
I've been reading a lot about GetObject. It appears that its documentation is even wrong (it says you can omit the first parameter but I've found that doesn't work).
Is this the right way to write an automation server in Delphi that can be reused?
Well, I got it working (I hope.)
Reading more of the same article cited above, found the following:
Know how to implement servers that support GetActiveObject.
Adding a global object, and registering in the Running Object Table (ROT) accomplishes the desired task of having the COM call passed to the running application:
Project file:
program TestOLEProject3;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
TestOLEProject3_TLB in 'TestOLEProject3_TLB.pas',
Unit2 in 'Unit2.pas' {TestOLE: CoClass},
Unit3 in 'Unit3.pas';
{$R *.TLB}
{$R *.res}
begin
Application.Initialize;
RegisterGlobalTestOLE;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Unit2.pas:
unit Unit2;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
ComObj, ActiveX, TestOLEProject3_TLB, StdVcl;
type
TTestOLE = class(TAutoObject, ITestOLE)
protected
procedure Method1; safecall;
procedure Quit; safecall;
end;
implementation
uses ComServ, Unit1, Unit3;
procedure TTestOLE.Method1;
begin
Form1.Memo1.Lines.Add('Wheeee');
end;
procedure TTestOLE.Quit;
begin
RevokeGlobalTestOLE;
end;
initialization
TAutoObjectFactory.Create(ComServer, TTestOLE, CLASS_TestOLE, ciMultiInstance,
tmApartment);
end.
Unit3.pas (functions to register and unregister the global object):
unit Unit3;
interface
procedure RegisterGlobalTestOLE;
procedure RevokeGlobalTestOLE;
implementation
uses TestOLEProject3_TLB, ComObj, ActiveX;
var
GlobalTestOLEHandle: longint = 0;
procedure RegisterGlobalTestOLE;
var
GlobalTestOLE: ITestOLE;
begin
GlobalTestOLE := CoTestOLE.Create;
OleCheck(RegisterActiveObject(GlobalTestOLE, CLASS_TestOLE,
ACTIVEOBJECT_STRONG, GlobalTestOLEHandle));
end;
procedure RevokeGlobalTestOLE;
begin
if (GlobalTestOLEHandle <> 0) then
begin
OleCheck(RevokeActiveObject(GlobalTestOLEHandle, nil));
GlobalTestOLEHandle := 0;
end;
end;
end.

Form not minimizing properly [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to minimize a window to the taskbar? (i.e. not iconify)
I want to show some form before showing the main form in my app, I do:
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
with TForm2.Create(Application) do
try
ShowModal;
finally
Free;
end;
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
It's working properly but when I minimizing first form (TForm2) it's doing something like this (not minimizing to taskbar):
What's wrong?
Try to Hide it before you Free first. I don't know but if your first form is an authentication form maybe you could also use ModalResult to be sure that the user's response was ok.
Hope this helps.

How can I display a form for set configuration before the main form?

in my project i have two form's(form1,form2), form1 is configuration form.
i want to show Form1 and when we click Button1 then show Form2 and free(Release) Form1. how can to i do this?
i use this code. but this project start and then exit automatically.A Friend said because the application message loop never start, and application terminates because main form does not exist. how i can to solve this problem?
uses Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Release;
end;
///
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Form1:= TForm1.Create(Application);
Application.Run;
end.
Do exactly what you asked in the question title: Create and show the configuration form, and then create and show the main form. The trick is in how you create them. Only use Application.CreateForm for the one form that you want to be your main form. Use the ordinary object creation technique for all other forms.
Modify your DPR file like so:
var
ConfigForm: TConfigForm;
begin
Application.Initialize;
ConfigForm := TConfigForm.Create(nil);
try
if ConfigForm.ShowModal <> mrOK then
exit;
finally
ConfigForm.Free;
end;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
You need to create Form2 first and this will be your main form. You want it to start hidden and be shown after Form1 has done its job. Something like this:
uses Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
Release;
end;
///
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm2, Form2);
Form2.Hide;
Form1 := TForm1.Create(Application);
Form1.Show;
Application.Run;
end.
The reason is that the app terminates when your main form closes. And your main form is typically the first one that you create.
You can prohibit Form1 to be shown by setting ShowMainForm to false. Leave the code in the DPR just as the IDE creates it:
uses
Forms,
Unit2 in 'Unit2.pas' {Form2},
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
In the FormCreate event of Form2 just set ShowMainForm to false and call Show to make Form2 visible:
procedure TForm2.FormCreate(Sender: TObject);
begin
Application.ShowMainForm := False;
Show;
end;
and in the ButtonClick event of Form2 show Form1 and close Form2:
procedure TForm2.Button1Click(Sender: TObject);
begin
Form1.Show;
Close;
end;
This keeps all necessary changes inside unit2.
Edit
Some remarks that came to mind after sleeping a night over it:
Form2 should be the last one auto-created, i.e. the one directly before the Application.Run statement.
The Form1.Show statement in the ButtonClick event should be moved to the FormClose event. Thus the user can close the form with the Windows close button or whatever he likes best.
If for some reason Form1 should never be shown, some code must be added to close the application. A Halt may serve here.

Resources