I have a Delphi application that has a document browser as the main form. When the user opens a document, we open an editor window. We want to have each editor with a button on
Sorry if this is really stupid, but you don't have the formstyle set to fsStayOnTop do you? This would explain this behaviour.
perhaps add this in the createparams
Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;
or try this anywhere in the code. I presonally use it on the forms .OnCreate event.
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;
the downside of this is that if the main form is minimized the other forms hide aswell, but restore when the main form does.
My application works in the way you describe. Here is the approach I took. I would have liked to find a simpler approach but never did.
I started out by reading these articles. This first one is an great write up by Peter Below:
http://groups-beta.google.com/group/borland.public.delphi.winapi/msg/e9f75ff48ce960eb?hl=en
Other information was also found here, however this did not prove to be a valid solution: for my use: http://blogs.teamb.com/DeepakShenoy/archive/2005/04/26/4050.aspx
Eventually here is what I ended up with.
My splash screen doubles as the Application Main form. The Main form has a special tie to the Application Object. Using all secondary forms gets me the behavior that I was looking for.
In each form that I want on the task bar I override CreateParams. I do this on my edit forms and what the users sees as the "main form"
procedure TUaarSalesMain.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := GetDesktopWindow;
end;
My "Main" form as far as Delphi is concerned loads the true main form in its Activitate function. I use a member variable to keep track of the first activate. Then at the end of the function I hide the splash form, but do not close it. This was important for me because if the user was editing a document and closed the main form I did not want the edit screens to be forced closed at the same time. This way all of the visible forms are treated the same.
if FFirstActivate = false then
exit;
FFristActivate := false;
/*
Main Load code here
Update Splash label, repaint
Application.CreateForm
etc.
*/
// I can't change visible here but I can change the size of the window
Self.Height := 0;
Self.Width := 0;
Self.Enabled := false;
// It is tempting to set Self.Visible := false here but that is not
// possible because you can't change the Visible status inside this
// function. So we need to send a message instead.
ShowWindow(Self.Handle, SW_HIDE);
end;
But there is still a problem. You need the main/splash window to close when all other forms are closed. I have an extra check in my close routines for Parent <> nil because I use forms as plugins (form my purposes they work better than frames).
I didn't really like using the Idle event, but I don't notice this being a drag on the CPU.
{
TApplicationManager.ApplicationEventsIdle
---------------------------------------------------------------------------
}
procedure TApplicationManager.ApplicationEventsIdle(Sender: TObject;
var Done: Boolean);
begin
if Screen.FormCount < 2 then
Close;
end;
{
TApplicationManager.FormCloseQuery
---------------------------------------------------------------------------
}
procedure TApplicationManager.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
var
i: integer;
begin
for i := 0 to Screen.FormCount - 1 do
begin
if Screen.Forms[i] <> self then
begin
// Forms that have a parent will be cleaned up by that parent so
// ignore them here and only attempt to close the parent forms
if Screen.Forms[i].Parent = nil then
begin
if Screen.Forms[i].CloseQuery = false then
begin
CanClose := false;
break;
end;
end;
end;
end;
end;
{
TApplicationManager.FormClose
---------------------------------------------------------------------------
}
procedure TApplicationManager.FormClose(Sender: TObject;
var Action: TCloseAction);
var
i: integer;
begin
for i := Screen.FormCount - 1 downto 0 do
begin
if Screen.Forms[i] <> self then
begin
// Forms that have a parent will be cleaned up by that parent so
// ignore them here and only attempt to close the parent forms
if Screen.Forms[i].Parent = nil then
begin
Screen.Forms[i].Close;
end;
end;
end;
end;
This has served me well so far. I did make a small change for Vista because the icon for my "Main/Splash" screen was still showing. I don't remember what that was though. I probably don't need to set width, height, enabled, and send the hide message on the splash screen. I just wanted to make sure it didn't show up :-).
Dealing with the close events was necessary. If I remember correctly that was needed for when windows sent a shutdown message. I think only the main form gets that message.