|
TDBGrid mit dynamischer Spaltenbreite
Frage:Wie kann man die Spaltenbreite im TDBGrid so einstellen, dass sie sich automatisch der größten Breite des Textes anpasst?
Antwort: Diese Frage besteht bei genauerer Betrachtung aus gleich zwei Teilen:
1. Wie ermittele ich die maximale Zeichenanzahl der in der anzuzeigenden Tabellenspalte vorgefundenen Werte?
2. Wie kann ich zur Laufzeit die Spaltenbreite im TDBGrid anpassen?
Für die erste Aufgabe gibt es verschiedene Wege. Die Anwendung könnte sofort nach dem Öffnen der Datenmenge in einer Schleife alle Datensätze durchgehen, um zuerst den maximalen Wert zu suchen, um dann einmalig die Spaltenbreite anzupassen. Um diesen Aufwand zu vermeiden, kann die aber erst später über das TDBGrid-Ereigenis OnDrawColumnCell nachgeholt werden, auch wenn dann die Spaltenbreite zur Laufzeit mehrfach geändert wird, wenn es in der Spaltenbreite sehr große Unterschiede gibt. Denn immer dann, wenn dieses Ereignis eintrifft, kann das eigene Programm über den Konstrukt TDBGrid(Sender).Canvas.TextExtent(Column.Field.DisplayText).cx nachfragen, welcher Platz für die vollständige Darstellung benötigt würde. Vergleich man diesen Wert mit dem Parameter Column.Width, so kann das Programm erkennen, wenn die aktuelle Spaltenbreite nicht ausreicht. In diesem Fall schickt sich das Formular selbst eine private Botschaft, um die betroffene Spalte im TDBGrid entsprechend zu verbreitern. Da eine über die Win32-API-Funktion PostMessage verschickte Nachricht über die Botschaftswarteschlange erst dann ausgelesen wird, wenn die Anwendung nichts besseres zu tun hat, kommt diese Manipulation dem interen Ablauf im TDBGrid nicht in die Quere.
Das folgende Beispiel demonstriert dies:
{ ****************************************************************
Autor : Andreas Kosch
Compiler : Delphi 6.0 Enterprise
Betriebssystem : Windows 2000 SP2
Erstellt am : 07.08.2001
Beschreibung : Spaltenbreite im TDBGrid zur Laufzeit
automatisch an den längen Spaltenwert
anpassen, der angezeigt werden muss.
**************************************************************** }
unit DBGridAutoSizeFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids, DB, DBTables, StdCtrls;
const
PM_COLUMNWIDTH = WM_APP + 1;
type
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
procedure PMCOLUMNWIDTH(var Msg: TMessage); message PM_COLUMNWIDTH;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{ *.dfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
with Table1 do
for i := 0 to Pred(Fields.Count) do
Fields[i].DisplayWidth := 4;
end;
procedure TForm1.PMCOLUMNWIDTH(var Msg: TMessage);
begin
with TColumn(Pointer(Msg.LParam)) do
Width := Msg.WParam;
end;
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with TDBGrid(Sender).Canvas.TextExtent(Column.Field.DisplayText) do
if (cx + 6 > Column.Width) then
Postmessage(Handle, PM_COLUMNWIDTH, cx + 10, LongInt(Column));
end;
end.
|