研发在 DBGrid 上完美地显示序号的方法(11分)

  • 主题发起人 主题发起人 kinneng
  • 开始时间 开始时间
不是不想用 RecNo,是不能用 RecNo,用TScrollInfo的方法,在添加、插入等操作,滚动条没变化,相当于顶贴的第 6 个方法,不行,高手们,还有什么高招,加油吧。
 
如果不想多写几行代码,又想什么问题都能解决,那只能等真正的高手出现了。在dbgrid中,其实很多地方就用到了RECNO。兵来将挡,水来土挡,在一些没触发滚动条的地方,写几行代码就触发就行了。做自己的产品,一般来说用RECNO是绝对够用了,查了一下楼主的贴子,确实跟我们的要求不一样,楼主是做控件产品的,解决问题的方法应该比我们更多,要求也更多。
 
是个关系到用户感观的东西,其实做数据处理时没什么帮助,关注。
 
3、使用 CalcField 计算字段,做在控件里面,强加一个计算字段给用家。
我认为这个序号字段应该是跟随DbGrid变化而变化,应该是Dbgrid的一个自身的属性。
即为记录的当前的行。

如果仅仅实现这种效果的话,3还是可行的。
 
各位高手们,很多人把 recno 误认为是序号,其实它是编号,删掉数据就不连续了。
 
TFdbgrid=class(Tdbgrid)
protected
procedure SetColumnAttributes; override;
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
end;
procedure TFdbgrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
AState: TGridDrawState);
var Ftoprow,i:Integer;
function gettoprow:Integer;
var i:Integer;
SInfo: TScrollInfo;
begin
for i:=0 to RowCount-1 do
begin
if DataLink.ActiveRecord=i then
begin
SInfo.cbSize := sizeof(SInfo);
SInfo.fMask := SIF_ALL;
GetScrollInfo(self.Handle, SB_VERT, SInfo);
if (DataLink.DataSet.State =dsInsert) and (DataLink.ActiveRecord=DataLink.BufferCount-1 ) then
begin
result:=SInfo.nPos-i+1;
end else
result:=SInfo.nPos-i;
if Result=0 then Result:=1;
Break;
end;
end;
end;
begin
if (ACol <= 0) then
begin
Canvas.Brush.Color := FixedColor;
Canvas.FillRect(ARect);
Ftoprow:=gettoprow-1;
if (ARow>0) then
Canvas.TextRect(ARect, 1, ARect.Top + 5, IntToStr(Arow+Ftoprow));
end else
inherited
end;
procedure TFdbgrid.SetColumnAttributes;
begin
inherited;
if (dgIndicator in Options) then
ColWidths[0] := 30;
end;
高手测试一下。我在本机上用BDE、ADO测试,滚动、新增、插入、删除操作暂时没发现问题
 
通过滚动条获得定位信息是个失败方案,我已经用了一年多时间,做了数万次试验,
不想再重复失败的。
 
直接用RECNO或滚动条信息,是比较简便的方法,如果数据库固定,用这两方法基本没问题。如果所使用的数据库及连接方式不可预知,可用RECNO及虚拟序号的方法,如果dataset.IsSequenced为true,可直接使用RECNO,否则利用自己建立的虚拟序号。如果还觉得虚拟序号方案不理想,那还是不用显示序号了。
 
创意、自由、灵活,超强的报表功能,独特的双数据源连接,全功能的表格组件!

http://www.anylib.com
 
RECNO或滚动条信息都是有问题的,数据集属性也不应该改。
 
我的表格是多数据源的,下拉框使用独立数据源,有多少下拉框就可以用多少数据源,
至于滚动条问题,我早研究过,它有很多毛病,假设数据行数大于表格行数,然后将光
标放在数据库最后一行,再按insert键,序号就出错了。还有一种方法就是建立RecNo与
序号的对照表,删除数据的时候维护这个表,但这很浪费资源。
 
找到一个不依靠recno及滚动条的方法,不过要多写点代码。
1.继承Tdatalink,在其中定义一Ftoprow变量,重写Dataevent过程,设置Ftoprow:=Ftoprow+count;
2.重写dbgrid的WMVScroll,将其中移动记录的first、last方法全部改为moveby方式(first等方法不会触发datalink的datasetscroll)
3.在drawcell中就可以直接引用datalink的Ftoprow了。

经试验,此方案不依赖于recno及scrollinfo,应该比较可靠。不方便的地方是需要重新创建一个继承自dbgrid的grid。
 
再次重申,RecNo的方法是失败的,反反复复提到它,只会误导其它有兴趣的网友。
DBGrid的滚动条的状态,跟数据的序号根本就没有关系,参考它计算滚动条的代码
就一清二楚,所以靠它来取得正确序号,完全是缘木求鱼。
 
新的方法并没有依赖RECNO。而且如果用的是ADO或clientdataset的话,用RECNO完全没有问题
 
我觉得各有各的方法!用recno也好,用Datalink也好!都是基于数据集的;
 
不是好不好的问题,是能用不能用的问题,用RecNo肯定不能使用BDE数据库,那就叫做失
败,还有什么可以辩解的,继续讨论RecNo就是浪费时间,还有滚动条,滚动条的计算,并
不与数据的序号有什么关系,如果不信,可以看DBGrid的源代码再上来贴。
不能直接使用,但不代表不能间接使用、部分使用,例如建立序号<=>RecNo对照表,或者在
不添加数据时使用滚动条信息,在添加数据时另想办法,都是可以的。
总之显示序号,不能牺牲原有的功能,不能够影响原来的性能,不能够对使用作出限制,
要无声无息在工作,否则的话毫无意义,不如考虑一下第3种计算字段的方法。
 
凡是能够贴出,符合下面要求:必须绝对计算正确,可应付各种状态的,绝对不能牺牲原有的功能,绝对不能够对使用作出限制,尽量不能够影响原来的性能。我重开新贴给300分。
 
找到一个不依靠recno及滚动条的方法,不过要多写点代码。
1.继承Tdatalink,在其中定义一Ftoprow变量,重写Dataevent过程,设置Ftoprow:=Ftoprow+count;
2.重写dbgrid的WMVScroll,将其中移动记录的first、last方法全部改为moveby方式(first等方法不会触发datalink的datasetscroll)
3.在drawcell中就可以直接引用datalink的Ftoprow了。
------------------------------------------------------------------------------
此方案的思想就是根本daaset移动时计算出当前grid的toprow,不依赖recno及滚动条。
 
楼主如果没看过Tdatalink代码,建议看看,如果看过了,建议再仔细看看dataEvent过程,妙全在里面。
 
不需要研究datalink,一样可以做得很好。
 
后退
顶部