Link to home
Start Free TrialLog in
Avatar of BigRat
BigRatFlag for France

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?
Avatar of 2266180
2266180
Flag of United States of America image

well ... you could place the pagecontrol/splitter and pagecontrol in a panel :)
alternativly, just set teh align property correctly.
I have tested with:
pagecontrol1.align=top
splitter.align=top
pagecontrol2.align=client

and it works corrrectly.
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(Sender: TObject);
    procedure ClearPageControl21Click(Sender: TObject);
    procedure ClearSplitter1Click(Sender: TObject);
    procedure CreatePageControl21Click(Sender: TObject);
    procedure CreateSplitter1Click(Sender: TObject);
    procedure CreateStatusbar1Click(Sender: TObject);
    procedure CreatePagecontrol11Click(Sender: TObject);
    procedure ClearPageControl11Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

  pg1, pg2: TPageControl;
  sb: TStatusBar;
  sp: TSplitter;

implementation

{$R *.dfm}

procedure TForm1.ClearAll1Click(Sender: 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(Sender: TObject);
begin
  if pg1 = nil then
  begin
    pg1 := TPageControl.Create(Application);
    pg1.Parent := Form1;
    pg1.Align := alTop
  end;
  if pg2 = nil then
  begin
    pg2 := TPageControl.Create(Application);
    pg2.Parent := Form1;
    pg2.Align := alClient
  end;
  if sb = nil then
  begin
    sb := TStatusBar.Create(Application);
    sb.Parent := Form1;
    sb.Align := alBottom
  end;
  if sp = nil then
  begin
    sp := TSplitter.Create(Application);
    sp.Parent := Form1;
    sp.Align := alTop
  end;
end;

procedure TForm1.Clearstatusbar1Click(Sender: TObject);
begin
  if sb <> nil then
    FreeAndNil(sb);
end;

procedure TForm1.ClearPageControl21Click(Sender: TObject);
begin
  if pg2 <> nil then
    FreeAndNil(pg2);
end;

procedure TForm1.ClearSplitter1Click(Sender: TObject);
begin
  if sp <> nil then
    FreeAndNil(sp);
end;

procedure TForm1.CreatePageControl21Click(Sender: TObject);
begin
  if pg2 = nil then
  begin
    pg2 := TPageControl.Create(Application);
    pg2.Parent := Form1;
    pg2.Align := alClient
  end;
end;

procedure TForm1.CreateSplitter1Click(Sender: TObject);
begin
  if sp = nil then
  begin
    sp := TSplitter.Create(Application);
    sp.Parent := Form1;
    sp.Align := alTop
  end;
end;

procedure TForm1.CreateStatusbar1Click(Sender: TObject);
begin
  if sb = nil then
  begin
    sb := TStatusBar.Create(Application);
    sb.Parent := Form1;
    sb.Align := alBottom
  end;
end;

procedure TForm1.CreatePagecontrol11Click(Sender: TObject);
begin
  if pg1 = nil then
  begin
    if sp <> nil then
      sp.Align := alBottom;

    pg1 := TPageControl.Create(Application);
    pg1.Parent := Form1;
    pg1.Align := alTop;

    if sp <> nil then
      sp.Align := alTop;    
  end;
end;

procedure TForm1.ClearPageControl11Click(Sender: 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
Avatar of BigRat

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.
>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.
ASKER CERTIFIED SOLUTION
Avatar of Mike Littlewood
Mike Littlewood
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of BigRat

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!
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)
Avatar of BigRat

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!


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.
Avatar of BigRat

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.
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
Avatar of BigRat

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.
Avatar of BigRat

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!