用Delphi自带的StringGrid吧,在StringGrid的OnDrawCell事件中:procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin with StringGrid1 do begin Canvas.FillRect(Rect); DrawText(GetDC(Handle), PChar(Cells[ACol, ARow]), Length(Cells[ACol, ARow]), Rect, DT_WORDBREAK); end; end;然后你的 comment:='1'; comment:=comment + #13 + #10 + '2'; StringGrid.cells[1,1]:=comment; 就能换行了
轻松实现DBGrid的多表头 hj0791(原作)
关键字 多表头
用法: 设置DBGrid的Column的Caption属性 例如:Column1的Caption为111|222 Column2的Caption为111|333 那么Column1和Column2公用一个表头111 unit ADBGrid;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, Math;type TADBGrid = class(TDBGrid) private { Private declarations } //兄弟列子标题,当前列子标题 BrerLayerTitles, CurLayerTitles: TStringList; SaveFont: TFont; //根据当前数据列号和表头的层号获取表头的区域 function TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect; LayerID, ACol: Integer): TRect; //解出当前数据列标题为子标题并返回标题层数(子标题数) function ExtractSubTitle(LayerTitles: TStrings; ACol: Integer): Integer; protected { Protected declarations } procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override; procedure Paint; override; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end;procedure Register;implementationprocedure Register; begin RegisterComponents('Samples', [TADBGrid]); end;constructor TADBGrid.Create(AOwner: TComponent); begin inherited; BrerLayerTitles := TStringList.Create; curLayerTitles := TStringList.Create; SaveFont := TFont.Create; end;destructor TADBGrid.Destroy; begin BrerLayerTitles.Free; curLayerTitles.Free; SaveFont.Free; inherited; end;procedure TADBGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); var SubTitleRT, CaptionRt, IndicatorRT: TRect; Column: TColumn; SubTitle: string; i: Integer; begin if (ARow = 0) and (ACol > 0) then begin ExtractSubTitle(curLayerTitles, RawToDataColumn(ACol)); for i := 0 to curLayerTitles.Count - 1 do begin SubTitleRT := TitleLayerRect(curLayerTitles, ARect, i, RawToDataColumn(ACol)); CaptionRt := SubTitleRT; Canvas.Brush.Color := FixedColor; Canvas.FillRect(SubTitleRT); DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDINNER, BF_TOPLEFT); if i <> CurLayerTitles.Count - 1 then begin DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDOUTER, BF_BOTTOM); Dec(SubTitleRT.Bottom, 2); end else Dec(SubTitleRT.Bottom, 1); Canvas.Pen.Color := clWhite; Dec(SubTitleRT.Right, 1); Canvas.MoveTo(SubTitleRT.Right, SubTitleRT.Top); Canvas.LineTo(SubTitleRT.Right, SubTitleRT.Bottom); Canvas.LineTo(SubTitleRT.Left, SubTitleRT.Bottom); Column := Columns[RawToDataColumn(ACol)]; SubTitle := ''; if Assigned(Column) then begin SubTitle := CurLayerTitles[i]; SaveFont.Assign(Canvas.Font); Canvas.Font.Assign(TitleFont); try InflateRect(SubTitleRT, -1, -1); DrawText(Canvas.Handle, PChar(SubTitle), Length(SubTitle), SubTitleRT, DT_CENTER or DT_SINGLELINE or DT_VCENTER); finally Canvas.Font.Assign(SaveFont); end; end; end; if dgIndicator in Options then begin IndicatorRT := Rect(0, 0, IndicatorWidth + 1, RowHeights[0]); Canvas.FillRect(IndicatorRT); IndicatorRT.Right := IndicatorRT.Right - 1; Canvas.Rectangle(IndicatorRT); IndicatorRT.Right := IndicatorRT.Right + 1; DrawEdge(Canvas.Handle, IndicatorRT, BDR_RAISEDOUTER, BF_RIGHT); end; end else begin inherited; if ACol = 0 then DrawEdge(Canvas.Handle, ARect, BDR_SUNKENOUTER, BF_BOTTOMRIGHT); end; end;function TADBGrid.ExtractSubTitle(LayerTitles: TStrings; ACol: Integer): Integer; var L, P: Integer; SubTitle: string; begin Result := 0; if Assigned(Columns[ACol]) then SubTitle := Columns[ACol].Title.Caption else Exit; if LayerTitles <> nil then LayerTitles.Clear; L := 0; repeat P := Pos('|', SubTitle); if P = 0 then begin if LayerTitles <> nil then LayerTitles.Add(SubTitle); end else begin if LayerTitles <> nil then LayerTitles.Add(Copy(SubTitle, 1, P - 1)); SubTitle := Copy(SubTitle, P + 1, Length(SubTitle) - P); end; L := L + 1; until P = 0; Result := L; end;procedure TADBGrid.Paint; var i, MaxLayer, Layer: Integer; TM: TTextMetric; begin if ([csLoading, csDestroying] * ComponentState) <> [] then Exit; MaxLayer := 0; //获取表头最大层数 for i := 0 to Columns.Count - 1 do begin Layer := ExtractSubTitle(nil, i); if Layer > MaxLayer then MaxLayer := Layer; end; SaveFont.Assign(Canvas.Font); Canvas.Font.Assign(TitleFont); try GetTextMetrics(Canvas.Handle, TM); //调整DBGrid的标题行高度 RowHeights[0] := (TM.tmHeight + TM.tmInternalLeading + 3) * MaxLayer; finally Canvas.Font.Assign(SaveFont); end; inherited; end;function TADBGrid.TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect; LayerID, ACol: Integer): TRect; var SubTitle: string; i, j: Integer; bBrer: Boolean; begin Result := TitleRect; if Assigned(Columns[ACol]) then SubTitle := Columns[ACol].Title.Caption else Exit; ExtractSubTitle(LayerTitles, ACol); //联合左边的兄弟列 for i := ACol - 1 downto 0 do begin ExtractSubTitle(BrerLayerTitles, i); bBrer := False; //判断是否为兄弟列 if (BrerLayerTitles.Count = LayerTitles.Count) then begin for j := 0 to LayerID do begin bBrer := BrerLayerTitles[j] = LayerTitles[j]; if not bBrer then Break; end; end; if bBrer then begin Result.Left := Result.Left - Columns[i].Width; if dgColLines in Options then Result.Left := Result.Left - 1; end else Break; end; //联合右边的兄弟列 for i := ACol + 1 to Columns.Count - 1 do begin ExtractSubTitle(BrerLayerTitles, i); bBrer := False; //判断是否为兄弟列 if BrerLayerTitles.Count = LayerTitles.Count then begin for j := 0 to LayerID do begin bBrer := BrerLayerTitles[j] = LayerTitles[j]; if not bBrer then Break; end; end; if bBrer then begin Result.Right := Result.Right + Columns[i].Width; if dgColLines in Options then Result.Right := Result.Right + 1; end else Break; end; //调整表头区域 Result.Top := (RowHeights[0] div LayerTitles.Count) * LayerID; Result.Bottom := (RowHeights[0] div LayerTitles.Count) * (LayerID + 1); end;end.
我 在 使 用 Delphi 5进 行 数 据 库 编 程 的 时 候 , 希 望 DBGRID构 件 在 显 示 数 据 的 时 候 能 象 FoxPro的BROWSE命 令 一 样 , 锁 定 左 边 指 定 的 几 列 不 进 行 滚 动 , 请 问 应 用 什 么 方 法 来 实 现 ?
我 们 知 道 Delphi的 TStringGrid有 一 个 属 性 FixedCols来 指 定 不 滚 动 的列 。 虽 然 TDBGrid不 能 直 接 使 用 这 一 属 性 , 但 通 过 强 制 类 型 转 换 也 可 以 实 先 这 一 功 能 , 因为 这 两 个 类 都 来 自 TCustomGrid类 。 下 面 我 们 以 Delphi 3.0的 Demos\Db\CtrlGrid为 例 来说 明 具 体 的 用 法 。 在 这 个 例 子 的 TFmCtrlGrid.FormShow过 程 中 加 入 如 下 一 行 :TStringGrid(DbGrid1).FixedCols := 2;
运 行 该 程 序 ,在 左 右 移 动 各 列 时, Symbol列 不 会 移 动 。 除 了 这 种 方 法 , 也 可 以 采 用 下 面 的 方 法 : 首 先 在 Form声 明 部 分 加上 type TMyGrid = Class(TDBGrid) end;然 后 在 TFmCtrlGrid.FormShow过程中加入: TMyGrid(DbGrid1).FixedCols := 2;
两 者 从 形 式 上 略 有 不 同 , 但 实 质 都 是 一 样 的 。 我 们 这 里 设 置FixedCols为 2, 这 是 因 为 在 DBGrid构 件 最 左 侧 有 个 指 示 列 , 如 果 你 将 DBGrid的 Options属性 的 dgIndicator设 为False, 则 应 设 置 FixedCols为 1。
Rect: TRect; State: TGridDrawState);
begin
with StringGrid1 do begin
Canvas.FillRect(Rect);
DrawText(GetDC(Handle),
PChar(Cells[ACol, ARow]),
Length(Cells[ACol, ARow]),
Rect,
DT_WORDBREAK);
end;
end;然后你的
comment:='1';
comment:=comment + #13 + #10 + '2';
StringGrid.cells[1,1]:=comment;
就能换行了
关键字 多表头
用法:
设置DBGrid的Column的Caption属性
例如:Column1的Caption为111|222
Column2的Caption为111|333
那么Column1和Column2公用一个表头111
unit ADBGrid;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, Math;type
TADBGrid = class(TDBGrid)
private
{ Private declarations }
//兄弟列子标题,当前列子标题
BrerLayerTitles, CurLayerTitles: TStringList;
SaveFont: TFont;
//根据当前数据列号和表头的层号获取表头的区域
function TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect; LayerID, ACol: Integer): TRect;
//解出当前数据列标题为子标题并返回标题层数(子标题数)
function ExtractSubTitle(LayerTitles: TStrings; ACol: Integer): Integer;
protected
{ Protected declarations }
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
end;procedure Register;implementationprocedure Register;
begin
RegisterComponents('Samples', [TADBGrid]);
end;constructor TADBGrid.Create(AOwner: TComponent);
begin
inherited;
BrerLayerTitles := TStringList.Create;
curLayerTitles := TStringList.Create;
SaveFont := TFont.Create;
end;destructor TADBGrid.Destroy;
begin
BrerLayerTitles.Free;
curLayerTitles.Free;
SaveFont.Free;
inherited;
end;procedure TADBGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
AState: TGridDrawState);
var
SubTitleRT, CaptionRt, IndicatorRT: TRect;
Column: TColumn;
SubTitle: string;
i: Integer;
begin
if (ARow = 0) and (ACol > 0) then
begin
ExtractSubTitle(curLayerTitles, RawToDataColumn(ACol));
for i := 0 to curLayerTitles.Count - 1 do
begin
SubTitleRT := TitleLayerRect(curLayerTitles, ARect, i, RawToDataColumn(ACol));
CaptionRt := SubTitleRT;
Canvas.Brush.Color := FixedColor;
Canvas.FillRect(SubTitleRT); DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDINNER, BF_TOPLEFT);
if i <> CurLayerTitles.Count - 1 then
begin
DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDOUTER, BF_BOTTOM);
Dec(SubTitleRT.Bottom, 2);
end else Dec(SubTitleRT.Bottom, 1);
Canvas.Pen.Color := clWhite;
Dec(SubTitleRT.Right, 1);
Canvas.MoveTo(SubTitleRT.Right, SubTitleRT.Top);
Canvas.LineTo(SubTitleRT.Right, SubTitleRT.Bottom);
Canvas.LineTo(SubTitleRT.Left, SubTitleRT.Bottom);
Column := Columns[RawToDataColumn(ACol)];
SubTitle := '';
if Assigned(Column) then
begin
SubTitle := CurLayerTitles[i];
SaveFont.Assign(Canvas.Font);
Canvas.Font.Assign(TitleFont);
try
InflateRect(SubTitleRT, -1, -1);
DrawText(Canvas.Handle, PChar(SubTitle), Length(SubTitle),
SubTitleRT, DT_CENTER or DT_SINGLELINE or DT_VCENTER);
finally
Canvas.Font.Assign(SaveFont);
end;
end;
end;
if dgIndicator in Options then
begin
IndicatorRT := Rect(0, 0, IndicatorWidth + 1, RowHeights[0]);
Canvas.FillRect(IndicatorRT);
IndicatorRT.Right := IndicatorRT.Right - 1;
Canvas.Rectangle(IndicatorRT);
IndicatorRT.Right := IndicatorRT.Right + 1;
DrawEdge(Canvas.Handle, IndicatorRT, BDR_RAISEDOUTER, BF_RIGHT);
end;
end
else begin
inherited;
if ACol = 0 then
DrawEdge(Canvas.Handle, ARect, BDR_SUNKENOUTER, BF_BOTTOMRIGHT);
end;
end;function TADBGrid.ExtractSubTitle(LayerTitles: TStrings;
ACol: Integer): Integer;
var L, P: Integer;
SubTitle: string;
begin
Result := 0;
if Assigned(Columns[ACol]) then
SubTitle := Columns[ACol].Title.Caption
else Exit;
if LayerTitles <> nil then LayerTitles.Clear;
L := 0;
repeat
P := Pos('|', SubTitle);
if P = 0 then
begin
if LayerTitles <> nil then LayerTitles.Add(SubTitle);
end
else begin
if LayerTitles <> nil then LayerTitles.Add(Copy(SubTitle, 1, P - 1));
SubTitle := Copy(SubTitle, P + 1, Length(SubTitle) - P);
end;
L := L + 1;
until P = 0;
Result := L;
end;procedure TADBGrid.Paint;
var
i, MaxLayer, Layer: Integer;
TM: TTextMetric;
begin
if ([csLoading, csDestroying] * ComponentState) <> [] then Exit;
MaxLayer := 0;
//获取表头最大层数
for i := 0 to Columns.Count - 1 do
begin
Layer := ExtractSubTitle(nil, i);
if Layer > MaxLayer then MaxLayer := Layer;
end;
SaveFont.Assign(Canvas.Font);
Canvas.Font.Assign(TitleFont);
try
GetTextMetrics(Canvas.Handle, TM);
//调整DBGrid的标题行高度
RowHeights[0] := (TM.tmHeight + TM.tmInternalLeading + 3) * MaxLayer;
finally
Canvas.Font.Assign(SaveFont);
end;
inherited;
end;function TADBGrid.TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect;
LayerID, ACol: Integer): TRect;
var
SubTitle: string;
i, j: Integer;
bBrer: Boolean;
begin
Result := TitleRect;
if Assigned(Columns[ACol]) then
SubTitle := Columns[ACol].Title.Caption
else Exit;
ExtractSubTitle(LayerTitles, ACol);
//联合左边的兄弟列
for i := ACol - 1 downto 0 do
begin
ExtractSubTitle(BrerLayerTitles, i);
bBrer := False;
//判断是否为兄弟列
if (BrerLayerTitles.Count = LayerTitles.Count) then
begin
for j := 0 to LayerID do
begin
bBrer := BrerLayerTitles[j] = LayerTitles[j];
if not bBrer then
Break;
end;
end;
if bBrer then
begin
Result.Left := Result.Left - Columns[i].Width;
if dgColLines in Options then
Result.Left := Result.Left - 1;
end
else Break;
end;
//联合右边的兄弟列
for i := ACol + 1 to Columns.Count - 1 do
begin
ExtractSubTitle(BrerLayerTitles, i);
bBrer := False;
//判断是否为兄弟列
if BrerLayerTitles.Count = LayerTitles.Count then
begin
for j := 0 to LayerID do
begin
bBrer := BrerLayerTitles[j] = LayerTitles[j];
if not bBrer then
Break;
end;
end;
if bBrer then
begin
Result.Right := Result.Right + Columns[i].Width;
if dgColLines in Options then
Result.Right := Result.Right + 1;
end
else Break;
end;
//调整表头区域
Result.Top := (RowHeights[0] div LayerTitles.Count) * LayerID;
Result.Bottom := (RowHeights[0] div LayerTitles.Count) * (LayerID + 1);
end;end.