Avatar of BigRat
BigRat
Flag 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?
Delphi

Avatar of undefined
Last Comment
BigRat

8/22/2022 - Mon
2266180

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.
Mike Littlewood

Do you have / prefer to create stuff dynamically?
Mike Littlewood

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
Your help has saved me hundreds of hours of internet surfing.
fblack61
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.
2266180

>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
Mike Littlewood

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
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!
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Mike Littlewood

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)
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!


Mike Littlewood

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.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
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.
Mike Littlewood

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
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.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
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!