• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2304
  • Last Modified:

Setting StringGrids Scrollbar to be AlwaysVisible

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
szafran81
Asked:
szafran81
  • 10
  • 9
1 Solution
 
2266180Commented:
set the Scrollbars property to ssBoth
0
 
szafran81Author Commented:
Nope. only one is needed, and only one can be displayed. No need for 2 scrollbars.
0
 
szafran81Author Commented:
...and setting it ssBoth didn't help either - the scroll bar isn't visible until there are more rows to display than visible.
0
[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

 
2266180Commented:
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
 
szafran81Author Commented:
also it would be nice to make it visible, but disabled (grayed out) until there will more rows than visible.
0
 
2266180Commented:
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
 
2266180Commented:
oh, I forgot. you only need one of the scxrololbars. well, remove the otehr one from create params and enablescrollbar ;)
0
 
szafran81Author Commented:
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
 
2266180Commented:
ok
0
 
szafran81Author Commented:
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
 
2266180Commented:
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
 
szafran81Author Commented:
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
 
szafran81Author Commented:
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
 
szafran81Author Commented:
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
 
2266180Commented:
>> 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
 
szafran81Author Commented:
sorry ;)
i was after a few b**rs, and apparently i've missed that ;)
0
 
szafran81Author Commented:
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
 
2266180Commented:
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
 
2266180Commented:
>> 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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 10
  • 9
Tackle projects and never again get stuck behind a technical roadblock.
Join Now