2011. április 17., vasárnap
How to autosize a TDBGrid
Problem/Question/Abstract:
When placing a DBGrid on a form, it is difficult to know exactly how large it needs to be to accomodate the datafields and the number of records that are displayed. There is always a white border at the bottom under the last record and to the right of the rightmost field. There must be a simple way to tell the DBgrid (and the non data-aware grid, too) to always and automatically resize itself according to what it needs to display. Any ideas?
Answer:
Solve 1:
I use the following code to size my DBGrid and my form:
procedure TListDlg.FormCreate(Sender: TObject);
var
W, i: Integer;
begin
DataSet.Active := True {Make sure that your dataset is active}
W := 0;
for i := 0 to DBGrid.Columns.Count - 1 do
W := W + DBGrid.Columns[i].Width + 1;
DBGrid.ClientWidth := W;
Self.ClientWidth := (DBGrid.Left * 2) + DBGrid.Width;
end;
Now your DBGrid is centered in your form and shows all Columns. To avoid the "white border" you can use the following code:
procedure TDBGrid.WMSize(var Msg: TWMSize);
var
RowHeight: Integer;
VisibleRows: Integer;
begin
if Align <> alClient then
begin
if not (csDesigning in ComponentState) then
ShowScrollBar(Handle, SB_VERT, False);
{There is a problem in scaling a grid because the VCL includes the scrollbar}
RowHeight := DefaultRowHeight;
if dgRowLines in Options then
RowHeight := RowHeight + GridLineWidth;
VisibleRows := ClientHeight div RowHeight;
if VisibleRows < 1 then
VisibleRows := 1;
if HandleAllocated then
ClientHeight := (VisibleRows * RowHeight);
Msg.Result := 0;
end
else
inherited;
end;
Solve 2:
If you need to actually calculate the width of the entire TDBGrid, use the following:
function NewTextWidth(fntFont: TFont; const sString: OpenString): integer;
var
fntSave: TFont;
begin
result := 0;
fntSave := Application.MainForm.Font;
Application.MainForm.Font := fntFont;
try
result := Application.MainForm.Canvas.TextWidth(sString);
finally
Application.MainForm.Font := fntSave;
end;
end;
{Calculate the width of the grid needed to exactly display with no horizontal scrollbar and with no extra space between the last column and the vertical scrollbar. The grid's datasource must be properly set and the datasource's dataset must be properly set, though it need not be open. Note: this width includes the width of the vertical scrollbar, which changes based on screen resolution. These changes are compensated for.}
function iCalcGridWidth(dbg: TDBGrid): integer;
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 := NewTextWidth(dbg.Font, cMEASURE_CHAR);
with dbg.dataSource.dataSet do
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 := NewTextWidth(dbg.TitleFont, DisplayLabel);
if iColWidth < iTitleWidth then
iColWidth := iTitleWidth;
end;
inc(iColumns, 1);
inc(result, iColWidth + iEXTRA_COL_PIX);
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;
I had to use the function NewTextWidth, rather than the Grid's Canvas.TextWith as the Canvas of the Grid may not initialized when you need to call iCalcGridWidth.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése