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即可

 

你可能感兴趣的:(function,table,Integer,Class,redirect,网格)