I have a grid component (DBGrid) which has lots of columns on it. Because of large number of columns, a scrollbar was created, and thus some part of grid remains hidden. I need to find out what is the real width of DBGrid, including the part which is not shown due to scroll bar. But Width property gives only the width of the component itself. Anybody has any idea?
4 Answers
TDBGrid
has a Columns
property. Each of the columns has its own Width
property. So you could loop through all of the columns and sum up their widths.
Like this:
function TotalColumnsWidth(var AGrid: TDBGrid);
var
i: Integer;
begin
Result := 0;
for i := to AGrid.Columns.Count - 1 do
Result := Result + AGrid.Columns[i].Width;
end;

- 15,626
- 10
- 42
- 52

- 6,932
- 10
- 65
- 105
-
That works only if there is no empty space at the end of the datagrid, that means it only works if columns are taking all the space. – Tofig Hasanov Nov 11 '09 at 17:58
-
Actually the real reason why I need that, is exactly this problem. I want to get rid of empty space after columns, but can't figure out how to find the ("width of DBGrid" - "width of columns") – Tofig Hasanov Nov 11 '09 at 18:05
-
@Tofig but the empty space is visible only if the width of the columns is less then the width of the DBGrid? Do you want to resize your columns that they will take all of their owner (DBGrid) width? – Wodzu Nov 11 '09 at 18:09
-
"empty space is visible only if the width of the columns is less then the width of the DBGrid" - not really, DBGrid can still have empty space, even when columns are wider than DBGrid. Usually it happens when columns are resized during run-time. – Tofig Hasanov Nov 11 '09 at 18:42
Perhaps this may be helpful. It is part of a class helper for TDBGrid that auto sizes the last column, so that the grid has no empty space. Should be easy to adjust to your needs.
As you may notice, the CalcDrawInfo method is what you are seeking for. As it is protected you can either use a class helper or the usual protected-hack to get hands on it.
procedure TDbGridHelper.AutoSizeLastColumn;
var
DrawInfo: TGridDrawInfo;
ColNo: Integer;
begin
ColNo := ColCount - 1;
CalcDrawInfo(DrawInfo);
if (DrawInfo.Horz.LastFullVisibleCell < ColNo - 1) then Exit;
if (DrawInfo.Horz.LastFullVisibleCell < ColNo) then
ColWidths[ColNo] := DrawInfo.Horz.GridBoundary - DrawInfo.Horz.FullVisBoundary
else
ColWidths[ColNo] := ColWidths[ColNo] + DrawInfo.Horz.GridExtent - DrawInfo.Horz.FullVisBoundary
end;

- 45,288
- 3
- 82
- 130
-
I didn't quite understand, where can I get this method: "CalcDrawInfo" from? If i just copy this code into the program, compiler does not recognize it. – Tofig Hasanov Nov 12 '09 at 13:37
-
Disregard that, I didn't notice that it was protected. It actually worked! Thanks a lot :) – Tofig Hasanov Nov 12 '09 at 16:12
-
I have this problem too but I use C++ Builder XE instead Delphi. Can you describe to me how to use this procedure in C++ Builder XE? Help me please :( – Jessie M Feb 22 '13 at 09:52
I think I have found a solution (although it seems a little strange). In order to find the difference between column widths and real width of the DBgrid (that means find the width of the empty space left after last column), we need to keep track of which column is shown on the left now (what is current column that is scrolled to). We can do that using OnDrawColumnCell event, since it will draw only columns which are scrolled on now. Then we need to calculate sum of widths of all visible columns, and subtract that from DBGrid's width. P.S. Sorry for bad english
Ex code:
For i:=0 to Last do
if Vis[i] then
Begin
Sum:=Sum+DBG.Columns[i].Width;
Inc(Cnt);
End;
if dgColLines in DBG.Options then
Sum := Sum + Cnt;
//add indicator column width
if dgIndicator in DBG.Options then
Sum := Sum + IndicatorWidth;
Dif:=DBG.ClientWidth - Sum;

- 3,303
- 10
- 51
- 81
Here are functions we have used in the past. It takes into account the width of data based on the font and also compensates for vertical lines if they are visible
function GridTextWidth(fntFont : TFont; const sString : OpenString) :
integer;
var
f: TForm;
begin
try
f:=TForm.Create(nil);
f.Font:=fntFont;
result:=f.canvas.textwidth(sstring);
finally
f.Free;
end;
end;
function CalcGridWidth(dbg : TDBGrid { the grid to meaure }): integer; { the "exact" width }
const cMEASURE_CHAR = '0';
iEXTRA_COL_PIX = 4;
iINDICATOR_WIDE = 11;
var i, iColumns, iColWidth, iTitleWidth, iCharWidth : integer;
begin
iColumns := 0;
result := GetSystemMetrics(SM_CXVSCROLL);
iCharWidth := GridTextWidth(dbg.font,cMeasure_char);
with dbg.dataSource.dataSet do begin
DisableControls;
for i := 0 to FieldCount - 1 do with Fields[i] do
if visible then
begin
iColWidth := iCharWidth * DisplayWidth;
if dgTitles in dbg.Options then begin
ititlewidth:=GridTextWidth(dbg.titlefont,displaylabel);
if iColWidth < iTitleWidth then
iColWidth := iTitleWidth;
end;
inc(iColumns, 1);
inc(result, iColWidth + iEXTRA_COL_PIX);
end;
EnableControls;
end;
if dgIndicator in dbg.Options then
begin
inc(iColumns, 1);
inc(result, iINDICATOR_WIDE);
end;
if dgColLines in dbg.Options then
inc(result, iColumns)
else
inc(result, 1);
end;

- 6,294
- 12
- 62
- 107
-
It still does not count empty space left after the last column. Is there a way to post pictures here? I would show the empty space which bothers me. – Tofig Hasanov Nov 11 '09 at 19:34