Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ScrollBar on TabSheet

1,057 views
Skip to first unread message

Grega Loboda

unread,
May 12, 2003, 7:26:20 AM5/12/03
to
Is it possible to set TTabSheet to show scroll bar if there are controls
that are not visible to the user because height of the tab sheet is less
than top of some controls? If so, how?
I know I could use scrollbox on tab sheet but is out of the question as I
need controls right on the tab sheet because of the streaming I will be
using.

Grega

Peter Below (TeamB)

unread,
May 12, 2003, 2:46:52 PM5/12/03
to

Well, TTabsheet does not derive from TScrollingWinControl, so it has no
support for your requirements. But Windows basically supports scrollbars on
*any* control, you just have to write all the code for scrolling etc.
yourself.

Here is a starter pack <g>. The controls are all on the tabsheet.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;

type
TTabsheet = class( ComCtrls.TTabsheet )
private
Procedure WMVScroll( Var msg: TWMSCROLL ); message WM_VSCROLL;
Procedure WMHScroll( Var msg: TWMSCROLL ); message WM_HSCROLL;
Procedure HandleScrollbar( Var msg: TWMSCROLL; bar: Integer );
protected
Procedure Loaded; override;
public
Procedure CreateParams( var params: TCreateParams ); override;
end;
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
RadioGroup1: TRadioGroup;
GroupBox1: TGroupBox;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit4: TEdit;
Edit5: TEdit;
Edit6: TEdit;
ComboBox1: TComboBox;
private
{ Private declarations }

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TTabsheet }

procedure TTabsheet.CreateParams(var params: TCreateParams);
begin
inherited;
params.style := params.Style or WS_VSCROLL or WS_HSCROLL;
end;

procedure TTabsheet.WMHScroll(var msg: TWMSCROLL);
begin
HandleScrollbar( msg, SB_HORZ );
end;

procedure TTabsheet.WMVScroll(var msg: TWMSCROLL);
begin
HandleScrollbar( msg, SB_VERT );
end;

procedure TTabsheet.HandleScrollbar(var msg: TWMSCROLL; bar: Integer);
var
si: TScrollInfo;
i,oldpos, dx, dy: Integer;
begin
msg.result := 0;
si.cbSize := Sizeof( TscrollInfo );
si.fMask := SIF_ALL;
GetScrollInfo( Handle, bar, si );
oldpos := si.nPos;
si.fMask := SIF_POS;
{ For simplicities sake we use 1 unit as the small scroll increment
and 10 as large one }
Case msg.ScrollCode Of
SB_TOP : si.nPos := si.nMin;
SB_BOTTOM : si.nPos := si.nMax;
SB_LINEUP : Dec( si.nPos, 1 );
SB_LINEDOWN : Inc( si.nPos, 1 );
SB_PAGEUP : Dec( si.nPos, 10 );
SB_PAGEDOWN : Inc( si.nPos, 10 );
SB_THUMBTRACK, SB_THUMBPOSITION
: si.nPos := msg.Pos;
SB_ENDSCROLL: Exit;
End;
si.fMask := SIF_POS;
If si.nPos < si.nMin Then
si.nPos := si.nMin;
If si.nPos > si.nMax Then
si.nPos := si.nMax;
SetScrollInfo( Handle, bar, si, true );
If bar = SB_VERT Then Begin
dy := oldpos - si.nPos;
dx := 0;
End
Else Begin
dx := oldpos - si.nPos;
dy := 0;
End;
For i:= 0 to Controlcount-1 Do
With controls[i] Do
SetBounds( Left+dx, Top+dy, Width, Height );
end;

procedure TTabsheet.Loaded;
var
i, maxX, maxY: Integer;
c: TControl;
si: TScrollInfo;
begin
inherited;
maxX := 0;
maxY := 0;
for i:= 0 to Controlcount-1 do begin
c:= controls[i];
c.Align := alNone;
// everything else does not work with a scollable parent
if (c.Left+c.width) > maxX then
maxX := c.Left + c.Width;
if (c.Top+c.Height) > maxY then
maxY := c.Top + c.Height;
end;
si.cbSize := Sizeof( TscrollInfo );
si.fMask := SIF_ALL;
si.nMin := 0;
si.nPage := 0;
si.nPos := 0;
if maxX > clientwidth then begin
maxX := maxX + GetSystemMetrics( SM_CXVSCROLL );
si.nMax := maxX - ClientWidth ;
SetScrollInfo( handle, SB_HORZ, si, true );
end
else
ShowScrollbar( handle, SB_HORZ, false );
if maxY > clientheight then begin
maxY := maxY + GetSystemMetrics( SM_CYHSCROLL );
si.nMax := maxY - clientheight;
SetScrollInfo( handle, SB_VERT, si, true );
end
else
ShowScrollbar( handle, SB_VERT, false );
end;


--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be

John Elrick

unread,
May 12, 2003, 4:43:22 PM5/12/03
to

"Grega Loboda" <grega....@email.si> wrote in message
news:3ebf...@newsgroups.borland.com...

SNIP

> I know I could use scrollbox on tab sheet but is out of the question as I
> need controls right on the tab sheet because of the streaming I will be
> using.

Whoa...back up. Why is that a problem?


John Elrick

Grega Loboda

unread,
May 13, 2003, 2:54:24 AM5/13/03
to
Well, if you really want to know. I have this page control on the form at
design time (so form is owner of the page control). This page control has
one tab sheet and if I place scrollbox on that tab (as it is now), owner of
the scrollbox is form as well. I inherit a lot from this form, to create
other form. This form knows how to handle many things. Now I would like to
place some editors on that page control at runtime. Stream that page control
and be able to set editors back at some later stage. As I only want to
stream page control (not the whole form, because then I would stream
TColumns and many other things that should not be streamed and are there on
the form as well), I need owner of those editors to be page control (only
owned components get streamed). But owner of the scrollbox is already form,
so editors dropped on the scrollbox will not be streamed as streaming is
already stopped at scrollbox, as it's owner is not, so called root. Plus, if
I change the owner of the scrollbox, whean streaming, I should free that
scrollbox as well. So, just problems.

Grega

"John Elrick" <jel...@adelphia.net> wrote in message
news:3ec007e4$1...@newsgroups.borland.com...

Grega Loboda

unread,
May 13, 2003, 3:02:26 AM5/13/03
to
Great. One more question. If I want this TabSheet to be created instead of
normal TabSheet all over my project (I have few forms that should use this),
where should I define this new TabSheet. Is it ok to define it in some unit
and just put that unit into uses. Do it has to be the last in the uses or
something like that. I saw things work differently when units in uses have
different order.

Grega

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.00009e3...@antispam.compuserve.com...

John Elrick

unread,
May 13, 2003, 9:01:59 AM5/13/03
to

"Grega Loboda" <grega....@email.si> wrote in message
news:3ec09621$1...@newsgroups.borland.com...

> Well, if you really want to know. I have this page control on the form at
> design time (so form is owner of the page control). This page control has
> one tab sheet and if I place scrollbox on that tab (as it is now), owner
of
> the scrollbox is form as well. I inherit a lot from this form, to create
> other form. This form knows how to handle many things. Now I would like to
> place some editors on that page control at runtime. Stream that page
control
> and be able to set editors back at some later stage. As I only want to

SNIP

> scrollbox as well. So, just problems.

Yea...that's the least of it. I think you are taking some serious shortcuts
here that will end up biting you in the butt.

First, _everything_ you put on the form will by default have the Form as an
Owner. Even if you create them at runtime, when you stream them back
in...guess who the owner is.

So, freeing the PageControl probably won't free all the controls on the
tabsheets. Simple solution (of course there is one)...create a Frame which
is embedded into the TabSheet. You can pretty much guarantee that the Frame
will own everything dropped on it, you can easily and safely Free the Frame
and it's pretty durn easy to save and load it and its contents from a
stream.

As a plus, Frame supports scroll bars.

The downside is that you won't just be able to stream the entire control,
you'll have to do it a page at a time...but that's a lot more flexible
anyhow.


John

Peter Below (TeamB)

unread,
May 13, 2003, 3:20:42 PM5/13/03
to
In article <3ec09803$1...@newsgroups.borland.com>, Grega Loboda wrote:
> Great. One more question. If I want this TabSheet to be created instead of
> normal TabSheet all over my project (I have few forms that should use this),
> where should I define this new TabSheet. Is it ok to define it in some unit
> and just put that unit into uses. Do it has to be the last in the uses or
> something like that. I saw things work differently when units in uses have
> different order.

You can put it into a unit of its own and add that to your Interface-section
Uses clause. It has to appear *after* ComCtrls.

Grega Loboda

unread,
May 14, 2003, 5:26:43 AM5/14/03
to
I can't say you're wrong about the things you have said, but look it this
way. If I have a page control, that has tab sheets that can scroll, all I
have to do is stream that page control. I know won't be able to stream
controls added at design time, but then again, I don't want to stream those.
Controls added at design time should not be moved. I need to stream page
control in case, where user has own defined table. I create controls at run
time (owner of that controls will be page control), but those controls are
not positioned in the best way, so I want to give a chance to the user, to
reposition those controls. If there is one tabsheet there at design time, I
might have a problem, but I think I can have a page control with no tabs at
design time so I guess I won't have a problem when streaming back.

Grega

"John Elrick" <jel...@adelphia.net> wrote in message

news:3ec0ed41$1...@newsgroups.borland.com...

John Elrick

unread,
May 14, 2003, 8:48:15 AM5/14/03
to

"Grega Loboda" <grega....@email.si> wrote in message
news:3ec20b53$1...@newsgroups.borland.com...

> I can't say you're wrong about the things you have said, but look it this
> way. If I have a page control, that has tab sheets that can scroll, all I
> have to do is stream that page control. I know won't be able to stream
> controls added at design time, but then again, I don't want to stream
those.
> Controls added at design time should not be moved. I need to stream page
> control in case, where user has own defined table. I create controls at
run
> time (owner of that controls will be page control), but those controls are
> not positioned in the best way, so I want to give a chance to the user, to
> reposition those controls. If there is one tabsheet there at design time,
I
> might have a problem, but I think I can have a page control with no tabs
at
> design time so I guess I won't have a problem when streaming back.

Depends on what you are attempting to do. In theory, you shouldn't have any
problem with streaming the ScrollBox either, since it is Parented to the
TabSheet.


John


Brett Watters

unread,
May 14, 2003, 5:04:35 PM5/14/03
to
Greg,

If things are working now because all your controls are created at run-time
without
the form as the owner, then why not just create the ScrollBox as run-time
also? Either
this or set the scrollbox's owner to the TabPanel? Then your streaming
should work as
it does before.

Thanks,

Brett

"Grega Loboda" <grega....@email.si> wrote in message

news:3ec20b53$1...@newsgroups.borland.com...

Grega Loboda

unread,
May 15, 2003, 2:06:43 AM5/15/03
to
If I have scrollbox there and I stream page control back, I get error
ScrollBox1 already exists. And scrollbox must be there at design time, as
for some forms, I put editors on it at design time and add tab sheets if
needed.

Grega

"Brett Watters" <bwat...@geometrix.bc.ca> wrote in message
news:3ec2...@newsgroups.borland.com...

John Elrick

unread,
May 15, 2003, 2:13:07 PM5/15/03
to

"Grega Loboda" <grega....@email.si> wrote in message
news:3ec3...@newsgroups.borland.com...

> If I have scrollbox there and I stream page control back, I get error
> ScrollBox1 already exists. And scrollbox must be there at design time, as
> for some forms, I put editors on it at design time and add tab sheets if
> needed.

Right...you have to free it first or you'll get the error.

Same thing with anything else you stream in. Easy way to handle it. Put
PageControl on a Panel and set the PageControl to alClient.

procedure TForm1.LoadStuff(const aStream: TStream);
var
localIsLocked : boolean;
begin
localIsLocked := LockWindowUpdate(Self.Handle);
if not localIsLocked then
Exit;

try
PageControl1.Free;
...load your stuff onto the panel. Don't remember exact syntax off the
top of my head
finally
LockWindowUpdate(0);
end;

end;

0 new messages