I've got a TDBGrid with predefined columns, and I just can't get the width right. I can mess with the Width property of the columns in the Form Designer and get the width to look just right at design time, but at runtime, for whatever reason, the columns tend to be significantly wider, and I end up with a scroll bar at the bottom of the grid. Is there any way to get make the columns size themselves correctly without all the trial-and-error, especially if the grid only has one or two of them?
5 Answers
I use this procedure inside forms OnResize event
procedure AutoStretchDBGridColumns(Grid: TDBGrid; Columns, MinWidths: Array of integer);
var
x, i, ww: integer;
begin
// Stretches TDBGrid columns
// Columns contains columns to stretch
// MinWidths contains columns minimum widhts
// To stretch grids columns 1,2 and 5 automatically and set minimum widths to 80, 150 and 150 call
// AutoStretchDBGridColumns(DBGrid1, [1,2,5], [80, 150, 150]);
Assert(Length(Columns) = Length(MinWidths), 'Length(Columns) <> Length(MinWidths)');
ww := 0;
for i := 0 to Grid.Columns.Count - 1 do
begin
if Grid.Columns[i].Visible then
ww := ww + Grid.Columns[i].Width + 1; //** +1 for grid line width
end;
if dgIndicator in Grid.Options then
ww := ww + IndicatorWidth;
x := (Grid.ClientWidth - ww) div Length(Columns);
for i := 0 to High(Columns) do
Grid.Columns[Columns[i]].Width := Max(Grid.Columns[Columns[i]].Width + x, MinWidths[i]);
end;
It has some flaws, but works quite well.
I think I know the answer to the problem. I had the same problem for a few years. When I put demo data in I resize the columns width (design time) but I suspect, as a bug in Delphi, if the width you enter is the same as the default width Delphi assigns to the column, the width is not saved in the dfm file - as can be seen if you view the dfm as text.
My solution is to set it to one pixel wider or narrower so that Delphi will be forced to store the width (or edit the dfm directly) and so it will be set at run time. If you don't set it, Delphi will assign some calculated width at run time - which is not what you want as it could change depending on the data. Simple solution but it took me a long time to figure out.
You can do that, but you have to check the width of all fields for all records that you potentially can display.
Given the fact that there are still plenty of applications that hardly filter their record set, this can mean that you need to check a zillion records, just to get rid of the scrollbar.
Have you ever considered that you might just want to display too much information at once?
A possible alternative is to show a hint text for fields that do not fit in their column?
I have used such an alternative, but need to check the sources; I can get you some sample code tomorrow.
--jeroen
JP's answer is a pretty good solution. You need to manually stretch or shrink the columns as necessary to make it fit in the window. There is a windows API call to get the vertical scroll bar width. Then you can look at the visible rows to see if the vertical scroll bar is being shown.
Another technique is to figure out the width of each column relative to each other. Then when you resize them maintain the same ratio.
You may have a look at the answers to this question.
Perhaps the protected CalcDrawInfo method may help here.