.Net单据打印有很多方法,目前介绍一种完全画线,绘制文本的方法,效果图如下
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wms.Print.Service.Base;
namespace Wms.Print.Service.Grid
{
/// <summary>
/// 绘制网格,核心是二维数组,可以是DataGrid、MsHFlexGrid、DataTable、HtmlTable等二维表现形式的数据源。
/// </summary>
public class DrawGrid : MyGrid, IDraw, IDisposable
{
//************字 段************
private Graphics mGraphics; //绘图表面
private Rectangle mRectangle; //绘制区
//绘笔
private Brush mBrush;
private Pen mPen;
#region IDraw 成员
/// <summary>
/// 获取或设置绘图表面
/// </summary>
public Graphics Graphics
{
get
{
return this.mGraphics;
}
set
{
this.mGraphics = value;
}
}
/// <summary>
/// 获取或设置绘制区域
/// </summary>
public Rectangle Rectangle
{
get
{
return mRectangle;
}
set
{
mRectangle = value;
}
}
/// <summary>
/// 画笔
/// </summary>
public Pen Pen
{
get
{
return mPen;
}
set
{
if (value != null)
{
mPen = value;
}
}
}
/// <summary>
/// 画刷
/// </summary>
public Brush Brush
{
get
{
return mBrush;
}
set
{
if (value != null)
{
mBrush = value;
}
}
}
#endregion
private Font[] mFonts;
/// <summary>
/// 网格各列的字体,仅对不合并的网格有效
/// </summary>
public Font[] Fonts
{
get { return mFonts; }
set { mFonts = value; }
}
/// <summary>
///
/// </summary>
public DrawGrid()
{
mPen = new Pen(Color.Black);
mBrush = Brushes.Black;
}
/// <summary>
///
/// </summary>
/// <param name="rows"></param>
/// <param name="cols"></param>
public DrawGrid(int rows, int cols)
{
this.Initialize(rows, cols);
}
/// <summary>
///
/// </summary>
public override void Dispose()
{
base.Dispose();
if (mGraphics != null)
this.mGraphics.Dispose();
}
/// <summary>
/// 绘制网格线,不包括边界线
/// </summary>
public void DrawGridLine()
{
DrawGridLine(this.mGraphics, this.mRectangle, this.Pen, this.GridText, this.PreferredRowHeight, this.ColsWidth, this.Line, this.Border, new PointF(1.0F, 1.0F), this.Merge);
}
/// <summary>
/// 绘制网格文本
/// </summary>
public void DrawGridText()
{
DrawGridText(this.mGraphics, this.mRectangle, this.Brush, this.GridText, this.PreferredRowHeight, this.ColsWidth, this.ColsAlignString, this.Font, new PointF(1.0F, 1.0F), this.Merge);
}
/// <summary>
/// 绘制边框
/// </summary>
public void DrawGridBorder()
{
DrawGridBorder(this.mGraphics, this.mRectangle, this.Pen, this.Border);
}
/// <summary>
/// 绘制网格络及文本和边框
/// </summary>
public void Draw()
{
DrawGridLine();
/*
//测试绘制用的时间
System.DateTime dt1;
dt1 = System.DateTime.Now;
Console.WriteLine(dt1.ToString() + dt1.Millisecond.ToString());
*/
//______________________
DrawGridText();
//______________________
/*
System.DateTime dt2;
dt2 = System.DateTime.Now;
Console.WriteLine(dt2.ToString() + dt2.Millisecond.ToString());
TimeSpan aa = dt2 - dt1;
double secondDef = aa.TotalSeconds;
Console.WriteLine(secondDef.ToString());
*/
DrawGridBorder();
}
#region 绘制核心
#region 画标准横坚网格线核心 protected void DrawGridLine(Graphics g,Rectangle p_rec,int p_rows,int p_cols,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY)
/// <summary>
/// 画网格线,标准备的横竖线交叉的线
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmPen">绘图线的笔,可以定义颜色与线宽</param>
/// <param name="p_rows">行数</param>
/// <param name="p_cols">列数</param>
/// <param name="p_rowHeight">行高</param>
/// <param name="p_arrColsWidth">列宽</param>
/// <param name="p_gridLineFlag">网格线类型</param>
/// <param name="p_gridBorderFlag">边框类型</param>
/// <param name="p_scaleXY">水平与垂直方向缩放量</param>
protected void DrawGridLine(Graphics g, Rectangle p_rec, Pen pmPen, int p_rows, int p_cols, int p_rowHeight, int[] p_arrColsWidth, GridLineFlag p_gridLineFlag, GridBorderFlag p_gridBorderFlag, PointF p_scaleXY)
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
//缩放程序
this.TransGrid(g, rec, p_scaleXY);
#region 有网格线才画
if (p_gridLineFlag != GridLineFlag.None)
{
int lngRows = p_rows; //arrStrGrid.GetLength(0); //行数,也可由二维数组算出
int lngCols = p_cols; //arrStrGrid.GetLength(1); //列数
int lngRowIndex; //当前行
int lngColIndex; //当前列
//起止坐标
int X1, X2, Y1, Y2;
int lngLineLen; //线长
int lngLineHei; //线高
//计算坐标、线长、线高
lngLineLen = rec.Width;
lngLineHei = rec.Height;
#region 包括横线就画
if (p_gridLineFlag == GridLineFlag.Horizontal || p_gridLineFlag == GridLineFlag.Both)
{
//******先画横线******
X1 = rec.X;
Y1 = rec.Y;
X2 = X1 + lngLineLen;
//最上边与最下边的线不画
for (lngRowIndex = 1; lngRowIndex < lngRows; lngRowIndex++)
{
Y1 += p_rowHeight; //这里可以换成行高数组
//Y1 += p_arrRowsWidth[lngRowIndex - 1];//这里可以换成行高数组
Y2 = Y1;
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
}
#endregion
#region 包括竖线就画
if (p_gridLineFlag == GridLineFlag.Vertical || p_gridLineFlag == GridLineFlag.Both)
{
//******再画竖线******
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
//Y不变
X1 = rec.X;
Y1 = rec.Y;
Y2 = Y1 + lngLineHei;
//最左边与右边的线不画
for (lngColIndex = 0; lngColIndex < lngCols - 1; lngColIndex++)
{
X1 += mArrColWidth[lngColIndex];
X2 = X1;
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
}
#endregion
}//End If
#endregion
//******边框******
if (p_gridBorderFlag != GridBorderFlag.None)
{
this.DrawGridBorder(g, rec, pmPen, p_gridBorderFlag);
}
//重置,不再变换
this.ResetTransGrid();
}
#endregion
#region protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen pmPen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY)
/// <summary>
/// 画网格线,标准备的横竖线交叉的线
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmPen">绘图线的笔,可以定义颜色与线宽</param>
/// <param name="arrStrGrid">二维数组,对应了网格行、列数</param>
/// <param name="p_rowHeight">行高</param>
/// <param name="p_arrColsWidth">列宽</param>
/// <param name="p_gridLineFlag">网格线类型</param>
/// <param name="p_gridBorderFlag">边框类型</param>
/// <param name="p_scaleXY">水平与垂直方向缩放量</param>
protected void DrawGridLine(Graphics g, Rectangle p_rec, Pen pmPen, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, GridLineFlag p_gridLineFlag, GridBorderFlag p_gridBorderFlag, PointF p_scaleXY)
{
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
DrawGridLine(g, p_rec, pmPen, lngRows, lngCols, p_rowHeight, p_arrColsWidth, p_gridLineFlag, p_gridBorderFlag, p_scaleXY);
}
#endregion
#region 画合并线的核心 protected void DrawGridMergeLine(Graphics g,Rectangle p_rec,Pen pmPen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
/// <summary>
/// 画网格线,根据合并方式判断相邻单元格内容一格一格的画
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmPen">绘图线的笔,可以定义颜色与线宽</param>
/// <param name="arrStrGrid">二维数组</param>
/// <param name="p_rowHeight">行高</param>
/// <param name="p_arrColsWidth">列宽</param>
/// <param name="p_gridLineFlag">网格线类型</param>
/// <param name="p_gridBorderFlag">边框类型</param>
/// <param name="p_scaleXY">水平与垂直方向缩放量</param>
/// <param name="gridMergeFlag">网格单元格合并方式</param>
protected void DrawGridMergeLine(Graphics g, Rectangle p_rec, Pen pmPen, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, GridLineFlag p_gridLineFlag, GridBorderFlag p_gridBorderFlag, PointF p_scaleXY, GridMergeFlag gridMergeFlag)
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
//网格不合并直接画标准网格线,否则一个单元格一个单元格的画
if (gridMergeFlag == GridMergeFlag.None)
{
this.DrawGridLine(g, rec, pmPen, lngRows, lngCols, p_rowHeight, p_arrColsWidth, p_gridLineFlag, p_gridBorderFlag, p_scaleXY);
return;
}
else
{
#region 有网格线才画
if (p_gridLineFlag != GridLineFlag.None)
{
//变换
this.TransGrid(g, rec, p_scaleXY);
//起止坐标
int X1, X2, Y1, Y2;
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
#region 画单元格线
//边界不画
for (int i = 0; i < lngRows; i++)
{
X1 = rec.X;
Y1 = rec.Y;
for (int j = 0; j < lngCols; j++)
{
//-----水平线-----
X2 = X1 + mArrColWidth[j];
Y1 = rec.Y + p_rowHeight * i; //****可用行高数组
Y2 = Y1;
//画第二行开始及以下的横线,当前行与上一行文本不同
if (i > 0)
{
//任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
if (gridMergeFlag == GridMergeFlag.Any)
{
//画线(条件:此列不合并 || 文本空 || 当前行与上一行文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i - 1, j])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
}
}
//-----'竖线-----
//画第二列以后的竖线,当前列与上一列比较
if (j > 0)
{
Y2 = Y2 + p_rowHeight; //****可用行高数组
X2 = X1;
//任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
if (gridMergeFlag == GridMergeFlag.Any)
{
//画线(条件:此行不合并 || 文本空 || 当前列与上一列文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i, j - 1])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
}
}
//下一列,宽加上
X1 += mArrColWidth[j];
}//End For 列
}//End For 行
#endregion
//******边框******
if (p_gridBorderFlag != GridBorderFlag.None)
{
this.DrawGridBorder(g, rec, pmPen, p_gridBorderFlag);
}
//重置,不再变换
this.ResetTransGrid();
}//End If
#endregion
}//End If
}//End Function
#endregion
#region 标准不合并网格的文本 protected void DrawGridText(Graphics g,Rectangle p_rec,Brush pmBrush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY)
/// <summary>
/// 绘制网格文本,标准的行与列单元格,无合并
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmBrush">绘图文本的画刷,可以定义颜色</param>
/// <param name="arrStrGrid">二维字符数组(网格)</param>
/// <param name="p_rowHeight">固定行高</param>
/// <param name="p_arrColsWidth">列宽数组,为null时则平均列宽</param>
/// <param name="alignment">由Left,Center,Right对齐方式第一个字母组成的串</param>
/// <param name="p_scaleXY">指定X与Y向缩放比例值</param>
/// <param name="p_font"></param>
protected void DrawGridText(Graphics g, Rectangle p_rec, Brush pmBrush, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, string alignment, Font p_font, PointF p_scaleXY)
{
try
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
Font font = p_font;
if (font == null)
{
font = new Font("宋体", 12.0F);
}
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
//列对齐方式
AlignFlag[] arrAlign;
arrAlign = this.GetColsAlign(alignment);
//变换
this.TransGrid(g, rec, p_scaleXY);
//起止坐标
int X1, Y1, width;
#region 画单元格文本
StringFormat sf = new StringFormat(); //字符格式
sf.LineAlignment = StringAlignment.Center; //垂直居中
// sf.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
sf.FormatFlags = StringFormatFlags.LineLimit;
for (int i = 0; i < lngRows; i++)
{
X1 = rec.X;
Y1 = rec.Y + p_rowHeight * i; //****可用行数组
for (int j = 0; j < lngCols; j++)
{
width = mArrColWidth[j];
Rectangle recCell = new Rectangle(X1, Y1, width, p_rowHeight + 4); //实际上居中会稍微偏上,因为字体有预留边距
sf.Alignment = StringAlignment.Near; //默认左对齐
if (arrAlign.Length > j)
{
if (arrAlign[j] == AlignFlag.Center)
{
sf.Alignment = StringAlignment.Center; //居中
}
else if (arrAlign[j] == AlignFlag.Right)
{
sf.Alignment = StringAlignment.Far; //居右
}
}
//改变字体,以Fonts属性的为准,若Fonts未被赋值,则按整个DarwGrid的字体来打印
Font realFont = font;
if (mFonts != null && mFonts.Length > j && mFonts[j] != null)
{
realFont = mFonts[j];
}
if (lngCols == 12)
{
if (j == 1 || j == 7)
{
if (arrStrGrid[i, j].Length > 10)
{
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
else
{
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
}
else
{
// g.DrawString(arrStrGrid[i, j], realFont, pmBrush, recCell, sf);
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
}
else
{
if (j == 1 || j == 6)
{
if (arrStrGrid[i, j].Length > 10)
{
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
else
{
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
}
else
{
// g.DrawString(arrStrGrid[i, j], realFont, pmBrush, recCell, sf);
g.DrawString(arrStrGrid[i, j], new Font("宋体", 10.0F, FontStyle.Bold), pmBrush, recCell, sf);
}
}
X1 += width;
}//End For 列
}//End For 行
#endregion
//重置,不再变换
this.ResetTransGrid();
// font.Dispose();
}
catch (Exception e)
{
//MessageBox.Show(e.Message);
}
finally
{
}
}//End Function
#endregion
#region 合并方式下的网格文本 protected void DrawGridText(Graphics g,Rectangle p_rec,Brush pmBrush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
/// <summary>
/// 绘制网格文本,标准的行与列单元格,无合并
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmBrush">绘图文本的画刷,可以定义颜色</param>
/// <param name="arrStrGrid">二维字符数组(网格)</param>
/// <param name="p_rowHeight">固定行高</param>
/// <param name="p_arrColsWidth">列宽数组,为null时则平均列宽</param>
/// <param name="alignment">由Left,Center,Right对齐方式第一个字母组成的串</param>
/// <param name="p_scaleXY">指定X与Y向缩放比例值</param>
/// <param name="gridMergeFlag"></param>
/// <param name="p_font"></param>
protected void DrawGridMergeText(Graphics g, Rectangle p_rec, Brush pmBrush, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, string alignment, Font p_font, PointF p_scaleXY, GridMergeFlag gridMergeFlag)
{
if (gridMergeFlag == GridMergeFlag.None)
{
DrawGridText(g, p_rec, pmBrush, arrStrGrid, p_rowHeight, p_arrColsWidth, alignment, p_font, p_scaleXY);
return;
}
try
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
Font font = p_font;
if (font == null)
{
font = new Font("宋体", 12.0F);
}
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
//列对齐方式
AlignFlag[] arrAlign;
arrAlign = this.GetColsAlign(alignment);
//变换
this.TransGrid(g, rec, p_scaleXY);
#region 画单元格文本
StringFormat sf = new StringFormat(); //字符格式
sf.LineAlignment = StringAlignment.Center; //垂直居中
sf.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
CellRectangle cell = new CellRectangle(rec.X, rec.Y, 0, p_rowHeight); //单元格
for (int i = 0; i < lngRows; i++)
{
for (int j = 0; j < lngCols; j++)
{
//.....
cell = this.GetMergeCell(new Point(rec.X, rec.Y), arrStrGrid, p_rowHeight, mArrColWidth, i, j);
Rectangle recCell = new Rectangle(cell.Left, cell.Top, cell.Width, cell.Height + 4); //实际上居中会稍微偏上,因为字体有预留边距
sf.Alignment = StringAlignment.Near; //默认左对齐
if (arrAlign.Length > j)
{
if (arrAlign[j] == AlignFlag.Center)
{
sf.Alignment = StringAlignment.Center; //居中
}
else if (arrAlign[j] == AlignFlag.Right)
{
sf.Alignment = StringAlignment.Far; //居右
}
}
g.DrawString(arrStrGrid[i, j], font, pmBrush, recCell, sf);
}//End For 列
}//End For 行
#endregion
//重置,不再变换
this.ResetTransGrid();
//font.Dispose();
}
catch (Exception e)
{
//MessageBox.Show(e.Message);
}
finally
{
}
}//End Function
#endregion
#region protected void DrawGridBorder(Graphics g,Rectangle rec,Pen pmPen,GridBorderFlag p_gridBorderFlag)
/// <summary>
/// 绘制网格边框
/// </summary>
/// <param name="g"></param>
/// <param name="rec"></param>
/// <param name="p_gridBorderFlag"></param>
/// <param name="pmPen"></param>
protected void DrawGridBorder(Graphics g, Rectangle rec, Pen pmPen, GridBorderFlag p_gridBorderFlag)
{
//无边框就退出
if (p_gridBorderFlag == GridBorderFlag.None)
{
return;
}
float penwidth = 1F; //笔宽
int movXY = 0; //根据笔的粗细要相应的调整矩形
switch (p_gridBorderFlag)
{
case GridBorderFlag.Single:
break;
case GridBorderFlag.SingleBold:
penwidth = 2F;
break;
case GridBorderFlag.Double:
//双线内边框
g.DrawRectangle(pmPen, rec);
movXY = 2;
break;
case GridBorderFlag.DoubleBold:
//双线内边框
g.DrawRectangle(pmPen, rec);
penwidth = 2F;
movXY = 3;
break;
}
Pen pen = (Pen)(pmPen.Clone());
pen.Width = penwidth;
//g.DrawRectangle(pen,rec);
Rectangle recBorder = rec;
recBorder.X = rec.X - movXY;
recBorder.Y = rec.Y - movXY;
recBorder.Width = rec.Width + movXY * 2;
recBorder.Height = rec.Height + movXY * 2;
//外边框
g.DrawRectangle(pen, recBorder);
pen.Dispose();
}
#endregion
/// <summary>
/// 变换网格
/// </summary>
/// <param name="g"></param>
/// <param name="p_rec"></param>
/// <param name="p_scaleXY"></param>
private void TransGrid(Graphics g, Rectangle p_rec, PointF p_scaleXY)
{
//坐标平移,使绘制的缩放图相对于原矩阵
//float translateX = 0.0f;
//float translateY = 0.0f;
//缩放变换
if (!p_scaleXY.IsEmpty)
{
g.ScaleTransform(p_scaleXY.X, p_scaleXY.Y);
}
}
private void ResetTransGrid()
{
//this.Graphics.ResetTransform();
}
#endregion
#region 画合并线的核心 protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen pmPen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
/// <summary>
/// 画网格线,根据合并方式判断相邻单元格内容一格一格的画
/// </summary>
/// <param name="g">绘图表面</param>
/// <param name="p_rec">绘图区</param>
/// <param name="pmPen">绘图线的笔,可以定义颜色与线宽</param>
/// <param name="arrStrGrid">二维数组</param>
/// <param name="p_rowHeight">行高</param>
/// <param name="p_arrColsWidth">列宽</param>
/// <param name="p_gridLineFlag">网格线类型</param>
/// <param name="p_gridBorderFlag">边框类型</param>
/// <param name="p_scaleXY">水平与垂直方向缩放量</param>
/// <param name="gridMergeFlag">网格单元格合并方式</param>
protected void DrawGridLine(Graphics g, Rectangle p_rec, Pen pmPen, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, GridLineFlag p_gridLineFlag, GridBorderFlag p_gridBorderFlag, PointF p_scaleXY, GridMergeFlag gridMergeFlag)
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
//网格不合并直接画标准网格线,否则一个单元格一个单元格的画
if (gridMergeFlag == GridMergeFlag.None)
{
this.DrawGridLine(g, rec, pmPen, lngRows, lngCols, p_rowHeight, p_arrColsWidth, p_gridLineFlag, p_gridBorderFlag, p_scaleXY);
return;
}
else
{
#region 有网格线才画
if (p_gridLineFlag != GridLineFlag.None)
{
//变换
this.TransGrid(g, rec, p_scaleXY);
//起止坐标
int X1, X2, Y1, Y2;
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
#region 画单元格线
//边界不画
for (int i = 0; i < lngRows; i++)
{
X1 = rec.X;
Y1 = rec.Y;
for (int j = 0; j < lngCols; j++)
{
//-----水平线-----
X2 = X1 + mArrColWidth[j];
Y1 = rec.Y + p_rowHeight * i; //****可用行高数组
Y2 = Y1;
//画第二行开始及以下的横线,当前行与上一行文本不同
if (i > 0)
{
switch (gridMergeFlag)
{
case GridMergeFlag.None:
//无合并,直接画线
g.DrawLine(pmPen, X1, Y1, X2, Y2);
break;
case GridMergeFlag.Row:
//仅行上相邻列相同就合并,即合并列
//画线(条件:无条件,只要是行上进行列合并,水平线肯定画)
g.DrawLine(pmPen, X1, Y1, X2, Y2);
break;
case GridMergeFlag.Col:
//仅列上相邻行相同就合并,即合并列
//画线(条件:此列不合并 || 文本空 || 当前行与上一行文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i - 1, j])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
break;
case GridMergeFlag.Any:
//任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
//画线(条件: 文本空 || 当前行与上一行文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i - 1, j])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
break;
}
}
//-----'竖线-----
//画第二列以后的竖线,当前列与上一列比较
if (j > 0)
{
Y2 = Y2 + p_rowHeight; //****可用行高数组
X2 = X1;
switch (gridMergeFlag)
{
case GridMergeFlag.None:
//无合并,直接画线
g.DrawLine(pmPen, X1, Y1, X2, Y2);
break;
case GridMergeFlag.Row:
//仅行上相邻列相同就合并,即合并列
//画线(条件:此行不合并 || 文本空 || 当前列与上一列文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i, j - 1])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
break;
case GridMergeFlag.Col:
//仅列上相邻行相同就合并,即合并列
//画线(条件:无,列竖线要画)
g.DrawLine(pmPen, X1, Y1, X2, Y2);
break;
case GridMergeFlag.Any:
//任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
//画线(条件: 文本空 || 当前行与上一行文本不同)
if (arrStrGrid[i, j] == "" || arrStrGrid[i, j] != arrStrGrid[i, j - 1])
{
g.DrawLine(pmPen, X1, Y1, X2, Y2);
}
break;
}
}
//下一列,宽加上
X1 += mArrColWidth[j];
}//End For 列
}//End For 行
#endregion
//******边框******
if (p_gridBorderFlag != GridBorderFlag.None)
{
this.DrawGridBorder(g, rec, pmPen, p_gridBorderFlag);
}
//重置,不再变换
this.ResetTransGrid();
}//End If
#endregion
}//End If
}//End Function
#endregion
/// <summary>
///
/// </summary>
/// <param name="g"></param>
/// <param name="p_rec"></param>
/// <param name="pmBrush"></param>
/// <param name="arrStrGrid"></param>
/// <param name="p_rowHeight"></param>
/// <param name="p_arrColsWidth"></param>
/// <param name="alignment"></param>
/// <param name="p_font"></param>
/// <param name="p_scaleXY"></param>
/// <param name="gridMergeFlag"></param>
protected void DrawGridText(Graphics g, Rectangle p_rec, Brush pmBrush, string[,] arrStrGrid, int p_rowHeight, int[] p_arrColsWidth, string alignment, Font p_font, PointF p_scaleXY, GridMergeFlag gridMergeFlag)
{
if (gridMergeFlag == GridMergeFlag.None)
{
DrawGridText(g, p_rec, pmBrush, arrStrGrid, p_rowHeight, p_arrColsWidth, alignment, p_font, p_scaleXY);
return;
}
try
{
//缩放矩阵,用于绘图
Rectangle rec = new Rectangle(p_rec.X, p_rec.Y, p_rec.Width, p_rec.Height);
Font font = p_font;
if (font == null)
{
font = new Font("宋体", 12.0F);
}
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
//列宽
int[] mArrColWidth = new int[lngCols];
mArrColWidth = p_arrColsWidth;
//列对齐方式
AlignFlag[] arrAlign;
arrAlign = this.GetColsAlign(alignment);
//变换
this.TransGrid(g, rec, p_scaleXY);
#region 画单元格文本
StringFormat sf = new StringFormat(); //字符格式
sf.LineAlignment = StringAlignment.Center; //垂直居中
sf.FormatFlags = StringFormatFlags.LineLimit; //| StringFormatFlags.NoWrap; //可换行否
CellRectangle cell = new CellRectangle(rec.X, rec.Y, 0, p_rowHeight); //单元格
for (int i = 0; i < lngRows; i++)
{
for (int j = 0; j < lngCols; j++)
{
//.....
cell = this.GetMergeCell(new Point(rec.X, rec.Y), arrStrGrid, p_rowHeight, mArrColWidth, i, j, gridMergeFlag);
Rectangle recCell = new Rectangle(cell.Left, cell.Top, cell.Width, cell.Height + 4); //实际上居中会稍微偏上,因为字体有预留边距
sf.Alignment = StringAlignment.Near; //默认左对齐
if (arrAlign.Length > j)
{
if (arrAlign[j] == AlignFlag.Center)
{
sf.Alignment = StringAlignment.Center; //居中
}
else if (arrAlign[j] == AlignFlag.Right)
{
sf.Alignment = StringAlignment.Far; //居右
}
}
g.DrawString(arrStrGrid[i, j], font, pmBrush, recCell, sf);
}//End For 列
}//End For 行
#endregion
//重置,不再变换
this.ResetTransGrid();
//font.Dispose();
}
catch (Exception e)
{
// MessageBox.Show(e.Message);
}
finally
{
}
}//End Function
#region protected virtual Cell GetMergeCell(Point GridLocation,string[,] arrStrGrid,int rowHeight,int[] ArrColWidth,int rowSel,int colSel,GridMergeFlag gridMergeFlag)
/// <summary>
/// 任意合并方式下返回指定单元格左顶宽高
/// </summary>
/// <param name="GridLocation">网格起点坐标</param>
/// <param name="arrStrGrid">二维网格</param>
/// <param name="rowHeight">行高</param>
/// <param name="ArrColWidth">列宽数组</param>
/// <param name="rowSel">指定单元格行</param>
/// <param name="colSel">指定单元格列</param>
/// <param name="gridMergeFlag"></param>
/// <returns></returns>
protected virtual CellRectangle GetMergeCell(Point GridLocation, string[,] arrStrGrid, int rowHeight, int[] ArrColWidth, int rowSel, int colSel, GridMergeFlag gridMergeFlag)
{
CellRectangle cell = new CellRectangle(0, 0, 0, 0);
int lngRows = arrStrGrid.GetLength(0); //行数
int lngCols = arrStrGrid.GetLength(1); //列数
int lngMergeRows = 1; //合并的行数(本身为1)
int lngMergeCols = 1; //合并的列数
int lngStartRow = rowSel; //记录与此单元格合并的起始行
int lngEndRow = rowSel; //以便计算高及起点Y坐标
int lngStartCol = colSel; //记录与此单元格合并的起始列
int lngEndCol = colSel; //以便计算宽及起点X坐标
if (gridMergeFlag == GridMergeFlag.Any || gridMergeFlag == GridMergeFlag.Col || gridMergeFlag == GridMergeFlag.ColDependOnBeforeGroup)
{
//计算在"列"上进行行合并时起始行与合并的多少
//往上查合并(列不变)
for (int rowIndex = rowSel - 1; rowIndex >= 0; rowIndex--)
{
if (arrStrGrid[rowSel, colSel] == arrStrGrid[rowIndex, colSel])
{
lngMergeRows++;
lngStartRow--;
}
else
{
break;
}
}
//往下查合并(列不变)
for (int rowIndex = rowSel + 1; rowIndex < lngRows; rowIndex++)
{
if (arrStrGrid[rowSel, colSel] == arrStrGrid[rowIndex, colSel])
{
lngMergeRows++;
lngEndRow++;
}
else
{
break;
}
}
}
if (gridMergeFlag == GridMergeFlag.Any || gridMergeFlag == GridMergeFlag.Row)
{
//计算在"行"上进行列合并时起始列与合并的多少
//往左查合并(行不变)
for (int colIndex = colSel - 1; colIndex >= 0; colIndex--)
{
if (arrStrGrid[rowSel, colSel] == arrStrGrid[rowSel, colIndex])
{
lngMergeCols++;
lngStartCol--;
}
else
{
break;
}
}
//往右查合并(行不变)
for (int colIndex = colSel + 1; colIndex < lngCols; colIndex++)
{
if (arrStrGrid[rowSel, colSel] == arrStrGrid[rowSel, colIndex])
{
lngMergeCols++;
lngEndCol++;
}
else
{
break;
}
}
}
//******************计算左顶宽高******************
int cellLeft = GridLocation.X;
int cellTop = GridLocation.Y + lngStartRow * rowHeight; //若行高不是固定行高,可以计算之前行的行高总和
int cellWidth = 0;
int cellHeight = 0;
//单元格合并列的前边的单元格列宽和
for (int i = lngStartCol - 1; i >= 0; i--)
{
cellLeft += ArrColWidth[i];
}
//单元格合并列列宽和
for (int i = lngStartCol; i <= lngEndCol; i++)
{
cellWidth += ArrColWidth[i];
}
cellHeight = lngMergeRows * rowHeight; //若行高不是固定行高,可以计算所有行的行高总和
cell = new CellRectangle(cellLeft, cellTop, cellWidth, cellHeight);
return cell;
}
#endregion
}
}