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: 

    代码如下:

  • 相关阅读:
    ACM的算法分类 2015-04-16 14:25 22人阅读 评论(0) 收藏
    初学Larevel 2014-08-21 11:24 90人阅读 评论(0) 收藏
    初学PHP&MySQL 2014-05-31 12:40 92人阅读 评论(0) 收藏
    codeforces 570 E. Pig and Palindromes (dp)
    codeforces 570 D. Tree Requests (dfs序)
    poj 2157 Maze (bfs)
    cf 570 C. Replacement (暴力)
    cf 570B B. Simple Game(构造)
    cf 570 A. Elections
    hdu 1429胜利大逃亡(续) (bfs+状态压缩)
  • 原文地址:https://www.cnblogs.com/xifarm/p/Spread_DiagonalCellType.html
Copyright © 2011-2022 走看看