2012-11-08 44 views
8

私はDBGridのフレームを、デフォルトのフィールドの半分を持つ10以上のテーブルと、各テーブル専用のフィールドに使用するようにしようとしています。内容に応じてDBGridの(または他の同様の)列の幅を自動調整/拡大する方法は?

列のスペースが限られており、非常に品質の悪い作業であるため、各表の各列を手動で構成したくないため、各列の幅を最大の内容で計算する方法が不思議でしたその列の中にある行は、それ自身のコンポーネントまたはデータセットによって測定されます。

誰もが知っていますか?そのパワーを持つカスタムコンポーネントが世界に出ていますか? グリッドのすべての表示可能な列の可視データに応じて、サイズの増減を実装するソリューションが必要です。 私の解決策は、選択したセルのペイントに問題があり、選択されたデータセット行から魔女が飛び出します。

enter image description here


注:、私の質問を閉じないでください。グリッドの幅やフォームの幅に合わせることではありません。水平スクロールバーを最小限に抑えるのは、すべての列の幅ですが、必ずしもそれを隠すわけではありません。

+1

ここをクリックしてください:[TDBGridの列を自動調整する方法](http://delphi.about.com/od/usedbvcl/a/dbgrid_autofit.htm) – kobik

+0

@RRUZこれはフォームには適合しませんが、水平スクロールバーが表示されている場合でも、独自のコンテンツになります。 – PSyLoCKe

+1

@kobik、Zarko Gajicルール! – PSyLoCKe

答えて

8

何がしなければならないことはメートルにグリッドのキャンバスを使用することです各列の内容を調整し、それに応じて列の幅を設定します。データセットを反復処理するか、OnColumnDraw-Eventを使用してオンザフライで幅を調整することができます。

はここでサンプルの、スクロールバーやないが存在しなければならない場合は気にせず、内容をだすべての列がそれに応じて拡大または縮小

procedure TForm7.DBGridDrawColumnCell(Sender: TObject; const Rect: TRect; 
    DataCol: Integer; Column: TColumn; State: TGridDrawState); 
Var 
    w : Integer; 

begin 
    w := 5+DBGrid.Canvas.TextExtent(Column.Field.DisplayText).cx; 
    if w>column.Width then Column.Width := w; 
end; 

procedure TForm7.FormActivate(Sender: TObject); 
Var 
    i : Integer; 

begin 
    // Initialize width 
    for I := 0 to DBGrid.Columns.Count - 1 do 
    DBGrid.Columns[i].Width := 5 + DBGrid.Canvas.TextWidth(DBGrid.Columns[i].title.caption) 
end; 
+0

この回答はとても面白かったです。私はどのように愚かですか?どうもありがとうございました! – PSyLoCKe

+0

タグを使用して最大の幅を調べるので、必要なときに列を小さくすることができます。 – PSyLoCKe

+0

Hmm。私の答えは最近「受け入れられない」。理由を知りたい – alzaimar

7

EDITEDは:

については、この新しいコードで、で、グリッド内の列に合わせた私の最初のコードは、AutoSizeColumnsは場合、MaxRowsまたはDataset.Eofまで、各列の幅をカルクするレコードを読み取ります。

class function TDBGridHelper.AutoSizeColumns(DBGrid: TDBGrid; const MaxRows: Integer = 25): Integer; 

var 
    DataSet: TDataSet; 
    Bookmark: TBookmark; 
    Count, I: Integer; 
    ColumnsWidth: array of Integer; 
begin 
    SetLength(ColumnsWidth, DBGrid.Columns.Count); 
    for I := 0 to DBGrid.Columns.Count - 1 do 
    if DBGrid.Columns[I].Visible then 
     ColumnsWidth[I] := DBGrid.Canvas.TextWidth(DBGrid.Columns[I].Title.Caption + ' ') 
    else 
     ColumnsWidth[I] := 0; 
    if DBGrid.DataSource <> nil then 
    DataSet := DBGrid.DataSource.DataSet 
    else 
    DataSet := nil; 
    if (DataSet <> nil) and DataSet.Active then 
    begin 
    Bookmark := DataSet.GetBookmark; 
    DataSet.DisableControls; 
    try 
     Count := 0; 
     DataSet.First; 
     while not DataSet.Eof and (Count < MaxRows) do 
     begin 
     for I := 0 to DBGrid.Columns.Count - 1 do 
      if DBGrid.Columns[I].Visible then 
      ColumnsWidth[I] := Max(ColumnsWidth[I], DBGrid.Canvas.TextWidth(
       DBGrid.Columns[I].Field.Text)); 
     Inc(Count); 
     DataSet.Next; 
     end; 
    finally 
     DataSet.GotoBookmark(Bookmark); 
     DataSet.FreeBookmark(Bookmark); 
     DataSet.EnableControls; 
    end; 
    end; 
    Count := 0; 
    for I := 0 to DBGrid.Columns.Count - 1 do 
    if DBGrid.Columns[I].Visible then 
    begin 
     DBGrid.Columns[I].Width := ColumnsWidth[I]; 
     Inc(Count, ColumnsWidth[I]); 
    end; 
    Result := Count - DBGrid.ClientWidth; 
end; 

私はDataSet.AfterOpenイベントでそれを呼び出す:

TGridHelper.AutoSizeColumns(MyDBGrid); 
+0

残念なことに、この解決策は私のニーズに合っていません。このコードでは、グリッド領域を超えないように列を引き伸ばしますが、データの一部が切り取られるため、コンテンツが侵害されます。正しいのは、グリッド幅の合計で列の幅全体ではなく、テキストの内容に合わせることです。しかし、試してくれてありがとう。 – PSyLoCKe

+0

これは質問に対する答えではありません。 – NGLN

+2

OPは彼が本当に最初に望んでいることを説明していないので、マイナスは公平ではありません。今では、同じユニットの別のコードと必要に合わせて投稿を編集しました。 –

0

このソリューションが行う(Iは、5つのピクセルのオフセットを使用する必要がありました)選択されたセル描画不良及びレコードポインタの誤動作を修正する。

type 
    TColumnAutoAdjust = record {Save the information responsible for setting column widths in the grid} 
    Field: String;   {Field name whose information is being stored} 
    Registered: Boolean;  {Indicates whether the size of this column already registered} 
    Updated: Boolean;  {Indicates the actual size of the column was updated} 
    LastWidth: Integer;  {Width indicates the final text of a record of a row column} 
    CurrWidth: Integer;  {Indicates the current size and column width} 
    Reverter: Integer;  {Indicates the greatest width recorded but that is less than the current} 
    Scrolls: Integer;  {Indicates the amount of scrolls present after one width adjustment} 
    RecNo: Integer;   {Indicates which was the record in the table which increased the width of colune} 
    end; 

var { inside the forms private } 
    gdCols: array of TColumnAutoAdjust; { vetor de ajuste de largura de cada coluna na grade de resultado } 
    RegisteredCols: Integer; { quantas colunas já foram registradas no controle de ajuste } 
    gdVisibleRows: Integer; { quantas linhas de cadastros estão visíveis da grade de resultado } 
    gdVisibleCols: Integer; { quantas colunas de cadastros estão visíveis da grade de resultado } 

{ before showing the grid } 
    RegisteredCols := ResultGrid.Columns.Count; 
    SetLength(gdCols, RegisteredCols); { determina o tamanho da vetor de controle de colunas } 
    { libera a lista } 
    ResultGrid.Align := alClient; 
    for i := 0 to RegisteredCols -1 do { inicializando a largura das colunas no tamanho do título de cada } 
    begin 
     gdCols[i].Field := ResultGrid.Columns[i].FieldName; 
     ResultGrid.Columns[i].Width := ResultGrid.Canvas.TextExtent(ResultGrid.Columns[i].Title.Caption).cx; 
     ResultGrid.Columns[i].Alignment := taLeftJustify; 
     ResultGrid.Columns[i].Title.Alignment := taLeftJustify; 
    end; 
    BrowserQuery.Open; 
    ResultGrid.Show; 
    for i := 0 to gdVisibleRows do 
    begin 
     BrowserQuery.Next; 
     ResultGrid.Refresh; 
    end; 
    for i := 0 to gdVisibleRows do 
    begin 
     BrowserQuery.Prior; 
     ResultGrid.Refresh; 
    end; 
    BrowserQuery.First; 
    ResultGrid.SetFocus; 
    end 

{ after dataset scroll}  
procedure TRecordsBrowserFrameBase.BrowserQueryAfterScroll(DataSet: TDataSet); 
var 
    i, TitleWidth: Integer; 
    mayAdjustAgain: Boolean; { } 
begin 
{ ajusta as colunas da grade de resultado a cada movimento da tabela de resultado } 
    mayAdjustAgain := False; 
    for i := 0 to RegisteredCols -1 do 
    begin 
    if not gdCols[i].Updated then 
    begin 
     ResultGrid.Columns[i].Width := gdCols[i].CurrWidth; 
     gdCols[i].Scrolls := 0; 
     gdCols[i].Updated := True; 
    end 
    else 
    begin 
     Inc(gdCols[i].Scrolls); 
     if (DataSet.RecNo > gdCols[i].RecNo + gdVisibleRows) or (DataSet.RecNo < gdCols[i].RecNo - gdVisibleRows) then 
     begin 
     TitleWidth := MaxColSpacing + ResultGrid.Canvas.TextExtent(ResultGrid.Columns[i].Title.Caption).cx; 
     gdCols[i].LastWidth := gdCols[i].CurrWidth; 
     gdCols[i].CurrWidth := IFX(gdCols[i].Reverter > TitleWidth, gdCols[i].Reverter, TitleWidth); 
     gdCols[i].Reverter := IFX(gdCols[i].Reverter > TitleWidth, TitleWidth, 0); 
     gdCols[i].Updated := False; 
     mayAdjustAgain := True; 
     end; 
    end; 
    end; 
    if mayAdjustAgain then 
    begin 
    ResultGrid.Refresh; 
    BrowserQueryAfterScroll(DataSet); 
    end; 
end; 

{ on draw column cell } 

procedure TRecordsBrowserFrameBase.GridColumnWidthAdjust(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); 
var 
    ColWidth, TextWidth, TitleWidth: Integer; 
begin 
{ ajusta a capitalização do texto das células } 
    (Sender as TJvDBGrid).Canvas.Pen.Color := clWhite; 
    (Sender as TJvDBGrid).Canvas.Rectangle(Rect); 
    (Sender as TJvDBGrid).Canvas.TextOut(Rect.Left+2, Rect.Top+2, NameCase(Column.Field.DisplayText)); 
{ ajusta as colunas de uma grade de acordo com o conteúdo das células } 
    gdVisibleRows := (Sender as TJvDBGrid).VisibleRowCount; 
    gdVisibleCols := (Sender as TJvDBGrid).VisibleColCount; 
    TitleWidth := MaxColSpacing + (Sender as TJvDBGrid).Canvas.TextExtent(Column.Title.Caption).cx; 
    TextWidth := MaxColSpacing + (Sender as TJvDBGrid).Canvas.TextExtent(NameCase(Column.Field.DisplayText)).cx; 
    ColWidth := Column.Width; 
    {$WARNINGS OFF} 
    if (TextWidth > gdCols[DataCol].Reverter) and (TextWidth < ColWidth) then gdCols[DataCol].Reverter := TextWidth; 
    if (TextWidth > ColWidth) then { texto da célula é mais largo que a coluna } 
    begin 
    gdCols[DataCol].Registered := True; 
    gdCols[DataCol].LastWidth := ColWidth; 
    gdCols[DataCol].CurrWidth := TextWidth; 
    gdCols[DataCol].Updated := False; 
    gdCols[DataCol].RecNo := BrowserQuery.RecNo; 
    gdCols[DataCol].Reverter := TitleWidth; 
    Exit; 
    end; 
    if (ColWidth < TitleWidth) then { texto da célula é menor que o título da coluna } 
    begin 
    gdCols[DataCol].Registered := True; 
    gdCols[DataCol].LastWidth := ColWidth; 
    gdCols[DataCol].CurrWidth := TitleWidth; 
    gdCols[DataCol].Updated := False; 
    gdCols[DataCol].Reverter := TitleWidth; 
    Exit; 
    end; 
{$WARNINGS ON} 
end; 
1

なぜ複雑なコードを使用するのですか? :Dこれを使ってください。また、5 pxのオフセットがあります。あなたは自動プロパティSizePriority=1を設定し、固定列のためSizePriority=0を設定し、あなたのケースで唯一の最後の列が自動サイズになります大きさにしたい各列に対して

procedure TForm1.FormActivate(Sender: TObject); 

var 

    i:integer; 

begin 

    for i :=0 to DbGrid1.Columns.Count - 1 do 
    DbGrid1.Columns[i].width :=5+dbgrid1.Canvas.TextWidth(DbGrid1.Columns[i].Title.Caption); 

end; 
1

次に、プロパティーをgrid.AutoFillColumns=trueに設定してください。

関連する問題