I currently have a delphi 7 project sitting in front of me and what the original creators of the software have done is used the main form as a launch pad for another form which contains the actual controls and logic behind the entire application. So basically, form1 loads up, is set to invisible and another form (the form with all the UI controls and logic) is created and shown, its a strange way to do things, but its the way they did it.
Now I'm not familiar with the way delphi 7 handles its forms, but this second window, the window with all the controls on, whenever i click the minimise button, the form does not drop down to the taskbar as one would expect, but rather, resizes so that only the minimise, maximise and close buttons are visible and then places itself at the bottom left of the screen, just above the start menu.
the creation of this second window is:
frmPlatform := TfrmPlatform.Create(frmMain);
ModalResult := frmPlatform.ShowModal;
where frmMain is the invisible form.
My question is, why does the second window not minimize as one would expect and drop to the taskbar? and how do i get it to work,
thanks
Standard behaviour of forms I'm afraid as the mainform is by default the only form shown by Delphi on the taskbar. You can however set other forms to appear on the taskbar as well:
procedure TForm1.CreateParams
(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle
or WS_EX_APPWINDOW;
end;
And you can hide your current main form of course as well, see: http://delphi.about.com/od/adptips1999/qt/hidefromtaskbar.htm, and http://delphi.about.com/od/delphitips2008/qt/hide_taskbutton.htm for D2007 and up.
I think you will find that in standard Delphi apps only the main (first) form will be shown in the task bar. Since your main form is invisible that's your issue. The minimize is probably due to the second form being called with show modal rather than simply show.
Can you remove the first form or change which form is the main form? This can be done from the project settings page.
Related
When a form is opened with TForm.Show, and you click outside of this form, it will hide. On the VCL it doesn't happens.
I could use the property FormStyle set to StayOnTop, but it would not be good for the kind of application i'm building.
What could i do to solve this?
I had to set the Parent of the second form. Just like this:
SecondForm.Parent := MainForm;
Doing this, when you click on the MainForm, the focus is changed, but the second form doesn't hide behind the MainForm.
I've created an application which consists of a MainForm and several MDIChild Forms. I'm using AdvDockPanel and AdvToolbar from TMS' components. My main form has AdvDockPanels on Top, Bottom, Left and Right side of the Form to display AdvToolbars.
Each MDIChild Forms contains an AdvToolbar and at creation of theses forms the AdvToolbar.Parent is set to the AdvDockPanel on the MainForm. At first, the AdvToolbar.Visible is False and on activation of each MDIChild Form I'm setting it's visibilty to True.
To sum up, on activation of an MDIChild Form I want it's AdvToolbar to be displayed on MainForm.AdvDockPanel and on deactivation of it I want it to hide.
This all works fine except when I try to drag an AdvToolbar from one AdvDockPanel to an other will crossing the middle of my MainForm which makes my active MDIChild form hidden and that causes this error: "Cannot change Visible in OnShow or OnHide".
I've debugged it and found where this Exception is raised. It's in Vcl.Forms.
procedure TCustomForm.CMShowingChanged(var Message: TMessage);
So, I'd like to know if there is a way to display the AdvToolbar from my active MDIChild Form on the MainForm while being able to drag my toolbar all around in my MainForm.
Thanks,
Charles
You could check if the current parent of the toolbar is a TFloatingWindow (thats the parent when dragging the toolbar):
procedure TForm25.FormDeactivate(Sender: TObject);
begin
if not (orgaadvtoolbar1.Parent is TFloatingWindow) then
OrgaAdvToolBar1.visible:=false;
end;
TAdvToolBar.Dragging doesn't work because TAdvToolbar uses an own dragging flag FDraging but its not a property, so you could only access the variable if you modify the sourcecode of TMS Software.
I have a delphi application with multiple forms. Initially I had tried a setup where each newly opened form was a frame and the "parent" of this form (whichever called to open the form) was hidden as the child was shown with the child being resized and relocated to give a seamless effect of having one window, when the child is closed the parent is relocated and again made visible. All forms have a bsSingle border style for the Windows title block.
This approach worked well for positioning however the issue I have is a noticeable flicker as the parent form is closed and the child opened, and as there is a small time period where no form is opened the icon/tray on the start bar would shift around and itself become hidden and visible.
Does anybody have any advice on solving this problem? I thought perhaps if I only had one form with the border within the application and opened each new form within this border it would work better - though I am unsure how exactly to do this.
Any help is much appreciated.
It is easy to make one form appear as a child inside another. Create a new form which will contain and create your other forms:
procedure TMainForm.FormCreate(Sender: TObject);
var
F : TForm;
begin
F := TOneOfYourChildForms.Create(Self);
F.Parent := Self;
F.Show();
end;
Create both your child forms similar to this, then just do Show on the one you want to display and Hide on the other. Set BorderStyle to bsNone on the child forms to remove the caption. Turn off Auto-Create on your forms in project settings if you create them yourself like this instead.
I've had success with this design, and I think it helped to have the contents of the "main form" within a TFrame as well. When you want to show the main form, you would just perform a frame swap.
In Delphi XE Update 1, I’m getting seemingly random behavior of modal forms if the parent (main) form’s FormStyle is set to fsStayOnTop.
1) With MainFormOnTaskbar := False (the old way), everything “just works”. With the new MainFormOnTaskbar := True, modal forms get hidden behind the main form when the main form is set to “stay on top”. In most cases saying
modalForm.PopupParent := self;
just before the call to modalForm.ShowModal seems to help. But not always.
2) All my modal forms are simple, no frills, positioned at MainFormCenter, not using form inheritance, etc. And yet the PopupParent fix only works for about half of them, while the other half still get hidden behind the main form. Strangest of all, in one case the ordering of unrelated lines of code breaks or makes it. See lines marked (1) and (2) in this code:
procedure TEchoMainForm.DBMaintenancePrompt( actions : TMaintenanceActions );
var
frm : TDBMaintenanceForm;
begin
frm := TDBMaintenanceForm.Create( self );
try
frm.Actions := actions; // (1)
frm.PopupParent := self; // (2)
frm.ShowModal;
finally
frm.Free;
end;
end;
When executed in this order, the modal form shows correctly on top of the main form. But when I reverse the lines, the modal form hides behind main. The line marked (1) sets a property of the modal form, which results in several checkboxes being checked on unchecked in a TRzCheckGroup, sitting on a TRzPageControl (from Raize components). This is the setter method that runs when line (1) above executes:
procedure TDBMaintenanceForm.SetActions(const Value: TMaintenanceActions);
var
ma : TMaintenanceAction;
begin
for ma := low( ma ) to high( ma ) do
cgMaintActions.ItemChecked[ ord( ma )] := ( ma in Value );
end;
end;
This is enough for the modal form to show behind the main form if the order of the lines (1) and (2) is reversed.
This might point to TRzCheckGroup (which gets manipulated when the setter code runs), but I have two other forms that show the same problem and do not use TRzCheckGroup (or TRzPageControl). And I could not reproduce the problem with a separate sample app using Raize components. Disabling the form, the pagecontrol or the TRzCheckGroup for the duration of the setter has no effect.
It does not appear to be a timing issue, because when the modal form shows hidden once, it always does. The change in behavior only comes from rearranging the lines of code.
3) One last observation: my modal forms are fairly simple, so they get displayed pretty much instantly, with no visible delay. But when the main form is fsStayOnTop, then very often I can see the modal form show on top of it, then see it get “pushed” behind. Then, on hitting Esc, the (invisible) modal form shows on top of the main form for a fraction of a second, then gets closed.
Either I‘m missing something that’ll seem obvious in hindsight, or this is a call for psychic debugging, I don’t know. Any ideas, please?
UPDATE. I’ve tried to track down the problem on another form where it occurs. It has a few buttons (Raize) and a TSyntaxMemo (an enhanced memo component from eControl.ru). This form has almost nothing in common with the other forms that experience the problem. After removing parts of the code and testing, I can now reproduce the problem by making a tiny change in a method that assigns a string to the memo component:
This is my original code, which causes the form containing the editor to hide behind the main form:
procedure TEditorForm.SetAsText(const Value: string);
begin
Editor.Text := Value;
end;
When I change the assignment to an empty string, the form displays correctly:
procedure TEditorForm.SetAsText(const Value: string);
begin
Editor.Text := ''; // CRAZY! Problem goes away
end;
When I assign a single character to the editor, the form starts hiding again:
procedure TEditorForm.SetAsText(const Value: string);
begin
Editor.Text := 'a'; // Problem is back
end;
Of course the other two problematic forms do not use this editor component or any of its units.
I've tried deleting the memo control and adding it again (think creation order etc.), but it had no effect. Same if I create the memo in code. The form hides as soon as a non-empty string is assigned to the memo's Text property.
I had the same issue some time ago. My solution was to add a Self.BringToFront; to the OnShow event of the modal form.
Windows does not support many top most forms for app. And modal form is topmost by default. But you have this style for your own form.
One decision in mind: remove top most of your main form (no visible effect), call modal form, set back topmost style when modal finished.
Let's say I have form A that contains a panel (with many other controls in it) and a form B that it is empty.
Can I programmatically detach the panel from form A and move it in form B (and maybe back to form A)?
I know that I can change the Owner of the panel but does it work between different forms?
Update:
After some Googling I see that there is a ParentWindow property.
As noted by others, there are several problems with changing the parent window of a control without changing the ownership, and changing a controls owner can be difficult if it has multiple controls sitting on it...
One way around it is to use a frame instead. A frame owns all of it's sub-controls, so all you would need to do is change the owner and parent of the frame, and everything else will come along with it. This approach also allows you to keep all the event handlers and glue code in a single place as well.
N#
You have to take ownership into account, otherwise the destruction of form A would lead to the disappearance (i.e. destruction) of your panel on form B, or worse.
type
TForm2 = class(TForm)
public
InsertedPanel: TControl; // or TPanel
.
procedure RemoveComponents(AForm: TComponent; AControl: TWinControl);
var
I: Integer;
begin
for I := 0 to AControl.ControlCount - 1 do
begin
if AControl.Controls[I] is TWinControl then
RemoveComponents(AForm, TWinControl(AControl.Controls[I]));
if AControl.Controls[I].Owner = AForm then
AForm.RemoveComponent(AControl.Controls[I]);
end;
AForm.RemoveComponent(AControl);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Form2.InsertedPanel := Panel1;
Panel1.Parent := nil;
RemoveComponents(Self, Panel1);
Form2.InsertComponent(Form2.InsertedPanel); // < this is not necessary
Form2.InsertedPanel.Parent := Form2; // as long as Parent is set
Panel1 := nil; // or if you free the panel
end; // manually
The extra reference may seem a bit silly: Form2.InsertedPanel and Panel1 point to the same object, but it's kind of semantically preferred. Maybe a central controlled variable is better.
Update:
I falsely assumed that RemoveComponent cascaded to the child controls on the panel. It doesn't, of course, so only removing the panel from form A would leave all the child controls of the panel still owned by form A. So I added the RemoveComponents routine to remove ownership from all the child controls of the panel.
Note that the child controls of the panel don't have an owner at this time. But since they are parented controls of the panel, destruction of the panel will free those controls. So be sure the panel has a parent, or free the panel explicitly.
All of the above only applies to a design time created panel, placed design time on the form, which was my assumption. Since this changing parents behaviour is apparently wanted or needed, you might want to consider to implement it completely at runtime. To keep the abbility to design the panel designtime, I suggest to create a Frame on which you can design that panel, and jump the Frame around your forms.
You can easily have something appear as if it was a panel, and also as a form, by really using a TForm for what you would have used the panel for. Then dock the form at runtime into the place where you have a blank panel left for that purpose, and undock it at runtime, by the same manner.
You can't undock a TPanel and have it appear as a top-level form window, but you can take a top level form window and dock it in code. To get the appearance and functionality you want you must use the correct tools (TForm, in this case).
Incidentally, component libraries like Toolbar 2000 do allow floating toolbar windows based on toolbar panels, so if you really insist on having all the designtim elements remain in one form, at desigtime, you should look into how it works in Toolbar 2000. It has a lot of code in there to render the toolbar in "undocked/floating" mode, and to handle the mouse-driven docking and undocking of toolbars into toolbar docks.
If the panel and child components are created at runtime, you can just set the Parent of the Panel to FormB:
Panel1.Parent := FormB;
Note that FormB has to have been created already before you can do this.
For more info, see the Delphi Wiki page here.