I have this problem. When I hide my main form, then the taskbar icon of my application is also hidden. I saw a new question about this problem as well and the answers didn't really help. They suggested to minimize it, but I do not want to minimize the application.
Is it possible to change the main form while the application is already running?
for instance. I have two forms. when I want to hide the one form and show the other form, then the taskbar icon should stay at the taskbar and the main form should switch to the other form.
I am using Delphi XE6 and it is a VCL Forms application.
I have also seen a different old question about changing main form while runtime, but it is very old and still based on Delphi 6.
If you set
Application.MainFormOnTaskbar
to false in your startup routine (in the.dpr
file), then the VCL will create a hidden form whose sole purpose is to provide the taskbar icon. This is an older approach and is generally not recommended, but as long as other windows are visible, it would let you hide your main form without the application disappearing from the taskbar.You can also provide an
Application.OnGetMainFormHandle
event handler to change yourApplication.MainFormHandle
at runtime (but notApplication.MainForm
).MainFormHandle
affects stuff like the owner of modal popup dialogs.More information on
Application.MainFormOnTaskbar
and the disadvantages of disabling it: This gets complicated in a hurry. The short version is in the VCL docs, which explain that several of Windows' newer features (like live taskbar thumbnails) that were introduced in Vista requireMainFormOnTaskbar := True
. There's a lot more background reading in this SO discussion.I implemented this in the same way @DavidHeffernan had already suggested and as yet have not come across any issues, it might not be the best way but it worked for me and what i was trying to achieve, which was have "normal" feeling behaviour when the user minimised their MainWork form.
Code looked similar to this:
hope this helps :-)
As David Heffernan already said it is not possible to change the Main Form of an already running application. This is the limitation of the windows itself.
What you can do is cheat and never actually change the Main Form but only make it look like you did.
How do you achieve that?
Step 1: Add code to the second Form to make its own Taskbar button
Step 2: Dynamically create the second Form just before switching to it. Upon its creation previously added code will create a new Taskbar button for your second form.
Step 3: Now hide you actual Main Form. Hiding it will also hide the Taskbar button belonging to it. So you end up still having one Taskbar button shown and it is the one belonging to your second Form.
Step 4: In order to allow your second Form to terminate your application at its closure call Close method of your true Main Form from your second Forms OnClose or OnFormCloseQuery event.
If you wanna be able to switch back to your true Main Form call Show method of your Main Form instead of Close method.
This approach allows us of swapping forms pretty quickly so only most keen users will notice short animation of Taskbar button.
NOTE: If your second for is a complex one and because of that takes some time to create you might wanna create it hidden and then once its creation process is finished show it and do the swap. Otherwise you might end up with two Taskbar buttons being shown at same time which I believe you wanna avoid.
Here is a short example:
- LoginForm is a true Main Form that is created at the application startup - WorkForm is the Form on which user will spend most of time after logging in and this one is created in login process
Login Form code:
Work form code:
I've had an additional issue working with Delphi XE2 MDI apps that are also COM servers. My main form Main calls a secondary form MenuForm which contains shared icons and popup menus for the whole app.
In my example, the app works perfectly when run standalone.
Main gets created, and then creates a MenuForm at the end of FormCreate. All good.
But when called from a COM server, Main.FormCreate is called first, but somehow MenuForm gets assigned to Application.MainForm. There is a race condition in the underlying RTL. This causes havoc when trying to create the first SDI child, as Application.MainForm is not MDI.
I tried working around this by Main.FormCreate posting a message back to itself, to delay creation of MenuForm until after Main.FormCreate has returned.
But there is still a race condition here - MenuForm was still assigned to Application.MainForm.
I was eventually able to work around this using code to poll Application.MainForm every 10ms, with a maximum of 10 seconds. I also had to remove any reference in Main to MenuForm's icon list (in the .dfm) until after MenuForm was created explicitly - otherwise MenuForm would get created implicitly at the end of MainForm.create.
Hope this helps someone!
You can change main form. Do a variable F: ^TForm, then set it to @Application.MainForm. After that you can set main form as via F^ := YourAnotherForm.
It is not possible to change the VCL main form whilst the program is running. This property is determined once and for all when the program starts.
One possible way to proceed for you is to arrange for the secondary form, the form that is not the main form, to have a button on the taskbar. Do that by making it unowned, or by using the
WS_EX_APPWINDOW
extended window style.Update
Well, you can change
Application.MainForm
, but it requires you to destroy the current main form, and then create a new one.