Solved

Setting StringGrids Scrollbar to be AlwaysVisible

Posted on 2008-10-20
19
1,934 Views
Last Modified: 2013-11-23
Hi

I have a TStringGrid on a Form, and that StringGrid has one scrollbar, and i need for that scrollbar to be always visible (even if theres is nothing to display in the string grid except the title row). how can I do it?
0
Comment
Question by:szafran81
  • 10
  • 9
19 Comments
 
LVL 28

Expert Comment

by:2266180
ID: 22758727
set the Scrollbars property to ssBoth
0
 

Author Comment

by:szafran81
ID: 22758757
Nope. only one is needed, and only one can be displayed. No need for 2 scrollbars.
0
 

Author Comment

by:szafran81
ID: 22758787
...and setting it ssBoth didn't help either - the scroll bar isn't visible until there are more rows to display than visible.
0
 
LVL 28

Expert Comment

by:2266180
ID: 22759042
I see what you mean. I tested some codes from the net, with createparams and  ShowScrollBar function but to no avail.
I mus step out now but I'll try some more when I return.
0
 

Author Comment

by:szafran81
ID: 22759113
also it would be nice to make it visible, but disabled (grayed out) until there will more rows than visible.
0
 
LVL 28

Expert Comment

by:2266180
ID: 22761162
I can't believe myself how stupid mistake I did :D. it actually works the way I tried I just had to set scrollbars to ssnone.

here is unit code and dfm for your reference


unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, Grids, StdCtrls, ComCtrls, XPMan;
 

type

  TStringGrid=class(Grids.TStringGrid)

  protected

    procedure CreateParams(var Params: TCreateParams); override;

  end;
 

  TForm1 = class(TForm)

    StringGrid1: TStringGrid;

    XPManifest1: TXPManifest;

    procedure FormCreate(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

{$R *.dfm}
 

procedure TForm1.FormCreate(Sender: TObject);

begin

  EnableScrollBar(stringgrid1.handle, SB_BOTH, ESB_DISABLE_BOTH);

end;
 

{ TStringGrid }
 

procedure TStringGrid.CreateParams(var Params: TCreateParams);

begin

  inherited;

  Params.Style := Params.Style OR WS_HSCROLL OR WS_VSCROLL;

end;
 

end.
 
 

DFM follows
 

object Form1: TForm1

  Left = 192

  Top = 114

  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 = []

  OldCreateOrder = False

  OnCreate = FormCreate

  PixelsPerInch = 96

  TextHeight = 13

  object StringGrid1: TStringGrid

    Left = 168

    Top = 96

    Width = 473

    Height = 217

    ScrollBars = ssNone

    TabOrder = 0

  end

  object XPManifest1: TXPManifest

    Left = 608

    Top = 32

  end

end

Open in new window

0
 
LVL 28

Expert Comment

by:2266180
ID: 22761166
oh, I forgot. you only need one of the scxrololbars. well, remove the otehr one from create params and enablescrollbar ;)
0
 

Author Comment

by:szafran81
ID: 22761233
thanks for the reply. now i need to go to get a drink to blow off some steam after a bad day. i'll try the code when i come back or in the morning.
0
 
LVL 28

Expert Comment

by:2266180
ID: 22761361
ok
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:szafran81
ID: 22761372
I've got the time to test before I go. It shows the scrollbar but it stays diabled even if no of rows > visible rows.
0
 
LVL 28

Accepted Solution

by:
2266180 earned 500 total points
ID: 22762315
of course. you need to write code for that. I didn't do it because
- you never told me which scrollbar it is. I suspect it's the vertical scrollbar now that you mention number of rows.
- AND, most important, it dependfs on how you are operating on the grid.

here is a demo code, with a bogus add and delete row. note that the scrollbar itself is not scrolling. it's passed midnight here so I'll continue tomorow.
unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, Grids, StdCtrls, ComCtrls, XPMan;
 

type

  TStringGrid=class(Grids.TStringGrid)

  protected

    procedure CreateParams(var Params: TCreateParams); override;

  public

    procedure updatescrollbar;

  end;
 

  TForm1 = class(TForm)

    StringGrid1: TStringGrid;

    XPManifest1: TXPManifest;

    Button1: TButton;

    Button2: TButton;

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

{$R *.dfm}
 

procedure TForm1.FormCreate(Sender: TObject);

begin

  EnableScrollBar(stringgrid1.handle, SB_VERT, ESB_DISABLE_BOTH);

end;
 

{ TStringGrid }
 

procedure TStringGrid.CreateParams(var Params: TCreateParams);

begin

  inherited;

  Params.Style := Params.Style OR WS_VSCROLL;

end;
 

procedure TForm1.Button1Click(Sender: TObject);

begin

  stringgrid1.rowcount:=stringgrid1.rowcount+1;

  stringgrid1.updatescrollbar;

end;
 

procedure TForm1.Button2Click(Sender: TObject);

begin

  stringgrid1.rowcount:=stringgrid1.rowcount-1;

  stringgrid1.updatescrollbar;

end;
 

procedure TStringGrid.updatescrollbar;

var i,h:integer;

begin // TODO: change this os it onlly gets called when really needed. no sense in enableing an enabled scroll bar or disableing a disabled scrollbar.

  i:=BorderWidth;

  h:=0;

  while i<TopRow+VisibleRowCount do

  begin

    h:=h+RowHeights[i]+GridLineWidth;

    inc(i);

  end;

  if i<rowcount then

    h:=h+RowHeights[i];

  if ClientHeight<=h then

    EnableScrollBar(handle, SB_VERT, ESB_ENABLE_BOTH)

  else

    EnableScrollBar(handle, SB_VERT, ESB_DISABLE_BOTH);

  SetScrollRange(handle, SB_VERT, VisibleRowCount, RowCount, true);

  SetScrollPos(handle, SB_VERT, TopRow, true);

end;
 

end.

Open in new window

0
 

Author Comment

by:szafran81
ID: 22762678
I've just came back from the bar. But I'm unable to check the code today (now it's midnight here). Dorry for the inconvence, i thouth that it'll be a simple code for that. I'll check the code in the morning. (maybe just enabling the ssVertical srollbar after the rowcount > visible rows wiil do the trick ?)
0
 

Author Comment

by:szafran81
ID: 22763046
i've worked it out.
just put EnableScrollBar(handle, SB_VERT, ESB_ENABLE_BOTH) if the row count is > than visible row count (real visible row count - eg. 15 - and not the VisibleRowCount property), and EnableScrollBar(handle, SB_VERT, ESB_DISABLE_BOTH) when it's less.
thanks.
0
 

Author Comment

by:szafran81
ID: 22763161
hmmm... i thought i worked it out... everything is fine... except that the thumb tracker (at least i think that's what it's called - the scrolling button inside the scrollbar, between the up and down buttons) isn't moving... hmmm... that's weird... anyways... time to go to sleep... will try something else in the morning.
0
 
LVL 28

Expert Comment

by:2266180
ID: 22765147
>> the scrolling button inside the scrollbar, between the up and down buttons) isn't moving.

that's what I meant by "note that the scrollbar itself is not scrolling." :)

I'm working on it.
0
 

Author Comment

by:szafran81
ID: 22765707
sorry ;)
i was after a few b**rs, and apparently i've missed that ;)
0
 

Author Comment

by:szafran81
ID: 22766131
it works =o]
i've added this on the of the proc that refreshes the contents of the grid:

      if (grid.RowCount > 12) then //12 is my visible row count
        begin
          EnableScrollBar(grid.Handle, SB_VERT, ESB_ENABLE_BOTH);
          grid.ScrollBars := ssVertical;
        end
      else
        begin
          grid.ScrollBars := ssNone;
          EnableScrollBar(grid.Handle, SB_VERT, ESB_DISABLE_BOTH);
        end;

Thank you for your help.
0
 
LVL 28

Expert Comment

by:2266180
ID: 22766193
find attached updated and working unit
unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, Grids, StdCtrls, ComCtrls, XPMan;
 

type

  TStringGrid=class(Grids.TStringGrid)

  protected

    procedure CreateParams(var Params: TCreateParams); override;

    procedure TopLeftChanged; override;

  public

    procedure updatescrollbar;

  end;
 

  TForm1 = class(TForm)

    StringGrid1: TStringGrid;

    XPManifest1: TXPManifest;

    Button1: TButton;

    Button2: TButton;

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

uses math;
 

{$R *.dfm}
 

procedure TForm1.FormCreate(Sender: TObject);

begin

  EnableScrollBar(stringgrid1.handle, SB_VERT, ESB_DISABLE_BOTH);

end;
 

{ TStringGrid }
 

procedure TStringGrid.CreateParams(var Params: TCreateParams);

begin

  inherited;

  Params.Style := Params.Style OR WS_VSCROLL;

end;
 

procedure TForm1.Button1Click(Sender: TObject);

begin

  stringgrid1.rowcount:=stringgrid1.rowcount+1;

  stringgrid1.updatescrollbar;

end;
 

procedure TForm1.Button2Click(Sender: TObject);

begin

  stringgrid1.rowcount:=stringgrid1.rowcount-1;

  stringgrid1.updatescrollbar;

end;
 

procedure TStringGrid.TopLeftChanged;

var s:TScrollInfo;

begin

  inherited;

  s.cbSize:=sizeof(s);

  s.fMask:=SIF_POS;

  s.nPos:=TopRow;

  setscrollinfo(handle, SB_VERT, s, true);

end;
 

procedure TStringGrid.updatescrollbar;

var i,h:integer;

    s:TScrollInfo;

begin // TODO: change this ss it onlly gets called when really needed. no sense in enableing an enabled scroll bar or disableing a disabled scrollbar.

  i:=BorderWidth;

  h:=0;

  while i<TopRow+VisibleRowCount do

  begin

    h:=h+RowHeights[i]+GridLineWidth;

    inc(i);

  end;

  if i<rowcount then

    h:=h+RowHeights[i];

  if ClientHeight<=h then

  begin

    EnableScrollBar(handle, SB_VERT, ESB_ENABLE_BOTH);

    s.cbSize:=sizeof(s);

    s.fMask:=SIF_POS or SIF_RANGE or SIF_PAGE;

    s.nMin:=FixedRows;

    s.nMax:=FixedRows+RowCount-TopRow-VisibleRowCount;

    s.nPos:=TopRow;

    s.nPage:=1;

    setscrollinfo(handle, SB_VERT, s, true);

    if getlasterror<>0 then

      showmessage(syserrormessage(getlasterror));

  end

  else

    EnableScrollBar(handle, SB_VERT, ESB_DISABLE_BOTH);

{  SetScrollRange(handle, SB_VERT, VisibleRowCount, RowCount, true);

  SetScrollPos(handle, SB_VERT, TopRow, true);}

end;
 

end.

Open in new window

0
 
LVL 28

Expert Comment

by:2266180
ID: 22766212
>> i've added this on the of the proc that refreshes the contents of the grid:

my solution works for any stringgrid (and can be adapted to any customgrid descendant), with custom row heights and custom size. the number of actually visible rows change if the grid is resized vertically and/or one or more of the rows heights are changed ;)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This is a video that shows how the OnPage alerts system integrates into ConnectWise, how a trigger is set, how a page is sent via the trigger, and how the SENT, DELIVERED, READ & REPLIED receipts get entered into the internal tab of the ConnectWise …

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now