BigRat
asked on
Pagecontrols, Splitter, StatusBar combination
I've been trying to get this dead right for some time now, but to no avail :(
I have a form which needs (from the top to the bottom) :-
PageControl1
Splitter
PageControl2
StatusBar
Currently I create the first three dynamically so as to get the splitter correct. I have no objection in creating everything dynamically if that helps.
The main problem is that if I set the TStatusBar.Visible property to false and then true it moves from being at the bottom of the screen to being attached to PageControl1 ABOVE the splitter!!!
I need it of course to reappear at the bottom.
I also want to hide PageControl2 and possible the splitter as well, in preparation for the next round of GUI development, so I don't want to waste time messing around trying out things.
Any help on this?
I have a form which needs (from the top to the bottom) :-
PageControl1
Splitter
PageControl2
StatusBar
Currently I create the first three dynamically so as to get the splitter correct. I have no objection in creating everything dynamically if that helps.
The main problem is that if I set the TStatusBar.Visible property to false and then true it moves from being at the bottom of the screen to being attached to PageControl1 ABOVE the splitter!!!
I need it of course to reappear at the bottom.
I also want to hide PageControl2 and possible the splitter as well, in preparation for the next round of GUI development, so I don't want to waste time messing around trying out things.
Any help on this?
Do you have / prefer to create stuff dynamically?
I played around with the stuff for you, made a quick dirty demo and everything seems to create on the fly fine.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
esting1: TMenuItem;
ClearAll1: TMenuItem;
CreateAll1: TMenuItem;
Clearstatusbar1: TMenuItem;
ClearPageControl21: TMenuItem;
ClearSplitter1: TMenuItem;
PageControls1: TMenuItem;
Splitter1: TMenuItem;
Statusbar1: TMenuItem;
CreatePageControl21: TMenuItem;
CreateSplitter1: TMenuItem;
CreateStatusbar1: TMenuItem;
CreatePagecontrol11: TMenuItem;
ClearPageControl11: TMenuItem;
procedure ClearAll1Click(Sender: TObject);
procedure CreateAll1Click(Sender: TObject);
procedure Clearstatusbar1Click(Sende r: TObject);
procedure ClearPageControl21Click(Se nder: TObject);
procedure ClearSplitter1Click(Sender : TObject);
procedure CreatePageControl21Click(S ender: TObject);
procedure CreateSplitter1Click(Sende r: TObject);
procedure CreateStatusbar1Click(Send er: TObject);
procedure CreatePagecontrol11Click(S ender: TObject);
procedure ClearPageControl11Click(Se nder: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
pg1, pg2: TPageControl;
sb: TStatusBar;
sp: TSplitter;
implementation
{$R *.dfm}
procedure TForm1.ClearAll1Click(Send er: TObject);
begin
if pg1 <> nil then
FreeAndNil(pg1);
if pg2 <> nil then
FreeAndNil(pg2);
if sb <> nil then
FreeAndNil(sb);
if pg1 <> nil then
FreeAndNil(sp);
end;
procedure TForm1.CreateAll1Click(Sen der: TObject);
begin
if pg1 = nil then
begin
pg1 := TPageControl.Create(Applic ation);
pg1.Parent := Form1;
pg1.Align := alTop
end;
if pg2 = nil then
begin
pg2 := TPageControl.Create(Applic ation);
pg2.Parent := Form1;
pg2.Align := alClient
end;
if sb = nil then
begin
sb := TStatusBar.Create(Applicat ion);
sb.Parent := Form1;
sb.Align := alBottom
end;
if sp = nil then
begin
sp := TSplitter.Create(Applicati on);
sp.Parent := Form1;
sp.Align := alTop
end;
end;
procedure TForm1.Clearstatusbar1Clic k(Sender: TObject);
begin
if sb <> nil then
FreeAndNil(sb);
end;
procedure TForm1.ClearPageControl21C lick(Sende r: TObject);
begin
if pg2 <> nil then
FreeAndNil(pg2);
end;
procedure TForm1.ClearSplitter1Click (Sender: TObject);
begin
if sp <> nil then
FreeAndNil(sp);
end;
procedure TForm1.CreatePageControl21 Click(Send er: TObject);
begin
if pg2 = nil then
begin
pg2 := TPageControl.Create(Applic ation);
pg2.Parent := Form1;
pg2.Align := alClient
end;
end;
procedure TForm1.CreateSplitter1Clic k(Sender: TObject);
begin
if sp = nil then
begin
sp := TSplitter.Create(Applicati on);
sp.Parent := Form1;
sp.Align := alTop
end;
end;
procedure TForm1.CreateStatusbar1Cli ck(Sender: TObject);
begin
if sb = nil then
begin
sb := TStatusBar.Create(Applicat ion);
sb.Parent := Form1;
sb.Align := alBottom
end;
end;
procedure TForm1.CreatePagecontrol11 Click(Send er: TObject);
begin
if pg1 = nil then
begin
if sp <> nil then
sp.Align := alBottom;
pg1 := TPageControl.Create(Applic ation);
pg1.Parent := Form1;
pg1.Align := alTop;
if sp <> nil then
sp.Align := alTop;
end;
end;
procedure TForm1.ClearPageControl11C lick(Sende r: TObject);
begin
if pg1 <> nil then
FreeAndNil(pg1);
end;
end.
object Form1: TForm1
Left = 268
Top = 145
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object MainMenu1: TMainMenu
Left = 80
Top = 40
object esting1: TMenuItem
Caption = 'Testing'
object CreateAll1: TMenuItem
Caption = 'Create All'
OnClick = CreateAll1Click
end
object ClearAll1: TMenuItem
Caption = 'Clear All'
OnClick = ClearAll1Click
end
end
object PageControls1: TMenuItem
Caption = 'PageControls'
object CreatePagecontrol11: TMenuItem
Caption = 'Create Pagecontrol1'
OnClick = CreatePagecontrol11Click
end
object CreatePageControl21: TMenuItem
Caption = 'Create PageControl2'
OnClick = CreatePageControl21Click
end
object ClearPageControl11: TMenuItem
Caption = 'Clear PageControl1'
OnClick = ClearPageControl11Click
end
object ClearPageControl21: TMenuItem
Caption = 'Clear PageControl 2'
OnClick = ClearPageControl21Click
end
end
object Splitter1: TMenuItem
Caption = 'Splitter'
object CreateSplitter1: TMenuItem
Caption = 'Create Splitter'
OnClick = CreateSplitter1Click
end
object ClearSplitter1: TMenuItem
Caption = 'Clear Splitter'
OnClick = ClearSplitter1Click
end
end
object Statusbar1: TMenuItem
Caption = 'Statusbar'
object CreateStatusbar1: TMenuItem
Caption = 'Create Statusbar'
OnClick = CreateStatusbar1Click
end
object Clearstatusbar1: TMenuItem
Caption = 'Clear status bar'
OnClick = Clearstatusbar1Click
end
end
end
end
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
esting1: TMenuItem;
ClearAll1: TMenuItem;
CreateAll1: TMenuItem;
Clearstatusbar1: TMenuItem;
ClearPageControl21: TMenuItem;
ClearSplitter1: TMenuItem;
PageControls1: TMenuItem;
Splitter1: TMenuItem;
Statusbar1: TMenuItem;
CreatePageControl21: TMenuItem;
CreateSplitter1: TMenuItem;
CreateStatusbar1: TMenuItem;
CreatePagecontrol11: TMenuItem;
ClearPageControl11: TMenuItem;
procedure ClearAll1Click(Sender: TObject);
procedure CreateAll1Click(Sender: TObject);
procedure Clearstatusbar1Click(Sende
procedure ClearPageControl21Click(Se
procedure ClearSplitter1Click(Sender
procedure CreatePageControl21Click(S
procedure CreateSplitter1Click(Sende
procedure CreateStatusbar1Click(Send
procedure CreatePagecontrol11Click(S
procedure ClearPageControl11Click(Se
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
pg1, pg2: TPageControl;
sb: TStatusBar;
sp: TSplitter;
implementation
{$R *.dfm}
procedure TForm1.ClearAll1Click(Send
begin
if pg1 <> nil then
FreeAndNil(pg1);
if pg2 <> nil then
FreeAndNil(pg2);
if sb <> nil then
FreeAndNil(sb);
if pg1 <> nil then
FreeAndNil(sp);
end;
procedure TForm1.CreateAll1Click(Sen
begin
if pg1 = nil then
begin
pg1 := TPageControl.Create(Applic
pg1.Parent := Form1;
pg1.Align := alTop
end;
if pg2 = nil then
begin
pg2 := TPageControl.Create(Applic
pg2.Parent := Form1;
pg2.Align := alClient
end;
if sb = nil then
begin
sb := TStatusBar.Create(Applicat
sb.Parent := Form1;
sb.Align := alBottom
end;
if sp = nil then
begin
sp := TSplitter.Create(Applicati
sp.Parent := Form1;
sp.Align := alTop
end;
end;
procedure TForm1.Clearstatusbar1Clic
begin
if sb <> nil then
FreeAndNil(sb);
end;
procedure TForm1.ClearPageControl21C
begin
if pg2 <> nil then
FreeAndNil(pg2);
end;
procedure TForm1.ClearSplitter1Click
begin
if sp <> nil then
FreeAndNil(sp);
end;
procedure TForm1.CreatePageControl21
begin
if pg2 = nil then
begin
pg2 := TPageControl.Create(Applic
pg2.Parent := Form1;
pg2.Align := alClient
end;
end;
procedure TForm1.CreateSplitter1Clic
begin
if sp = nil then
begin
sp := TSplitter.Create(Applicati
sp.Parent := Form1;
sp.Align := alTop
end;
end;
procedure TForm1.CreateStatusbar1Cli
begin
if sb = nil then
begin
sb := TStatusBar.Create(Applicat
sb.Parent := Form1;
sb.Align := alBottom
end;
end;
procedure TForm1.CreatePagecontrol11
begin
if pg1 = nil then
begin
if sp <> nil then
sp.Align := alBottom;
pg1 := TPageControl.Create(Applic
pg1.Parent := Form1;
pg1.Align := alTop;
if sp <> nil then
sp.Align := alTop;
end;
end;
procedure TForm1.ClearPageControl11C
begin
if pg1 <> nil then
FreeAndNil(pg1);
end;
end.
object Form1: TForm1
Left = 268
Top = 145
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object MainMenu1: TMainMenu
Left = 80
Top = 40
object esting1: TMenuItem
Caption = 'Testing'
object CreateAll1: TMenuItem
Caption = 'Create All'
OnClick = CreateAll1Click
end
object ClearAll1: TMenuItem
Caption = 'Clear All'
OnClick = ClearAll1Click
end
end
object PageControls1: TMenuItem
Caption = 'PageControls'
object CreatePagecontrol11: TMenuItem
Caption = 'Create Pagecontrol1'
OnClick = CreatePagecontrol11Click
end
object CreatePageControl21: TMenuItem
Caption = 'Create PageControl2'
OnClick = CreatePageControl21Click
end
object ClearPageControl11: TMenuItem
Caption = 'Clear PageControl1'
OnClick = ClearPageControl11Click
end
object ClearPageControl21: TMenuItem
Caption = 'Clear PageControl 2'
OnClick = ClearPageControl21Click
end
end
object Splitter1: TMenuItem
Caption = 'Splitter'
object CreateSplitter1: TMenuItem
Caption = 'Create Splitter'
OnClick = CreateSplitter1Click
end
object ClearSplitter1: TMenuItem
Caption = 'Clear Splitter'
OnClick = ClearSplitter1Click
end
end
object Statusbar1: TMenuItem
Caption = 'Statusbar'
object CreateStatusbar1: TMenuItem
Caption = 'Create Statusbar'
OnClick = CreateStatusbar1Click
end
object Clearstatusbar1: TMenuItem
Caption = 'Clear status bar'
OnClick = Clearstatusbar1Click
end
end
end
end
ASKER
>>and it works corrrectly.
First I presume you mean alTop etc.. Secondly I forgot to say that I have a toolbar on the form, which is aligned alTop. So the sequence should be :
ToolBar
PageControl1
Splitter
PageControl2
StatusBar
The lower half of the screen should disappear, because I need to introduce a component palette under the toolbar.
I did the changes and I got :-
PageControl1
ToolBar
PageControl2
StatusBar
the splitter seems to be inactive. Mind you the hiding/showing of the StatusBar is great!
Do you need to create the components in the correct order? I create PageControl1, PageControl2 and then Splitter.
>>Do you have / prefer to create stuff dynamically?
Basically a dynamic creation is not a bad idea, since the main form is cluttered with lots of other components and all this "bring to front" crap just to change a property is a pain. The ToolBar however has lots of buttons on it so I'd rather not change that.
First I presume you mean alTop etc.. Secondly I forgot to say that I have a toolbar on the form, which is aligned alTop. So the sequence should be :
ToolBar
PageControl1
Splitter
PageControl2
StatusBar
The lower half of the screen should disappear, because I need to introduce a component palette under the toolbar.
I did the changes and I got :-
PageControl1
ToolBar
PageControl2
StatusBar
the splitter seems to be inactive. Mind you the hiding/showing of the StatusBar is great!
Do you need to create the components in the correct order? I create PageControl1, PageControl2 and then Splitter.
>>Do you have / prefer to create stuff dynamically?
Basically a dynamic creation is not a bad idea, since the main form is cluttered with lots of other components and all this "bring to front" crap just to change a property is a pain. The ToolBar however has lots of buttons on it so I'd rather not change that.
>Do you need to create the components in the correct order?
I think so. not sure though.
what about the toolbar? is it created after pagecontrol1? if so, create it before.
also, you can try placing the toolbar at position -1,-1 on the form after showing pagecontrol1 so that it will be the first one.
I think so. not sure though.
what about the toolbar? is it created after pagecontrol1? if so, create it before.
also, you can try placing the toolbar at position -1,-1 on the form after showing pagecontrol1 so that it will be the first one.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
>>If you want to align them correctly you will have to create them in the right order.
Yes, but what is the order? I create all except the ToolBar and the StatusBar in the Form's OnCreate event handler. I have aligned the StatusBar as alBottom and the ToolBar as alTop in the Object Inspector at design time.
Currently I have the tool bar in the middle of the screen and a non-visible splitter which drags the top of the second page control.
>>group sets of components on Panels
Yes, I could do this with PageControl1 and the ToolBar since they "almost" belong to each other. The problem is, the Component palette must come between them, so I'd have the same problem on the Panel.
What of course I don't understand is how all this allocation works!
Yes, but what is the order? I create all except the ToolBar and the StatusBar in the Form's OnCreate event handler. I have aligned the StatusBar as alBottom and the ToolBar as alTop in the Object Inspector at design time.
Currently I have the tool bar in the middle of the screen and a non-visible splitter which drags the top of the second page control.
>>group sets of components on Panels
Yes, I could do this with PageControl1 and the ToolBar since they "almost" belong to each other. The problem is, the Component palette must come between them, so I'd have the same problem on the Panel.
What of course I don't understand is how all this allocation works!
Im a bit unsure how to explain it further.
Try adding/deleting components at design time, modifying their align properties etc etc.
You will see that if you start aligning things in the wrong order, everything will start going to the wrong places.
So you are basically working out the order of adding/deleting at design time, then replicate it during runtime.
All I can suggest is play around.
There are many good coders out there, but creating a good GUI is an art all of its own.
I have seen many good coded applications, but many that had GUI's I wouldnt let a monkey touch :o)
Try adding/deleting components at design time, modifying their align properties etc etc.
You will see that if you start aligning things in the wrong order, everything will start going to the wrong places.
So you are basically working out the order of adding/deleting at design time, then replicate it during runtime.
All I can suggest is play around.
There are many good coders out there, but creating a good GUI is an art all of its own.
I have seen many good coded applications, but many that had GUI's I wouldnt let a monkey touch :o)
ASKER
>>but creating a good GUI is an art all of its own
It shouldn't be. The semantics of the thing is not described in the Help file, nor any documentation I've seen as yet.
>>All I can suggest is play around.
That is precisely twhat I did not want to do therefore asked here!
So far I've got this :-
ToolBar - design time alTop anchored top & left/right
PageControl1 - run time alClient anchored top? left&right
PageControl2 - run time alBottom default anchoring
Splitter - run time alBottom default anchoring
StatusBar - design time alBottom anchored bottom left&right
Starts up normally, with all components properly placed.
Toggle visibility of PageControl2 works perfectly, but splitter seems active and expands the StatusBar.
Toggle visbility of StatusBar causes it to reappear above PageControl2 and hanging on to the splitter, so that it gets expanded by it.
I'm still googling for a tutorial on all of this, but that seems hopeless!
It shouldn't be. The semantics of the thing is not described in the Help file, nor any documentation I've seen as yet.
>>All I can suggest is play around.
That is precisely twhat I did not want to do therefore asked here!
So far I've got this :-
ToolBar - design time alTop anchored top & left/right
PageControl1 - run time alClient anchored top? left&right
PageControl2 - run time alBottom default anchoring
Splitter - run time alBottom default anchoring
StatusBar - design time alBottom anchored bottom left&right
Starts up normally, with all components properly placed.
Toggle visibility of PageControl2 works perfectly, but splitter seems active and expands the StatusBar.
Toggle visbility of StatusBar causes it to reappear above PageControl2 and hanging on to the splitter, so that it gets expanded by it.
I'm still googling for a tutorial on all of this, but that seems hopeless!
All correct except I would align the splitter to alTop to hang off the bottom of pagecontrol1
As for my point about GUI design, I do believe it is an art form.
What your doing here is just trying to work out where to link things correctly,
what I meant about my comment is just general design, understanding visually how things look and how useful to a user they are.
As for my point about GUI design, I do believe it is an art form.
What your doing here is just trying to work out where to link things correctly,
what I meant about my comment is just general design, understanding visually how things look and how useful to a user they are.
ASKER
>>All correct except I would align the splitter to alTop to hang off the bottom of pagecontrol1
When I do that the splitter does not apear on the screen and pagecontrol2 is no longer sizable.
I accept that GUI design is an art form. What I find annoying - after searching the web last night - is that I cannot find a decent explaination of how all this works. I believe that the problem lies in the Splitter. First this silly object does not take the two objects which it should split and the object which is the parent. I don't understand what creation order has to do with VISIBILITY!
The obvious way of doing all of this would be for the splitter to have alClient alignment in the parent and two children each having alTop and alBottom alignment. If one child is invisible the splitter gives the client area to the other. Perhaps you're right and I should put a Panel on the form between the ToolBar and the Status bar and on the panel the page controls and the splitter. I might even look for an alternative splitter control, which is more explicit. If I get time this weekend I'll do the changes and report back here.
When I do that the splitter does not apear on the screen and pagecontrol2 is no longer sizable.
I accept that GUI design is an art form. What I find annoying - after searching the web last night - is that I cannot find a decent explaination of how all this works. I believe that the problem lies in the Splitter. First this silly object does not take the two objects which it should split and the object which is the parent. I don't understand what creation order has to do with VISIBILITY!
The obvious way of doing all of this would be for the splitter to have alClient alignment in the parent and two children each having alTop and alBottom alignment. If one child is invisible the splitter gives the client area to the other. Perhaps you're right and I should put a Panel on the form between the ToolBar and the Status bar and on the panel the page controls and the splitter. I might even look for an alternative splitter control, which is more explicit. If I get time this weekend I'll do the changes and report back here.
the order for it to work properly should be
ToolBar - design time alTop
PageControl1 - run time alTop
Splitter - run time alTop
PageControl2 - run time alClient
StatusBar - design time alBottom
ToolBar - design time alTop
PageControl1 - run time alTop
Splitter - run time alTop
PageControl2 - run time alClient
StatusBar - design time alBottom
ASKER
Yes, Mike, that would be logical, but that combination - at least in my implementation - gets the ToolBar stuck in the middle of the screen.
At the moment I only have the problem of the status bar ending up in the middle of the screen after you hide and show it. As I primarily wanted the Message area to disappear that is not so bad.
At the moment I only have the problem of the status bar ending up in the middle of the screen after you hide and show it. As I primarily wanted the Message area to disappear that is not so bad.
ASKER
I create a panel and gave it alClient between the ToolBar and the StatusBar. On this client I created the two PageControls and the Splitter. Everything works perfectly when I hide/show the StatusBar and the lower PageControl, and irrespectively of whether one does alTop or alBottom!
alternativly, just set teh align property correctly.
I have tested with:
pagecontrol1.align=top
splitter.align=top
pagecontrol2.align=client
and it works corrrectly.