DrawGrid.cs
上传用户:jx_fiona
上传日期:2014-03-08
资源大小:1387k
文件大小:30k
源码类别:

打印编程

开发平台:

Others

  1. using System;
  2. using System.Drawing;
  3. namespace GoldPrinter
  4. {
  5. /// <summary>
  6. /// 绘制网格,核心是二维数组,可以是DataGrid、MsHFlexGrid、DataTable、HtmlTable等二维表现形式的数据源。
  7. /// 
  8. /// 作 者:长江支流(周方勇)
  9. /// Email:flygoldfish@163.com  QQ:150439795
  10. /// 网 址:www.webmis.com.cn
  11. /// ★★★★★您可以免费使用此程序,但是请您完整保留此说明,以维护知识产权★★★★★
  12. /// 
  13. /// </summary>
  14. public class DrawGrid:GoldGrid,IDraw,IDisposable
  15. {
  16. //************字    段************
  17. private Graphics _graphics; //绘图表面
  18. private Rectangle _rectangle; //绘制区
  19. //绘笔
  20. private Brush _brush;
  21. private Pen _pen;
  22. #region IDraw 成员
  23. /// <summary>
  24. /// 获取或设置绘图表面
  25. /// </summary>
  26. public Graphics Graphics
  27. {
  28. get
  29. {
  30. return this._graphics;
  31. }
  32. set
  33. {
  34. this._graphics = value;
  35. }
  36. }
  37. /// <summary>
  38. /// 获取或设置绘制区域
  39. /// </summary>
  40. public System.Drawing.Rectangle Rectangle
  41. {
  42. get
  43. {
  44. return _rectangle;
  45. }
  46. set
  47. {
  48. _rectangle = value;
  49. }
  50. }
  51. /// <summary>
  52. /// 画笔
  53. /// </summary>
  54. public Pen Pen
  55. {
  56. get
  57. {
  58. return _pen;
  59. }
  60. set
  61. {
  62. if (value != null)
  63. {
  64. _pen = value;
  65. }
  66. }
  67. }
  68. /// <summary>
  69. /// 画刷
  70. /// </summary>
  71. public Brush Brush
  72. {
  73. get
  74. {
  75. return _brush;
  76. }
  77. set
  78. {
  79. if (value != null)
  80. {
  81. _brush = value;
  82. }
  83. }
  84. }
  85. #endregion
  86. public DrawGrid()
  87. {
  88. _pen = new Pen(Color.Black);
  89. _brush = Brushes.Black;
  90. }
  91. public DrawGrid(int rows,int cols)
  92. {
  93.             this.Initialize(rows,cols);
  94. }
  95.         public override void Dispose()
  96.         {
  97.             base.Dispose ();
  98.             this._graphics.Dispose();
  99.         }
  100. /// <summary>
  101. /// 绘制网格线,不包括边界线
  102. /// </summary>
  103. public void DrawGridLine()
  104. {
  105. DrawGridLine(this._graphics,this._rectangle,this.Pen,this.GridText,this.PreferredRowHeight,this.ColsWidth,this.Line,this.Border,new PointF(1.0F,1.0F),this.Merge);
  106. }
  107. /// <summary>
  108. /// 绘制网格文本
  109. /// </summary>
  110. public void DrawGridText()
  111. {
  112. DrawGridText(this._graphics,this._rectangle,this.Brush,this.GridText,this.PreferredRowHeight,this.ColsWidth,this.ColsAlignString,this.Font,new PointF(1.0F,1.0F),this.Merge);
  113. }
  114. /// <summary>
  115. /// 绘制边框
  116. /// </summary>
  117. public void DrawGridBorder()
  118. {
  119. DrawGridBorder(this._graphics,this._rectangle,this.Pen,this.Border);
  120. }
  121. /// <summary>
  122. /// 绘制网格络及文本和边框
  123. /// </summary>
  124. public void Draw()
  125. {
  126. DrawGridLine();
  127. /*
  128. //测试绘制用的时间
  129. System.DateTime dt1;
  130. dt1 = System.DateTime.Now;
  131. Console.WriteLine(dt1.ToString() + dt1.Millisecond.ToString());
  132. */
  133. //______________________
  134. DrawGridText();
  135. //______________________
  136. /*
  137. System.DateTime dt2;
  138. dt2 = System.DateTime.Now;
  139. Console.WriteLine(dt2.ToString() + dt2.Millisecond.ToString());
  140. TimeSpan aa = dt2 - dt1;
  141. double secondDef = aa.TotalSeconds;
  142. Console.WriteLine(secondDef.ToString());
  143. */
  144. DrawGridBorder();
  145. }
  146. #region 绘制核心
  147. #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)
  148.         /// <summary>
  149.         /// 画网格线,标准备的横竖线交叉的线
  150.         /// </summary>
  151.         /// <param name="g">绘图表面</param>
  152.         /// <param name="p_rec">绘图区</param>
  153. /// <param name="p_pen">绘图线的笔,可以定义颜色与线宽</param>
  154. /// <param name="p_rows">行数</param>
  155.         /// <param name="p_cols">列数</param>
  156.         /// <param name="p_rowHeight">行高</param>
  157.         /// <param name="p_arrColsWidth">列宽</param>
  158.         /// <param name="p_gridLineFlag">网格线类型</param>
  159.         /// <param name="p_gridBorderFlag">边框类型</param>
  160.         /// <param name="p_scaleXY">水平与垂直方向缩放量</param>
  161. /// <remarks>
  162. /// 作    者:周方勇
  163. /// 修改日期:2004-08-07
  164. /// </remarks>
  165. protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen p_pen,int p_rows,int p_cols,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY)
  166. {
  167. //缩放矩阵,用于绘图
  168. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  169. //缩放程序
  170. this.TransGrid(g,rec,p_scaleXY);
  171. #region 有网格线才画
  172. if (p_gridLineFlag != GridLineFlag.None)
  173. {
  174. int lngRows = p_rows; //arrStrGrid.GetLength(0); //行数,也可由二维数组算出
  175. int lngCols = p_cols; //arrStrGrid.GetLength(1); //列数
  176. int lngRowIndex; //当前行
  177. int lngColIndex; //当前列
  178. //起止坐标
  179. int X1, X2,Y1, Y2;
  180. int lngLineLen; //线长
  181. int lngLineHei; //线高
  182. //计算坐标、线长、线高
  183. lngLineLen = rec.Width;
  184. lngLineHei = rec.Height;
  185. #region 包括横线就画
  186. if (p_gridLineFlag == GridLineFlag.Horizontal || p_gridLineFlag == GridLineFlag.Both)
  187. {
  188. //******先画横线******
  189. X1 = rec.X;
  190. Y1 = rec.Y;
  191. X2 = X1 + lngLineLen;
  192.         
  193. //最上边与最下边的线不画
  194. for(lngRowIndex = 1 ; lngRowIndex < lngRows ; lngRowIndex++)
  195. {
  196. Y1 += p_rowHeight; //这里可以换成行高数组
  197. //Y1 += p_arrRowsWidth[lngRowIndex - 1];//这里可以换成行高数组
  198. Y2 = Y1;
  199. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  200. }
  201. }
  202. #endregion 
  203. #region 包括竖线就画
  204. if (p_gridLineFlag == GridLineFlag.Vertical || p_gridLineFlag == GridLineFlag.Both)
  205. {
  206. //******再画竖线******
  207. //列宽
  208. int[] mArrColWidth = new int[lngCols];
  209. mArrColWidth = p_arrColsWidth;
  210. //Y不变
  211. X1 = rec.X;
  212. Y1 = rec.Y;
  213. Y2 = Y1 + lngLineHei;
  214. //最左边与右边的线不画
  215. for(lngColIndex = 0 ; lngColIndex < lngCols-1 ; lngColIndex++)
  216. {
  217. X1 += mArrColWidth[lngColIndex];
  218. X2 = X1;
  219. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  220. }
  221. }
  222. #endregion 
  223. }//End If
  224. #endregion
  225. //******边框******
  226. if (p_gridBorderFlag != GridBorderFlag.None)
  227. {
  228. this.DrawGridBorder(g,rec,p_pen,p_gridBorderFlag);
  229. }
  230. //重置,不再变换
  231. this.ResetTransGrid();
  232. }
  233. #endregion
  234. #region protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY)
  235. /// <summary>
  236. /// 画网格线,标准备的横竖线交叉的线
  237. /// </summary>
  238. /// <param name="g">绘图表面</param>
  239. /// <param name="p_rec">绘图区</param>
  240. /// <param name="p_pen">绘图线的笔,可以定义颜色与线宽</param>
  241. /// <param name="arrStrGrid">二维数组,对应了网格行、列数</param>
  242. /// <param name="p_rowHeight">行高</param>
  243. /// <param name="p_arrColsWidth">列宽</param>
  244. /// <param name="p_gridLineFlag">网格线类型</param>
  245. /// <param name="p_gridBorderFlag">边框类型</param>
  246. /// <param name="p_scaleXY">水平与垂直方向缩放量</param>
  247. /// <remarks>
  248. /// 作    者:周方勇
  249. /// 修改日期:2004-08-07
  250. /// </remarks>
  251. protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY)
  252. {
  253. int lngRows = arrStrGrid.GetLength(0); //行数
  254. int lngCols = arrStrGrid.GetLength(1); //列数
  255. DrawGridLine(g,p_rec,p_pen,lngRows,lngCols,p_rowHeight,p_arrColsWidth,p_gridLineFlag,p_gridBorderFlag,p_scaleXY);
  256. }
  257. #endregion
  258. #region 画合并线的核心 protected void DrawGridMergeLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  259. /// <summary>
  260. /// 画网格线,根据合并方式判断相邻单元格内容一格一格的画
  261. /// </summary>
  262. /// <param name="g">绘图表面</param>
  263. /// <param name="p_rec">绘图区</param>
  264. /// <param name="p_pen">绘图线的笔,可以定义颜色与线宽</param>
  265. /// <param name="arrStrGrid">二维数组</param>
  266. /// <param name="p_rowHeight">行高</param>
  267. /// <param name="p_arrColsWidth">列宽</param>
  268. /// <param name="p_gridLineFlag">网格线类型</param>
  269. /// <param name="p_gridBorderFlag">边框类型</param>
  270. /// <param name="p_scaleXY">水平与垂直方向缩放量</param>
  271. /// <param name="gridMergeFlag">网格单元格合并方式</param>
  272. /// <remarks>
  273. /// 作    者:周方勇
  274. /// 修改日期:2004-08-07
  275. /// </remarks>
  276. protected void DrawGridMergeLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  277. {
  278. //缩放矩阵,用于绘图
  279. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  280. int lngRows = arrStrGrid.GetLength(0); //行数
  281. int lngCols = arrStrGrid.GetLength(1); //列数
  282. //网格不合并直接画标准网格线,否则一个单元格一个单元格的画
  283. if (gridMergeFlag == GridMergeFlag.None)
  284. {
  285. this.DrawGridLine(g,rec,p_pen,lngRows,lngCols,p_rowHeight,p_arrColsWidth,p_gridLineFlag,p_gridBorderFlag,p_scaleXY);
  286. return;
  287. }
  288. else
  289. {
  290. #region 有网格线才画
  291. if (p_gridLineFlag != GridLineFlag.None)
  292. {
  293. //变换
  294. this.TransGrid(g,rec,p_scaleXY);
  295. //起止坐标
  296. int X1, X2,Y1, Y2;
  297. //列宽
  298. int[] mArrColWidth = new int[lngCols];
  299. mArrColWidth = p_arrColsWidth;
  300. #region 画单元格线
  301. //边界不画
  302. for(int i = 0 ; i < lngRows ; i++)
  303. {
  304. X1 = rec.X;
  305. Y1 = rec.Y;
  306. for(int j = 0 ; j < lngCols ; j++)
  307. {
  308. //-----水平线-----
  309. X2 = X1 + mArrColWidth[j];
  310. Y1 = rec.Y + p_rowHeight * i; //****可用行高数组
  311. Y2 = Y1;
  312. //画第二行开始及以下的横线,当前行与上一行文本不同
  313. if (i > 0)
  314. {
  315. //任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
  316. if (gridMergeFlag == GridMergeFlag.Any)
  317. {
  318. //画线(条件:此列不合并 || 文本空 || 当前行与上一行文本不同)
  319. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i-1,j])
  320. {
  321. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  322. }
  323. }
  324. }
  325. //-----'竖线-----
  326. //画第二列以后的竖线,当前列与上一列比较
  327. if (j > 0)
  328. {
  329. Y2 = Y2 + p_rowHeight; //****可用行高数组
  330. X2 = X1;
  331. //任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
  332. if (gridMergeFlag == GridMergeFlag.Any)
  333. {
  334. //画线(条件:此行不合并 || 文本空 || 当前列与上一列文本不同)
  335. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i,j-1])
  336. {
  337. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  338. }
  339. }
  340. }
  341. //下一列,宽加上
  342. X1 += mArrColWidth[j];
  343. }//End For 列
  344. }//End For 行
  345. #endregion
  346. //******边框******
  347. if (p_gridBorderFlag != GridBorderFlag.None)
  348. {
  349. this.DrawGridBorder(g,rec,p_pen,p_gridBorderFlag);
  350. }
  351. //重置,不再变换
  352. this.ResetTransGrid();
  353. }//End If
  354. #endregion
  355. }//End If
  356. }//End Function
  357. #endregion
  358. #region 标准不合并网格的文本 protected void DrawGridText(Graphics g,Rectangle p_rec,Brush p_brush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY)
  359. /// <summary>
  360. /// 绘制网格文本,标准的行与列单元格,无合并
  361. /// </summary>
  362. /// <param name="g">绘图表面</param>
  363. /// <param name="p_rec">绘图区</param>
  364. /// <param name="p_brush">绘图文本的画刷,可以定义颜色</param>
  365. /// <param name="arrStrGrid">二维字符数组(网格)</param>
  366. /// <param name="p_rowHeight">固定行高</param>
  367. /// <param name="p_arrColsWidth">列宽数组,为null时则平均列宽</param>
  368. /// <param name="alignment">由Left,Center,Right对齐方式第一个字母组成的串</param>
  369. /// <param name="p_scaleXY">指定X与Y向缩放比例值</param>
  370. /// <remarks>
  371. /// 作    者:周方勇
  372. /// 修改日期:2004-08-07
  373. /// </remarks>
  374. protected void DrawGridText(Graphics g,Rectangle p_rec,Brush p_brush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY)
  375. {
  376. try
  377. {
  378. //缩放矩阵,用于绘图
  379. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  380. Font font = p_font;
  381. if (font == null)
  382. {
  383. font = new Font("宋体",12.0F);
  384. }
  385. int lngRows = arrStrGrid.GetLength(0); //行数
  386. int lngCols = arrStrGrid.GetLength(1); //列数
  387. //列宽
  388. int[] mArrColWidth = new int[lngCols];
  389. mArrColWidth = p_arrColsWidth;
  390. //列对齐方式
  391. AlignFlag[] arrAlign;
  392. arrAlign = this.GetColsAlign(alignment);
  393. //变换
  394. this.TransGrid(g,rec,p_scaleXY);
  395. //起止坐标
  396. int X1,Y1,width;
  397. #region 画单元格文本
  398. StringFormat sf = new StringFormat(); //字符格式
  399. sf.LineAlignment = StringAlignment.Center; //垂直居中
  400. sf.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
  401.  
  402. for(int i = 0 ; i < lngRows ; i++)
  403. {
  404. X1 = rec.X;
  405. Y1 = rec.Y + p_rowHeight*i; //****可用行数组
  406. for(int j = 0 ; j < lngCols ; j++)
  407. {
  408. width = mArrColWidth[j];
  409. Rectangle recCell = new Rectangle(X1,Y1,width,p_rowHeight + 4);  //实际上居中会稍微偏上,因为字体有预留边距
  410. sf.Alignment = StringAlignment.Near; //默认左对齐
  411. if(arrAlign.Length > j)
  412. {
  413. if (arrAlign[j] == AlignFlag.Center)
  414. {
  415. sf.Alignment = StringAlignment.Center; //居中
  416. }
  417. else if (arrAlign[j] == AlignFlag.Right)
  418. {
  419. sf.Alignment = StringAlignment.Far ; //居右
  420. }
  421. }
  422. g.DrawString(arrStrGrid[i,j],font,p_brush,recCell,sf);
  423. X1 += width;
  424. }//End For 列
  425. }//End For 行
  426. #endregion
  427. //重置,不再变换
  428. this.ResetTransGrid();
  429. // font.Dispose();
  430. }
  431. catch(Exception e)
  432. {
  433. System.Windows.Forms.MessageBox.Show(e.Message);
  434. }
  435. finally
  436. {
  437. }
  438. }//End Function
  439. #endregion
  440. #region 合并方式下的网格文本 protected void DrawGridText(Graphics g,Rectangle p_rec,Brush p_brush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  441. /// <summary>
  442. /// 绘制网格文本,标准的行与列单元格,无合并
  443. /// </summary>
  444. /// <param name="g">绘图表面</param>
  445. /// <param name="p_rec">绘图区</param>
  446. /// <param name="p_brush">绘图文本的画刷,可以定义颜色</param>
  447. /// <param name="arrStrGrid">二维字符数组(网格)</param>
  448. /// <param name="p_rowHeight">固定行高</param>
  449. /// <param name="p_arrColsWidth">列宽数组,为null时则平均列宽</param>
  450. /// <param name="alignment">由Left,Center,Right对齐方式第一个字母组成的串</param>
  451. /// <param name="p_scaleXY">指定X与Y向缩放比例值</param>
  452. /// <remarks>
  453. /// 作    者:周方勇
  454. /// 修改日期:2004-08-07
  455. /// </remarks>
  456. protected void DrawGridMergeText(Graphics g,Rectangle p_rec,Brush p_brush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  457. {
  458. if (gridMergeFlag == GridMergeFlag.None)
  459. {
  460. DrawGridText(g,p_rec,p_brush,arrStrGrid,p_rowHeight,p_arrColsWidth,alignment,p_font,p_scaleXY);
  461. return;
  462. }
  463. try
  464. {
  465. //缩放矩阵,用于绘图
  466. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  467. Font font = p_font;
  468. if (font == null)
  469. {
  470. font = new Font("宋体",12.0F);
  471. }
  472. int lngRows = arrStrGrid.GetLength(0); //行数
  473. int lngCols = arrStrGrid.GetLength(1); //列数
  474. //列宽
  475. int[] mArrColWidth = new int[lngCols];
  476. mArrColWidth = p_arrColsWidth;
  477. //列对齐方式
  478. AlignFlag[] arrAlign;
  479. arrAlign = this.GetColsAlign(alignment);
  480. //变换
  481. this.TransGrid(g,rec,p_scaleXY);
  482. #region 画单元格文本
  483. StringFormat sf = new StringFormat(); //字符格式
  484. sf.LineAlignment = StringAlignment.Center; //垂直居中
  485. sf.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
  486. CellRectangle cell = new CellRectangle(rec.X,rec.Y,0,p_rowHeight); //单元格
  487. for(int i = 0 ; i < lngRows ; i++)
  488. {
  489. for(int j = 0 ; j < lngCols ; j++)
  490. {
  491. //.....
  492. cell = this.GetMergeCell(new Point(rec.X,rec.Y),arrStrGrid,p_rowHeight,mArrColWidth,i,j);
  493. Rectangle recCell = new Rectangle(cell.Left,cell.Top,cell.Width,cell.Height + 4);  //实际上居中会稍微偏上,因为字体有预留边距
  494. sf.Alignment = StringAlignment.Near; //默认左对齐
  495. if(arrAlign.Length > j)
  496. {
  497. if (arrAlign[j] == AlignFlag.Center)
  498. {
  499. sf.Alignment = StringAlignment.Center; //居中
  500. }
  501. else if (arrAlign[j] == AlignFlag.Right)
  502. {
  503. sf.Alignment = StringAlignment.Far ; //居右
  504. }
  505. }
  506. g.DrawString(arrStrGrid[i,j],font,p_brush,recCell,sf);
  507. }//End For 列
  508. }//End For 行
  509. #endregion
  510. //重置,不再变换
  511. this.ResetTransGrid();
  512. //font.Dispose();
  513. }
  514. catch(Exception e)
  515. {
  516. System.Windows.Forms.MessageBox.Show(e.Message);
  517. }
  518. finally
  519. {
  520. }
  521. }//End Function
  522. #endregion
  523. #region protected void DrawGridBorder(Graphics g,Rectangle rec,Pen p_pen,GridBorderFlag p_gridBorderFlag)
  524. /// <summary>
  525. /// 绘制网格边框
  526. /// </summary>
  527. /// <param name="g"></param>
  528. /// <param name="rec"></param>
  529. /// <param name="p_gridBorderFlag"></param>
  530. protected void DrawGridBorder(Graphics g,Rectangle rec,Pen p_pen,GridBorderFlag p_gridBorderFlag)
  531. {
  532. //无边框就退出
  533. if (p_gridBorderFlag == GridBorderFlag.None)
  534. {
  535. return;
  536. }
  537. float penwidth = 1F; //笔宽
  538. int movXY = 0; //根据笔的粗细要相应的调整矩形
  539. switch (p_gridBorderFlag)
  540. {
  541. case GridBorderFlag.Single:
  542. break;
  543. case GridBorderFlag.SingleBold:
  544. penwidth = 2F;
  545. break;
  546. case GridBorderFlag.Double:
  547. //双线内边框
  548. g.DrawRectangle(p_pen,rec);
  549. movXY = 2;
  550. break;
  551. case GridBorderFlag.DoubleBold:
  552. //双线内边框
  553. g.DrawRectangle(p_pen,rec);
  554. penwidth = 2F;
  555. movXY = 3;
  556. break;
  557. }
  558. Pen pen = (Pen)(p_pen.Clone());
  559. pen.Width = penwidth;
  560. //g.DrawRectangle(pen,rec);
  561. Rectangle recBorder = rec;
  562. recBorder.X = rec.X - movXY;
  563. recBorder.Y = rec.Y - movXY;
  564. recBorder.Width = rec.Width + movXY * 2;
  565. recBorder.Height = rec.Height + movXY * 2;
  566. //外边框
  567. g.DrawRectangle(pen,recBorder);
  568. pen.Dispose();
  569. }
  570. #endregion
  571. /// <summary>
  572. /// 变换网格
  573. /// </summary>
  574. /// <param name="g"></param>
  575. /// <param name="p_rec"></param>
  576. /// <param name="p_scaleXY"></param>
  577. private void TransGrid(Graphics g,Rectangle p_rec,PointF p_scaleXY)
  578. {
  579. //坐标平移,使绘制的缩放图相对于原矩阵
  580. float translateX = 0.0f;
  581. float translateY = 0.0f;
  582. //缩放变换
  583. if (!p_scaleXY.IsEmpty)
  584. {
  585. g.ScaleTransform(p_scaleXY.X,p_scaleXY.Y);
  586. }
  587. }
  588. private void ResetTransGrid()
  589. {
  590. //this.Graphics.ResetTransform();
  591. }
  592. #endregion
  593. #region 画合并线的核心 protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  594. /// <summary>
  595. /// 画网格线,根据合并方式判断相邻单元格内容一格一格的画
  596. /// </summary>
  597. /// <param name="g">绘图表面</param>
  598. /// <param name="p_rec">绘图区</param>
  599. /// <param name="p_pen">绘图线的笔,可以定义颜色与线宽</param>
  600. /// <param name="arrStrGrid">二维数组</param>
  601. /// <param name="p_rowHeight">行高</param>
  602. /// <param name="p_arrColsWidth">列宽</param>
  603. /// <param name="p_gridLineFlag">网格线类型</param>
  604. /// <param name="p_gridBorderFlag">边框类型</param>
  605. /// <param name="p_scaleXY">水平与垂直方向缩放量</param>
  606. /// <param name="gridMergeFlag">网格单元格合并方式</param>
  607. /// <remarks>
  608. /// 作    者:周方勇
  609. /// 修改日期:2004-08-07
  610. /// </remarks>
  611. protected void DrawGridLine(Graphics g,Rectangle p_rec,Pen p_pen,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,GridLineFlag p_gridLineFlag,GridBorderFlag p_gridBorderFlag,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  612. {
  613. //缩放矩阵,用于绘图
  614. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  615. int lngRows = arrStrGrid.GetLength(0); //行数
  616. int lngCols = arrStrGrid.GetLength(1); //列数
  617. //网格不合并直接画标准网格线,否则一个单元格一个单元格的画
  618. if (gridMergeFlag == GridMergeFlag.None)
  619. {
  620. this.DrawGridLine(g,rec,p_pen,lngRows,lngCols,p_rowHeight,p_arrColsWidth,p_gridLineFlag,p_gridBorderFlag,p_scaleXY);
  621. return;
  622. }
  623. else
  624. {
  625. #region 有网格线才画
  626. if (p_gridLineFlag != GridLineFlag.None)
  627. {
  628. //变换
  629. this.TransGrid(g,rec,p_scaleXY);
  630. //起止坐标
  631. int X1, X2,Y1, Y2;
  632. //列宽
  633. int[] mArrColWidth = new int[lngCols];
  634. mArrColWidth = p_arrColsWidth;
  635. #region 画单元格线
  636. //边界不画
  637. for(int i = 0 ; i < lngRows ; i++)
  638. {
  639. X1 = rec.X;
  640. Y1 = rec.Y;
  641. for(int j = 0 ; j < lngCols ; j++)
  642. {
  643. //-----水平线-----
  644. X2 = X1 + mArrColWidth[j];
  645. Y1 = rec.Y + p_rowHeight * i; //****可用行高数组
  646. Y2 = Y1;
  647. //画第二行开始及以下的横线,当前行与上一行文本不同
  648. if (i > 0)
  649. {
  650. switch(gridMergeFlag)
  651. {
  652. case GridMergeFlag.None:
  653. //无合并,直接画线
  654. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  655. break;
  656. case GridMergeFlag.Row:
  657. //仅行上相邻列相同就合并,即合并列
  658. //画线(条件:无条件,只要是行上进行列合并,水平线肯定画)
  659. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  660. break;
  661. case GridMergeFlag.Col:
  662. //仅列上相邻行相同就合并,即合并列
  663. //画线(条件:此列不合并 || 文本空 || 当前行与上一行文本不同)
  664. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i-1,j])
  665. {
  666. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  667. }
  668. break;
  669. case GridMergeFlag.Any:
  670. //任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
  671. //画线(条件: 文本空 || 当前行与上一行文本不同)
  672. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i-1,j])
  673. {
  674. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  675. }
  676. break;
  677. }
  678. }
  679. //-----'竖线-----
  680. //画第二列以后的竖线,当前列与上一列比较
  681. if (j > 0)
  682. {
  683. Y2 = Y2 + p_rowHeight; //****可用行高数组
  684. X2 = X1;
  685. switch(gridMergeFlag)
  686. {
  687. case GridMergeFlag.None:
  688. //无合并,直接画线
  689. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  690. break;
  691. case GridMergeFlag.Row:
  692. //仅行上相邻列相同就合并,即合并列
  693. //画线(条件:此行不合并 || 文本空 || 当前列与上一列文本不同)
  694. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i,j-1])
  695. {
  696. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  697. }
  698. break;
  699. case GridMergeFlag.Col:
  700. //仅列上相邻行相同就合并,即合并列
  701. //画线(条件:无,列竖线要画)
  702. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  703. break;
  704. case GridMergeFlag.Any:
  705. //任意合并,只要相邻单元格内容不同就画线,即只要相邻单元格内容相同就合并
  706. //画线(条件: 文本空 || 当前行与上一行文本不同)
  707. if(arrStrGrid[i,j] == "" || arrStrGrid[i,j] != arrStrGrid[i,j-1])
  708. {
  709. g.DrawLine(p_pen,X1,Y1,X2,Y2);
  710. }
  711. break;
  712. }
  713. }
  714. //下一列,宽加上
  715. X1 += mArrColWidth[j];
  716. }//End For 列
  717. }//End For 行
  718. #endregion
  719. //******边框******
  720. if (p_gridBorderFlag != GridBorderFlag.None)
  721. {
  722. this.DrawGridBorder(g,rec,p_pen,p_gridBorderFlag);
  723. }
  724. //重置,不再变换
  725. this.ResetTransGrid();
  726. }//End If
  727. #endregion
  728. }//End If
  729. }//End Function
  730. #endregion
  731. protected void DrawGridText(Graphics g,Rectangle p_rec,Brush p_brush,string[,] arrStrGrid,int p_rowHeight,int[] p_arrColsWidth,string alignment,Font p_font,PointF p_scaleXY,GridMergeFlag gridMergeFlag)
  732. {
  733. if (gridMergeFlag == GridMergeFlag.None)
  734. {
  735. DrawGridText(g,p_rec,p_brush,arrStrGrid,p_rowHeight,p_arrColsWidth,alignment,p_font,p_scaleXY);
  736. return;
  737. }
  738. try
  739. {
  740. //缩放矩阵,用于绘图
  741. Rectangle rec = new Rectangle(p_rec.X,p_rec.Y,p_rec.Width,p_rec.Height);
  742. Font font = p_font;
  743. if (font == null)
  744. {
  745. font = new Font("宋体",12.0F);
  746. }
  747. int lngRows = arrStrGrid.GetLength(0); //行数
  748. int lngCols = arrStrGrid.GetLength(1); //列数
  749. //列宽
  750. int[] mArrColWidth = new int[lngCols];
  751. mArrColWidth = p_arrColsWidth;
  752. //列对齐方式
  753. AlignFlag[] arrAlign;
  754. arrAlign = this.GetColsAlign(alignment);
  755. //变换
  756. this.TransGrid(g,rec,p_scaleXY);
  757. #region 画单元格文本
  758. StringFormat sf = new StringFormat(); //字符格式
  759. sf.LineAlignment = StringAlignment.Center; //垂直居中
  760. sf.FormatFlags = StringFormatFlags.LineLimit; //| StringFormatFlags.NoWrap; //可换行否
  761. CellRectangle cell = new CellRectangle(rec.X,rec.Y,0,p_rowHeight); //单元格
  762. for(int i = 0 ; i < lngRows ; i++)
  763. {
  764. for(int j = 0 ; j < lngCols ; j++)
  765. {
  766. //.....
  767. cell = this.GetMergeCell(new Point(rec.X,rec.Y),arrStrGrid,p_rowHeight,mArrColWidth,i,j,gridMergeFlag);
  768. Rectangle recCell = new Rectangle(cell.Left,cell.Top,cell.Width,cell.Height + 4);  //实际上居中会稍微偏上,因为字体有预留边距
  769. sf.Alignment = StringAlignment.Near; //默认左对齐
  770. if(arrAlign.Length > j)
  771. {
  772. if (arrAlign[j] == AlignFlag.Center)
  773. {
  774. sf.Alignment = StringAlignment.Center; //居中
  775. }
  776. else if (arrAlign[j] == AlignFlag.Right)
  777. {
  778. sf.Alignment = StringAlignment.Far ; //居右
  779. }
  780. }
  781. g.DrawString(arrStrGrid[i,j],font,p_brush,recCell,sf);
  782. }//End For 列
  783. }//End For 行
  784. #endregion
  785. //重置,不再变换
  786. this.ResetTransGrid();
  787. //font.Dispose();
  788. }
  789. catch(Exception e)
  790. {
  791. System.Windows.Forms.MessageBox.Show(e.Message);
  792. }
  793. finally
  794. {
  795. }
  796. }//End Function
  797. #region protected virtual Cell GetMergeCell(Point GridLocation,string[,] arrStrGrid,int rowHeight,int[] ArrColWidth,int rowSel,int colSel,GridMergeFlag gridMergeFlag)
  798. /// <summary>
  799. /// 任意合并方式下返回指定单元格左顶宽高
  800. /// </summary>
  801. /// <param name="GridLocation">网格起点坐标</param>
  802. /// <param name="arrStrGrid">二维网格</param>
  803. /// <param name="rowHeight">行高</param>
  804. /// <param name="ArrColWidth">列宽数组</param>
  805. /// <param name="rowSel">指定单元格行</param>
  806. /// <param name="colSel">指定单元格列</param>
  807. /// <returns></returns>
  808. protected virtual CellRectangle GetMergeCell(Point GridLocation,string[,] arrStrGrid,int rowHeight,int[] ArrColWidth,int rowSel,int colSel,GridMergeFlag gridMergeFlag)
  809. {
  810. CellRectangle cell = new CellRectangle(0,0,0,0);
  811. int lngRows = arrStrGrid.GetLength(0); //行数
  812. int lngCols = arrStrGrid.GetLength(1); //列数
  813. int lngMergeRows = 1; //合并的行数(本身为1)
  814. int lngMergeCols = 1; //合并的列数
  815. int lngStartRow = rowSel; //记录与此单元格合并的起始行
  816. int lngEndRow = rowSel; //以便计算高及起点Y坐标
  817. int lngStartCol = colSel; //记录与此单元格合并的起始列
  818. int lngEndCol = colSel; //以便计算宽及起点X坐标
  819. if (gridMergeFlag==GridMergeFlag.Any || gridMergeFlag==GridMergeFlag.Col || gridMergeFlag==GridMergeFlag.ColDependOnBeforeGroup)
  820. {
  821. //计算在"列"上进行行合并时起始行与合并的多少
  822. //往上查合并(列不变)
  823. for(int rowIndex = rowSel-1 ; rowIndex >= 0 ; rowIndex--)
  824. {
  825. if(arrStrGrid[rowSel,colSel] == arrStrGrid[rowIndex,colSel])
  826. {
  827. lngMergeRows++;
  828. lngStartRow--;
  829. }
  830. else
  831. {
  832. break;
  833. }
  834. }
  835. //往下查合并(列不变)
  836. for(int rowIndex = rowSel+1 ; rowIndex < lngRows ; rowIndex++)
  837. {
  838. if(arrStrGrid[rowSel,colSel] == arrStrGrid[rowIndex,colSel])
  839. {
  840. lngMergeRows++;
  841. lngEndRow++;
  842. }
  843. else
  844. {
  845. break;
  846. }
  847. }
  848. }
  849. if (gridMergeFlag==GridMergeFlag.Any || gridMergeFlag==GridMergeFlag.Row)
  850. {
  851. //计算在"行"上进行列合并时起始列与合并的多少
  852. //往左查合并(行不变)
  853. for(int colIndex = colSel-1 ; colIndex >= 0 ; colIndex--)
  854. {
  855. if(arrStrGrid[rowSel,colSel] == arrStrGrid[rowSel,colIndex])
  856. {
  857. lngMergeCols++;
  858. lngStartCol--;
  859. }
  860. else
  861. {
  862. break;
  863. }
  864. }
  865. //往右查合并(行不变)
  866. for(int colIndex = colSel+1 ; colIndex < lngCols ; colIndex++)
  867. {
  868. if(arrStrGrid[rowSel,colSel] == arrStrGrid[rowSel,colIndex])
  869. {
  870. lngMergeCols++;
  871. lngEndCol++;
  872. }
  873. else
  874. {
  875. break;
  876. }
  877. }
  878. }
  879. //******************计算左顶宽高******************
  880. int cellLeft = GridLocation.X;
  881. int cellTop = GridLocation.Y + lngStartRow * rowHeight; //若行高不是固定行高,可以计算之前行的行高总和
  882. int cellWidth = 0;
  883. int cellHeight = 0;
  884. //单元格合并列的前边的单元格列宽和
  885. for(int i = lngStartCol-1 ; i >= 0 ; i--)
  886. {
  887. cellLeft += ArrColWidth[i];
  888. }
  889. //单元格合并列列宽和
  890. for(int i = lngStartCol ; i <= lngEndCol ; i++)
  891. {
  892. cellWidth += ArrColWidth[i];
  893. }
  894. cellHeight = lngMergeRows * rowHeight; //若行高不是固定行高,可以计算所有行的行高总和
  895. cell = new CellRectangle(cellLeft,cellTop,cellWidth,cellHeight);
  896. return cell;
  897. }
  898. #endregion
  899.     }//End Class
  900. }//End NameSpace