K
kinneng
Unregistered / Unconfirmed
GUEST, unregistred user!
这两天上来灌水,见到有贴《dbgrid能做出每行每个单元格宽度各不一样的列表吗?要求贴
内所示 3200分急求方法》http://www.delphibbs.com/delphibbs/dispq.asp?lid=3536549
哇塞! 3200分,天价,虽然真正会放分的机会很渺茫,不过题目倒是很有意思,也许有些
人认为做不出来,所以人投了这么多分。
一、
在 Grids.pas 里面,有个函数是取格子的宽度的 GetColWidths,有很多函数靠它来取得
列的宽度,包括绘图部分等等,所以解决它就解决了很多问题。
function TCustomGrid.GetColWidths(Index: Longint): Integer;
begin
if (FColWidths = nil) or (Index >= ColCount) then
Result := DefaultColWidth
else
Result := PIntArray(FColWidths)^[Index + 1];
end;
扩充它为:
function TCustomGrid.GetColWidths(Index, ARow: Longint): Integer;
var
FWidth: Integer;
begin
if (FColWidths = nil) or (Index >= ColCount) then
FWidth := DefaultColWidth
else
FWidth := PIntArray(FColWidths)^[Index + 1];
//新增一个事件,让用户可以重新定义格子的宽度
if Assigned(FGetCellWidthEvent) then
FGetCellWidthEvent(Index, ARow, FWidth);
if FWidth < 0 then FWidth :=0; //避免用户恶搞,保证宽度不小于0
Result := FWidth;
end;
然后,凡是涉及这个函数的地方,一律加上 ARow 参数,具体就几处而已,现在的水费贵,
不灌了。
二、
画格子是在 Paint 过程里面画的,因为不在需要画上规则的垂直线,所以把画垂直线的部
分处理一下:
DrawLines(goHorzLine in Options, goVertLine in Options, LeftCol,
TopRow, [Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridBoundary,
Vert.GridBoundary], LineColor, Color);
StackFree(StrokeList);
StackFree(PointsList);
end;
将这句 goVertLine in Options 改成 False 永远禁止绘制垂直线!
DrawLines(goHorzLine in inherited Options, False, LeftCol,
TopRow, [Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridBoundary,
Vert.GridBoundary], LineColor, Color);
StackFree(StrokeList);
StackFree(PointsList);
end;
垂直线总要画的,我找了个画的地方,在 Paint 的子过程 DrawCells 里面,看到这两句
Where.Left := Where.Right + DrawInfo.Horz.EffectiveLineWidth;
Inc(CurCol);
end;
Where.Top := Where.Bottom + DrawInfo.Vert.EffectiveLineWidth;
Inc(CurRow);
现在加上自己画垂直线的代码,
if (CurCol >0)and(CurRow>0) then
begin
Canvas.MoveTo(Where.Right, Where.Top);
Canvas.LineTo(Where.Right, Where.Bottom);
end;
Where.Left := Where.Right + DrawInfo.Horz.EffectiveLineWidth;
Inc(CurCol);
end;
Where.Top := Where.Bottom + DrawInfo.Vert.EffectiveLineWidth;
Inc(CurRow);
实际上还要加上标题,指示列是否存在的判断代码,这里做实验,就免了,到
此为止,在界面上基本达到要求。
三、
界面上达到要求,但鼠标点击还有问题!有一个 CalcCoordFromPoint 的函数
是做这方面计算的。它的子函数 DoCalc 要修改!
for I := Start to Stop do
begin
Inc(Line, GetExtent(I) + EffectiveLineWidth);
if N < Line then
begin
Result := I;
Exit;
end;
end;
先将 DoCalc 复制一份,改名为 DoCalcY,然后修改 DoCalc 为:
for I := Start to Stop do
begin
Inc(Line, GetColWidths(I,Y) + EffectiveLineWidth);
if N < Line then
begin
Result := I;
Exit;
end;
end;
利用前面修改的 GetColWidths,然后将 CalcCoordFromPoint 函数
if not UseRightToLeftAlignment then
Result.X := DoCalc(DrawInfo.Horz, X, Result.Y)
else
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X, Result.Y);
修改为
Result.Y := DoCalcY(DrawInfo.Vert, Y); //利用原来的函数计算垂直间距
if not UseRightToLeftAlignment then
Result.X := DoCalc(DrawInfo.Horz, X, Result.Y)
else
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X, Result.Y);
这样鼠标点击就不会出现错位。
下载 http://kinneng.icpcn.com/htm/demo.htm
下面还要解决滚动!编辑框的问题,滚动在 Scroll 过程里面修改,而编辑框的
定位主要是修改 BoxRect 函数,不难修改。
改来改去,好像都在修改 Grids.pas 和 DBGrid 无关,但真是这么改就可以
成功的,因为 DBGrid 是 CustomGrid 的扩展版!
无论 Grids.pas 和 DBGrid.pas 都是不应该改的,这里只是做实验,最后把所有
改动,合成为新的独立控件。
到此,我已经解决了大部分问题,看上去简单,但实际真的很复杂,要了解其中
各种函数用途和算法,否则就无从入手,我没空不再搞下去了,也没有搞下去的
价值!即使是想拿来炫耀技术,也不值得花这个时间!
内所示 3200分急求方法》http://www.delphibbs.com/delphibbs/dispq.asp?lid=3536549
哇塞! 3200分,天价,虽然真正会放分的机会很渺茫,不过题目倒是很有意思,也许有些
人认为做不出来,所以人投了这么多分。
一、
在 Grids.pas 里面,有个函数是取格子的宽度的 GetColWidths,有很多函数靠它来取得
列的宽度,包括绘图部分等等,所以解决它就解决了很多问题。
function TCustomGrid.GetColWidths(Index: Longint): Integer;
begin
if (FColWidths = nil) or (Index >= ColCount) then
Result := DefaultColWidth
else
Result := PIntArray(FColWidths)^[Index + 1];
end;
扩充它为:
function TCustomGrid.GetColWidths(Index, ARow: Longint): Integer;
var
FWidth: Integer;
begin
if (FColWidths = nil) or (Index >= ColCount) then
FWidth := DefaultColWidth
else
FWidth := PIntArray(FColWidths)^[Index + 1];
//新增一个事件,让用户可以重新定义格子的宽度
if Assigned(FGetCellWidthEvent) then
FGetCellWidthEvent(Index, ARow, FWidth);
if FWidth < 0 then FWidth :=0; //避免用户恶搞,保证宽度不小于0
Result := FWidth;
end;
然后,凡是涉及这个函数的地方,一律加上 ARow 参数,具体就几处而已,现在的水费贵,
不灌了。
二、
画格子是在 Paint 过程里面画的,因为不在需要画上规则的垂直线,所以把画垂直线的部
分处理一下:
DrawLines(goHorzLine in Options, goVertLine in Options, LeftCol,
TopRow, [Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridBoundary,
Vert.GridBoundary], LineColor, Color);
StackFree(StrokeList);
StackFree(PointsList);
end;
将这句 goVertLine in Options 改成 False 永远禁止绘制垂直线!
DrawLines(goHorzLine in inherited Options, False, LeftCol,
TopRow, [Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridBoundary,
Vert.GridBoundary], LineColor, Color);
StackFree(StrokeList);
StackFree(PointsList);
end;
垂直线总要画的,我找了个画的地方,在 Paint 的子过程 DrawCells 里面,看到这两句
Where.Left := Where.Right + DrawInfo.Horz.EffectiveLineWidth;
Inc(CurCol);
end;
Where.Top := Where.Bottom + DrawInfo.Vert.EffectiveLineWidth;
Inc(CurRow);
现在加上自己画垂直线的代码,
if (CurCol >0)and(CurRow>0) then
begin
Canvas.MoveTo(Where.Right, Where.Top);
Canvas.LineTo(Where.Right, Where.Bottom);
end;
Where.Left := Where.Right + DrawInfo.Horz.EffectiveLineWidth;
Inc(CurCol);
end;
Where.Top := Where.Bottom + DrawInfo.Vert.EffectiveLineWidth;
Inc(CurRow);
实际上还要加上标题,指示列是否存在的判断代码,这里做实验,就免了,到
此为止,在界面上基本达到要求。
三、
界面上达到要求,但鼠标点击还有问题!有一个 CalcCoordFromPoint 的函数
是做这方面计算的。它的子函数 DoCalc 要修改!
for I := Start to Stop do
begin
Inc(Line, GetExtent(I) + EffectiveLineWidth);
if N < Line then
begin
Result := I;
Exit;
end;
end;
先将 DoCalc 复制一份,改名为 DoCalcY,然后修改 DoCalc 为:
for I := Start to Stop do
begin
Inc(Line, GetColWidths(I,Y) + EffectiveLineWidth);
if N < Line then
begin
Result := I;
Exit;
end;
end;
利用前面修改的 GetColWidths,然后将 CalcCoordFromPoint 函数
if not UseRightToLeftAlignment then
Result.X := DoCalc(DrawInfo.Horz, X, Result.Y)
else
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X, Result.Y);
修改为
Result.Y := DoCalcY(DrawInfo.Vert, Y); //利用原来的函数计算垂直间距
if not UseRightToLeftAlignment then
Result.X := DoCalc(DrawInfo.Horz, X, Result.Y)
else
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X, Result.Y);
这样鼠标点击就不会出现错位。
下载 http://kinneng.icpcn.com/htm/demo.htm
下面还要解决滚动!编辑框的问题,滚动在 Scroll 过程里面修改,而编辑框的
定位主要是修改 BoxRect 函数,不难修改。
改来改去,好像都在修改 Grids.pas 和 DBGrid 无关,但真是这么改就可以
成功的,因为 DBGrid 是 CustomGrid 的扩展版!
无论 Grids.pas 和 DBGrid.pas 都是不应该改的,这里只是做实验,最后把所有
改动,合成为新的独立控件。
到此,我已经解决了大部分问题,看上去简单,但实际真的很复杂,要了解其中
各种函数用途和算法,否则就无从入手,我没空不再搞下去了,也没有搞下去的
价值!即使是想拿来炫耀技术,也不值得花这个时间!