Grid分析 很久以前的笔记 有空再整理

TPanel

   |

TAcReportCtrl------相当于一个Grid

 

procedure TAcReportCtrl.DrawReport(hPaintDc: HDC; ps: TPaintStruct; rectPaint: TRect);

   // 绘制所有与失效区相交的矩形
  for I := 0 to FLineList.Count - 1 do
  begin
    ThisLine := TAcReportLine(FLineList[I]);
    for J := 0 to TAcReportLine(FLineList[i]).FCells.Count - 1 do
    begin
      ThisCell := TAcReportCell(ThisLine.FCells[J]);

      if ThisCell.OwnerCell = nil then
      begin
        ThisCell.DrawCellFrame(ACanvas, FPreviewStatus);
        ThisCell.Draw(ACanvas);
        if not FPreviewStatus and (ThisCell.Script.Count > 0) then
           ThisCell.DrawScriptFlag(ACanvas);
      end;
    end;
  end;

 

  if (Report.PageType <> ptDialog) and (DocMode = dmPrinting) then
  for I := 0  to Report.Objects.Count - 1 do
  begin
    t := Report.Objects[I];
    t.DrawCellFrame(ACanvas, FPreviewStatus);
    t.Draw(ACanvas);
    if not FPreviewStatus and (t.Script.Count > 0) then
      t.DrawScriptFlag(ACanvas);
  end;

 

 

procedure TEAReportDrawGrid.PaintGrid;
var
  I, N: Integer;
  vRow: TEAReportDrawGridRow;
begin
  if CanPaint then
  begin
    for I := 0 to Count - 1 do
    begin
      vRow := Rows[I];
      for N := 0 to vRow.Count - 1 do
        vRow.Cells[N].Paint;
    end;
    if CanDrawDragFrame then
      PaintDragFrame;
  end;
end;

 

procedure TEAReportStaticGrid.PaintDataGrid(AWidthArr: array of Integer);
var
  I, N, vInt1, vInt2, vDataHeight, vDataCount, vRealTitleHeight, vOff: Integer;
  vR1, vR2, vR3: TRect;
  vDrawStr: string;
  vFlags: Longint;
  vRectArr: TEARectArr;
begin
  if FOwner = nil then
    Exit;
   
  vR1 := FOwner.RealDisplayRect;
  if FShowTitle then
    vRealTitleHeight := GetViewScaleSize(FTitleHeight, ReportPmm.ViewScale)
  else
    vRealTitleHeight := 0;
  vDataCount := Trunc((TEARectFun.GetRectHeight(vR1)
    - vRealTitleHeight) / GetViewScaleSize(FDataHeight, ReportPmm.ViewScale));
  if vDataCount > RecordCount then
    vDataCount := RecordCount;
  vOff := 0;
  if FDataFillMode = edfmAutoHeight then
  begin
    if vDataCount <> 0 then
    begin
      vDataHeight := Trunc((TEARectFun.GetRectHeight(vR1) - vRealTitleHeight) / vDataCount);
      vOff := TEARectFun.GetRectHeight(vR1) - vRealTitleHeight - vDataHeight * vDataCount;
      if vOff < 0 then
        vOff := 0;
    end
    else
      vDataHeight := GetViewScaleSize(FDataHeight, ReportPmm.ViewScale);
  end
  else if FDataFillMode = edfmFixHeight then
  begin
    vDataHeight := GetViewScaleSize(FDataHeight, ReportPmm.ViewScale);
  end
  else begin  //FDataFillMode = ecwsDynamic
    vDataHeight := GetViewScaleSize(FDataHeight, ReportPmm.ViewScale);
    if (vDataCount < Self.RecordCount) and CanDynamicAdjustSize then
    begin
      vR1 := FOwner.RealDisplayRect;
      vDataCount := RecordCount;
      vRectArr := AdjustDynamicSize;
      if Length(vRectArr) > 0 then
      begin
        TEAPaintFun.InvalidateRectArr(ReportPmm.Handle, vRectArr);
      end;
    end;
  end;

  if (vDataCount = 0) or (TitleCount = 0) then
    Exit;

  vInt2 := vR1.Left;
  Canvas.Brush.Color := FOwner.Color;
  for I := 0 to TitleCount - 1 do
  begin
    Canvas.Font.Assign(Titles[I].FValueInfo.FFont);
    Canvas.Font.Size := GetViewScaleSize(Canvas.Font.Size, ReportPmm.ViewScale);
    vR2.Left := vInt2 + 1;
    vR2.Right := vInt2 + AWidthArr[I] - 1;
    vInt2 := vInt2 + AWidthArr[I];
    if vR2.Right > vR1.Right then
      vR2.Right := vR1.Right;

    vFlags := DT_EXPANDTABS or cSWordWraps[Titles[I].FValueInfo.FWordWrap]
      or cSHorzPosArr[Titles[I].FValueInfo.FHorzPos];

    vInt1 := vR1.Top + vRealTitleHeight;
    for N := 0 to vDataCount - 1 do
    begin
      vR2.Top := vInt1;
      vR2.Bottom := vInt1 + vDataHeight;
      if (FDataFillMode = edfmAutoHeight) then
      begin
        if N < vOff then
          Inc(vR2.Bottom);
        if (N = vDataCount - 1) and (vR2.Bottom < vR1.Bottom) then
        begin
          vR2.Bottom := vR1.Bottom;
        end;
      end;

      vInt1 := vR2.Bottom;
      vDrawStr := Cells[N, I];
      vR3 := vR2;
      Inc(vR3.Left, 2);
      vR3 := TEAPaintFun.GetTextRect(Canvas, vR3, vDrawStr,
        Titles[I].FValueInfo.FVertPos, Titles[I].FValueInfo.FWordWrap);

      DrawText(Canvas.Handle, PChar(vDrawStr), -1, vR3, vFlags);
      if (vR1.Right - vR2.Right > 1) then
        TEAPaintFun.Draw_Line(Canvas, vInt2, vR2.Top, vInt2, vInt1);
      if (I = 0) and (vR1.Bottom - vInt1 > 1) then
        TEAPaintFun.Draw_Line(Canvas, vR1.Left + 1, vInt1, vR1.Right, vInt1);

      if (vInt1 >= vR1.Bottom) or (vInt2 > vR1.Right) then
        Break;
    end;
  end;
end;

 

 

EReport中

 

component是其核心源码
WMPaint
WMLButtonDBLClk
WMLButtonDown

TReportCell属于TReportLine,TReportCell

TReportLine属于 TReportControl,TReportLine的所有水平坐标应该相接,
 纵坐标不一定在一条线上


TReportControl = Class(TWinControl) 纸张大小相关 可交互操作

TReportRunTime = Class(TComponent)与数据集相关
一个Line中的所有Cell是同样高度前后相接排成一行

一个Cell若包含子Cell,则这些子Cell必同样宽度上下相接排成一列(其实就是多行)。
合并后的原左上角的cell包含了下面的Cell.

 

Table一个表格
NewTable(ColNumber, RowNumber: Integer);
创建Table时指定行列,则有一个最基本行。

 

CombineCell;
先进行行合并。同一行的Cell除第一个以外全部从所属的行中去掉。
第一个Cell的宽度修改为所有选中Cell的宽度之和。

列合并,左上角的Cell owned所有其他选中的cell.其它选中的cell

 

 

CombineCellHorz;

 

EhReport1.VSplitCell(VSplitForm.VSplitCount.AsInteger);

SplitCell:核心
RemoveOwnedCell

VSplitCell(Number: Integer);
纵列水平Split,最多Split为Number个
调整第一列的宽度
以要Split的Cell为模板,创建一个Cell,插入到该Cell所属行。
以要Split的Cell Owned的Cell为模板,创建一列Cell。

 

一个Cell可以包含一个表格,选择单元格时,可以仅包含Cell中的Table中的表格。
如果跨越两个表格,则其中一个表格必须完全被包含。

 

EasyGrid加入嵌套则可实现任意网格。
先仅考虑固定行列的网格,及其分割合并。
复杂的表格可以看作简单网格的嵌套。


一个网格由Cell(行*列)组成,合并,拆分都是这些cell的拆分。

一个网格由Cell组成。Cell包含0个或多个网格。

TCustomEasyGrid.SetMerges
EasyGrid中每一个被合并的Cell,都记录有被合并后的最大区域。
AMergeRect中的数值为Cell的逻辑坐标。
for i := AMergeRect.Left to AMergeRect.Right do
    for j := AMergeRect.Top to AMergeRect.Bottom do
    begin
      Cells[i,j].Merge := AMergeRect;
      CellToCell(@ValueCellInfo, Cells[i, j]);
      if (i <> AMergeRect.Left) or (j <> AMergeRect.Top) then
      begin
        Cells[i,j].ForeText := '';
        Cells[i,j].BackText := '';
      end;
    end;

EsayGrid行模式。每一行的最小的CELL数目是一样的。

EReport行模式。如果不用嵌套,EReport可以把两个基本单元合并为1个,再拆分为3个。而EsayGrid不行。只能再拆分为2个。


/
EhLib
Gridseh
DrawCells//行模式
  CurRow := ARow;
    Where.Top := StartY;
    while (Where.Top < StopY) and (CurRow < RowCount) do
    begin
      CurCol := ACol;
      Where.Left := StartX;
      Where.Bottom := Where.Top + RowHeights[CurRow];
      while (Where.Left < StopX) and (CurCol < ColCount) do

 

//EasyGrid
DrawCells
    // 双层行列循环(先行后列)
    while (Where.Top < DrawRect.Bottom) and (CurRow <= EndRow) do
    begin
      CurCol := StartCol;
      Where.Left := DrawRect.Left;
      while (Where.Left < DrawRect.Right) and (CurCol <= EndCol) do


EasyGrid实现斜线 ,各种控件的插入。
数据获取,类似TStringgrid由外部在事件中提供,或者直接确定其文本。


二维转换为1维。设计时和运行时,运行时网格固定不可在增添。
一个List按行的顺序管理所有Cell的指针。


清单式网格打印时,网格固定,
清单式网格输入数据时行数目不确定。分为多个列。

 

XLGrid看Demo对其的应用了解初步的架构
TXLSheet = class(TComponent)类似于文档,FUsers类似于视图列表
TXLSheet.FSections: array[TXLSector] of TXLSection;//TXLSector  = (sCols, sRows, sTitle, sClient);


TXLSection = class(TListSList)

TXLView = class(TWinControl)

TXLGrid = class(TCustomPanel, IXLSheetUser)类似于视图。
一个Grid拥有四个TXLView :ColsView,RowsView,TitleView,ClientView
一个Grid对应一个TXLSheet

TXLSection.PaintRect //4995 行 PaintRect Begin
PaintCells
TXLSection.PaintCell

TXLSheet.Objects[]
PeekCells[]
function  TXLSection.GetPeekCell(ACoord: TPoint): TXLCell;
var XLRow: TXLRow;
begin
  ACoord := Redirect(ACoord);
  Result := Nil; XLRow := TXLRow(Items[ACoord.Y]);
  if XLRow <> Nil then Result := TXLCell(XLRow[ACoord.X]);
end;
function  TXLSection.GetPeekCell(ACoord: TPoint): TXLCell;
var XLRow: TXLRow;
begin
  ACoord := Redirect(ACoord);
  Result := Nil; XLRow := TXLRow(Items[ACoord.Y]);
  if XLRow <> Nil then Result := TXLCell(XLRow[ACoord.X]);
end;
行模式!!!


TXLRow


TXLView.WMPaint核心DoDraw


TXLEditCell可看作TXLEditInfo的特例,模拟消息
TXLAxis 看作0..1即可

 

1) 以前很想做关于自定义界面的东东,但是一直都在用PB的公司上班(目前都是), 时间又紧就一直没有做了,前段时间在做一个系统时,觉得有必要采用灵活多 变的自定义界面方式来实现(觉得还是delphi这些方面强,pb可能不好实现), 从技术上来说采用控件在窗口上拖拉来实现也不 会太难。由于我接触的财务比较多,觉得还是用表格来实现好些。中国财务的 填写多是表格!我也看到网上也有用 XLGrid 做成功的,好象这个东东不能在单 元格中嵌入表格,列表框之类的,不能实现主从表录入(好象是啊)。2) 如果自己来做表格控件,工作量较大。我以前用过王寒松的表格,觉得还是可以, 但是觉得不能象Excel而是类似于Word的表格,这是本身设计思想的结果,最后还 是选用了EasyGrid。 该控件是由Delphi中Grids的修改过来的。而且也改的很好。3) 由于时间紧,而且现在手中有项目要做(都拖了快一周了),因此作的很简单。 好多东西都没有作好,还有很多要完善,目前只是简单的实现了单元格连接了字段 和字段标签以及在单元格中嵌入表格,目的实现主从录入。嵌入的表格在IDE 环境中可以保存,但是在运行时期表格的保存还没有做,而且需要做一个在运行时期。 的编辑器,可以在运行时期对表格编辑。同样单元格还可以嵌入图片和ListBox,TreeView。 但是现在确实不能再写了,公司的事还是要作的,否者饭碗丢了,就掺了。我算了一下 要作的基本差不多,还要三周时间,有时间的话我一定会写完的。我个人分析一下: 用这个东东再结合语法解析器,来实现开发平台可性行是很高的。4) 经常看到在网上有人要计算表达式,顺便把我以前写的表达式解析器也送上来。 可以计算字段和数值的混合运算,支持If。最多支持两个数据集的字段运算。 改写人 : liuzhigang 地址 : 四川.成都 (德阳) Email : lzg_0625@yahoo.com.cn
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值