zoukankan      html  css  js  c++  java
  • Spread 之自定义对角线cellType源码: DiagonalCellType

    最新的SpreadWinform提供了多达24种CellType类型,下面的这2篇博文对新增了GcTextBoxCellType和GcDateTimeCellType单元格格式做了比较详细的说明。

    Spread 7 for WinForms 新增的GcTextBoxCellType (水印、自动换行、自动大写、长度限制等)

    Spread 7 for WinForms 新增的GcDateTimeCellType (日期、时间格式)

    一般常规的做法是通过LineShape来做,《Spread for Winforms 表格控件:实现交叉报表》 用LineShape进行了编码实践,使用效果反响不错。

     Spread_CrossReport

    在实际项目中,有人提出,能否自定义一个CellType来实现而不是采用Shape方式呢?

    答案是肯定的,下面我们来一一说明详细过程:

    在实际项目中有如下三种需求---需要在Spread表头绘制对角线+表头文字:

    region2 双区域对角线,定义枚举为:e2Region。

    region3三区域对角线,定义枚举为:e3Region

     region4 四区域对角线,定义枚举为:e4Region

    Step 1: 输入文字需求

    • 字体默认获取系统的
    • 斜线的颜色和宽度可自定义
    • 背景色和前景色可自定义
    • 可选择文字对齐方向,并对超出区域文字剪裁处理
    • 编辑CellType区域 
    • Step 2:依据文字需求,快速手绘原型:right

    IMG_20131218_151539

    在手绘原型过程中,产生过如下三种原型,在评审中被否决的:error

    IMG_20131218_151521

    主要是考虑到横线、竖线、斜对角线没有太多的使用场景,目前用不上。

    Step 3:DiagonalCellType接口测试开发

    自定义CellType的目的是方便使用,故依照TDD的编程思路,先通过接口测试开始第一步工作,方便用户和其他系统自带的CellType切换使用,且能复用Cell已有的BackColor、Font、ForeColor、CellPadding。

    下面是双区域对角线的测试使用源码。(实际项目中,仅需要前4行源码即可实现双区域对角线的CellType使用)

      1:             //Diagonal_2Region
    
      2:             DiagonalCellType ct = new DiagonalCellType(DiagonalSubCellType.e2Region);
    
      3:             this.fpSpread1.ActiveSheet.Cells[1, 0].CellType = ct;            
    
      4:             ct.SetText("产品", StringAlignment.Far);
    
      5:             ct.SetText("日期", StringAlignment.Near, StringFormatFlags.DirectionVertical);            
    
      6:             this.fpSpread1.ActiveSheet.Cells[1, 0].BackColor = Color.Green;
    
      7:             this.fpSpread1.ActiveSheet.Cells[1, 0].Font = new Font("宋体", 12);
    
      8:             this.fpSpread1.ActiveSheet.Cells[1, 0].ForeColor = Color.Blue; //line
    
      9:             this.fpSpread1.ActiveSheet.Cells[1, 0].CellPadding = new CellPadding(5);

    Step 4:DiagonalCellType设计方法

    在双区域、三区域、四区域这3种对角线,彼此之间可复用的代码非常多,故我们考虑了采用如下设计模式:工厂方法、模板方法、策略方法、桥接模式等。

    为了简化设计,对DiagonalCellType做了抽象,仅用了24行代码实现了一个对角线的接口类。

      1:     public class DiagonalCellType : FarPoint.Win.Spread.CellType.TextCellType
    
      2:     {
    
      3:         #region CTOR
    
      4:         SubDiagonalCellTypeBase m_cellType = null;
    
      5:         public DiagonalCellType(DiagonalSubCellType subType)
    
      6:         {
    
      7:             m_cellType = SubDiagonalCellTypeBase.CreateSubType(subType);
    
      8:         }
    
      9:         #endregion
    
     10: 
    
     11:         public void SetText(string text, StringAlignment sstringAlignment = StringAlignment.Near, StringFormatFlags ssStringFormatFlags = StringFormatFlags.NoClip)
    
     12:         {
    
     13:             m_cellType.SetText(text, sstringAlignment, ssStringFormatFlags);
    
     14:         }
    
     15: 
    
     16:         public override void PaintCell(Graphics g, Rectangle r, Appearance appearance, object value, bool isSelected, bool isLocked, float zoomFactor)
    
     17:         {
    
     18:             m_cellType.PaintCell(g, r, appearance, value, isSelected, isLocked, zoomFactor);
    
     19:         }
    
     20: 
    
     21:         public override System.Windows.Forms.Control GetEditorControl(System.Windows.Forms.Control parent, Appearance appearance, float zoomFactor)
    
     22:         {
    
     23:             return null;
    
     24:         }
    
     25:     }

    DiagonalCellType继承自TextCellType,为了复用已有的文本单元格属性,而不是“从轮子做起”。这里,我们重载了2个函数,并作了函数覆盖:

    PaintCell:GDI+绘制文本、线条核心函数,具体实现3种区域对角线不一样,故在SubDiagonalCellTypeBase类中延迟实现之。

    GetEditorControl:考虑到表头区域在绘制表格前已经确定,不需要编辑,故重写函数,返回null则屏蔽了默认的Editor控件。

    Step 5: 双区域对角线编码实践

    SubDiagonalCellType_2Region是双区域对角线的实现类,共36行代码:

      1:     public class SubDiagonalCellType_2Region : SubDiagonalCellTypeBase
    
      2:     {
    
      3:         public override void InnerPaintCell(Graphics g, Rectangle r, Appearance appearance, object value, bool isSelected, bool isLocked, float zoomFactor)
    
      4:         {
    
      5:             //line 1
    
      6:             g.DrawLine(LinePen, r.X, r.Y, r.X + r.Width, r.Y + r.Height);
    
      7: 
    
      8:             //text 1
    
      9:             SizeF sf = m_TextList[0].GetSizeF(g, appearance);
    
     10:             float x = r.X + r.Width/2 - sf.Width - appearance.CellPadding.Left;
    
     11:             float y = r.Y + appearance.CellPadding.Top;
    
     12:             RectangleF rr = new RectangleF(x, y, r.Right - x - appearance.CellPadding.Left, sf.Height);
    
     13:            // g.FillRectangle(new SolidBrush(Color.White), rr); //Test Rectangle Size
    
     14:             m_TextList[0].DrawString(g, rr, appearance);
    
     15: 
    
     16:             //text 2
    
     17:             sf = m_TextList[1].GetSizeF(g, appearance);
    
     18:             y = r.Y + r.Height - sf.Height - appearance.CellPadding.Bottom;
    
     19:             x = r.X + appearance.CellPadding.Left;
    
     20:             rr = new RectangleF(x, y, r.Width / 2 , sf.Height);
    
     21:            // g.FillRectangle(new SolidBrush(Color.White), rr); //Test Rectangle Size
    
     22:             m_TextList[1].DrawString(g, rr, appearance);
    
     23:         }
    
     24: 
    
     25:         protected override void ValidateData()
    
     26:         {
    
     27:             if (m_TextList.Count != 2)
    
     28:             {
    
     29:                 throw new Exception("must SetText twice");
    
     30:             }
    
     31:         }
    
     32: 
    
     33:         public override DiagonalSubCellType DiagonalSubCellType
    
     34:         {
    
     35:             get { return DiagonalSubCellType.e2Region; }
    
     36:         }
    
     37:     }
    • DiagonalSubCellType: 用来标明当前类属于哪种类型
    • ValidateData:数据校验,因为双区域需要2个文本,故做判断处理,不满足条件抛出异常。
    • InnerPaintCell:实现绘制双区域的函数,这里采用的模板方法,在基类SubDiagonalCellTypeBase已经实现了ValidateData-数据校验、背景色填充等。
      前景色、背景色、bore、CellPadding复用了Cell自带的,亦可通过Designer设计。
      为了方便用户使用,添加了编辑器修改对角线文字(文字行不可增减)

    Spread_Diaonal

    GDI+的一些注意事项:

    • 垃圾回收完毕后,销毁GDI+对象,这里我们通过微软推荐的using。
    • 在使用的Form中,启用buffer和双缓存,代码如下:
      1: //提高GDI+ 效率
    
      2: this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
    
      3: 

    代码如下:

  • 相关阅读:
    架构师技能图谱 V1.2
    CTO 技能图谱
    物联网的技术构架
    东进交换机
    Ipad2
    ipad2 恢复
    论文建议
    SQL归档
    SQL 会议消费记录统计
    javascript中的方法:类方法(静态方法)对象方法 原型方法
  • 原文地址:https://www.cnblogs.com/xifarm/p/Spread_DiagonalCellType.html
Copyright © 2011-2022 走看看