200分,看各个都是高手,论谁是英雄。dbgrid问题 ( 积分: 200 )

  • 主题发起人 主题发起人 klmyzgl
  • 开始时间 开始时间
K

klmyzgl

Unregistered / Unconfirmed
GUEST, unregistred user!
在设计数据库录入界面时,经常需要实现的复杂题头,不考虑第3方控件。用TDBGRID实现多表头。
 
在设计数据库录入界面时,经常需要实现的复杂题头,不考虑第3方控件。用TDBGRID实现多表头。
 
各位都来看看,帮帮忙
 
在Borland尚未增加此项功能之前,建议使用DBGridEh
 
xianguo ,感谢关注,希望有能力的人都看看,1+1=2的类似问题 你们就是研究一辈字,不过个小学水平, 我一直在这关注,直到有人能结局
 
变态。请加分
 
呵呵,楼主太抬举我了。对于Delphi,只是学习了几天,不敢说研究,更谈不上小学水平。
希望楼主的执着会有结果
 
多表头

设置DBGrid的Column的Caption属性
例如:Column1的Caption为111|222
Column2的Caption为111|333
那么Column1和Column2公用一个表头111


unit ADBGrid;

interface

uses
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;

implementation

procedure 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;
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.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.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. 有点资料看看谁能搞出来
 
用 ClientDataSet 加 DBGrid 就可以实现多表头了
 
如何实现的呀,发个给我PZMZGL@163.COM
 
这不是复制粘贴的事吗? 用不着发这么多贴
 
研究一下dbgrideh吧,相信可以多少给你启发。俺现在还是菜。
 
1、楼主太执着了,你为了这个问题已经发了 3 个帖了,呵呵。
2、说句不该说的,我也觉得 Delphi 提供的表格没他妈一个像样的,DBGrid 没有“优生”,“优育”岂不是很辛苦。建议你在 WebBroswer 中用 Html 画表,画成什么样子都成,还能直接预览、打印,就是与 Delphi 的交互差了点,不过工作量应该不大于你改造 DBGrid;话又说回来,你既然准备用 DBGrid,那无非是从数据库中读取数据显示到前台或将修改提交给数据库,这些在 Html 的 Table 中都很 Easy,何乐而不为?
3、其实你懂得绘制表格的原理就足够了,至于谁把多表头这事替你做了那无关紧要,一点肤浅建议,答非所问,呵呵。
 
有这劲儿,写个自己的DBGRID用。想咋用就咋用。
 
vvyang 你和我的想发一样。我这个问题自己以解决了,我重画了那个该死的东西,有点不完善,改进中/,你说的方法,我很同意,我也在做这方面的尝试。有空交流一下
另我这个贴子,没有人,解决,我自己解决了如何回收我的分呀
 
我对别人回收分数一向很反感,楼主既然来论英雄,那也应该拿出点大侠风范,覆水难收,别动不动就回收分数,所以————把分给我,我再给你,就回收了!
 
目前结论: 楼主也是个问完不擦屁股的。
 
dbGrid 优点不在于界面,要实现丰富多彩的界面,包括多表头,需要写新的控件,例如我写的dbGridEx,就是一个例子。重要的是override drawCell,代码不会很多,还是靠你自己写吧。
 
浏览器控件有个事件,WebBrowser1_BeforeNavigate2 的,就是“在浏览之前”事件,在这里处理是否继续。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部