How to autosize a TDBGrid (Views: 31)
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. |