LayoutUtility.cs 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. 
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6. using Microsoft.VisualBasic.PowerPacks;
  7. namespace Dongke.WinForm.Controls.InvoiceLayout
  8. {
  9. internal static class LayoutUtility
  10. {
  11. #region 函数
  12. /// <summary>
  13. /// 获取图形实例
  14. /// </summary>
  15. /// <param name="item"></param>
  16. /// <returns></returns>
  17. public static Shape GetNewShape(LayoutItem item)
  18. {
  19. Shape shape = null;
  20. switch (item.ItemType)
  21. {
  22. case ItemType.Ellipse:
  23. OvalShape eShape = new OvalShape();
  24. eShape.SelectionColor = Color.Transparent;
  25. eShape.BorderStyle = DashStyle.Solid;
  26. eShape.BorderColor = Color.Black;
  27. shape = eShape;
  28. break;
  29. case ItemType.Rectangle:
  30. RectangleShape rShape = new RectangleShape();
  31. rShape.SelectionColor = Color.Transparent;
  32. rShape.BorderStyle = DashStyle.Solid;
  33. rShape.BorderColor = Color.Black;
  34. shape = rShape;
  35. break;
  36. case ItemType.Image:
  37. case ItemType.Text:
  38. case ItemType.Grid:
  39. case ItemType.PageNum:
  40. default:
  41. RectangleShape dShape = new RectangleShape();
  42. dShape.SelectionColor = Color.Transparent;
  43. dShape.BorderStyle = DashStyle.Custom;
  44. dShape.BorderColor = Color.Transparent;
  45. shape = dShape;
  46. break;
  47. }
  48. return shape;
  49. }
  50. #region 绘制直线
  51. /// <summary>
  52. /// 绘制直线
  53. /// </summary>
  54. /// <param name="graphics">Graphics</param>
  55. /// <param name="startPoint">起点</param>
  56. /// <param name="endPoint">终点</param>
  57. /// <param name="lineColor">线的颜色</param>
  58. /// <param name="lineWidth">线宽(mm)</param>
  59. public static void DrawLine(
  60. Graphics graphics,
  61. PointF startPoint,
  62. PointF endPoint,
  63. Color lineColor,
  64. float lineWidth)
  65. {
  66. DrawLine(graphics, graphics.PageUnit, startPoint, endPoint, lineColor, lineWidth);
  67. }
  68. /// <summary>
  69. /// 绘制直线
  70. /// </summary>
  71. /// <param name="graphics">Graphics</param>
  72. /// <param name="unit">GraphicsUnit</param>
  73. /// <param name="startPoint">起点</param>
  74. /// <param name="endPoint">终点</param>
  75. /// <param name="lineColor">线的颜色</param>
  76. /// <param name="lineWidth">线宽(mm)</param>
  77. public static void DrawLine(
  78. Graphics graphics,
  79. GraphicsUnit unit,
  80. PointF startPoint,
  81. PointF endPoint,
  82. Color lineColor,
  83. float lineWidth)
  84. {
  85. if (lineWidth == 0 || ((startPoint.X == endPoint.X) && (startPoint.Y == endPoint.Y)))
  86. {
  87. return;
  88. }
  89. GraphicsContainer containerState = graphics.BeginContainer();
  90. graphics.PageUnit = unit;
  91. SmoothingMode smoothingMode = graphics.SmoothingMode;
  92. try
  93. {
  94. using (Pen pen = new Pen(lineColor))
  95. {
  96. graphics.SmoothingMode = SmoothingMode.AntiAlias;
  97. pen.Width = Math.Max(LayoutCommon.PixelToMillimeter(1), lineWidth);
  98. graphics.DrawLine(pen, startPoint, endPoint);
  99. }
  100. }
  101. finally
  102. {
  103. graphics.SmoothingMode = smoothingMode;
  104. graphics.EndContainer(containerState);
  105. }
  106. }
  107. #endregion 绘制直线
  108. #region 绘制椭圆
  109. /// <summary>
  110. /// 绘制椭圆
  111. /// </summary>
  112. /// <param name="graphics">Graphics</param>
  113. /// <param name="rectangle">图形范围</param>
  114. /// <param name="lineColor">边线颜色</param>
  115. /// <param name="fillColor">填充颜色</param>
  116. /// <param name="lineWidth">边线宽(mm)</param>
  117. /// <param name="isTransparent">背景是否透明</param>
  118. public static void DrawEllipse(
  119. Graphics graphics,
  120. RectangleF rectangle,
  121. Color lineColor,
  122. Color fillColor,
  123. float lineWidth,
  124. bool isTransparent)
  125. {
  126. DrawEllipse(graphics, graphics.PageUnit, rectangle,
  127. lineColor, fillColor, lineWidth, isTransparent);
  128. }
  129. /// <summary>
  130. /// 绘制椭圆
  131. /// </summary>
  132. /// <param name="graphics">Graphics</param>
  133. /// <param name="unit">GraphicsUnit</param>
  134. /// <param name="rectangle">图形范围</param>
  135. /// <param name="lineColor">边线颜色</param>
  136. /// <param name="fillColor">填充颜色</param>
  137. /// <param name="lineWidth">边线宽(mm)</param>
  138. /// <param name="isTransparent">背景是否透明</param>
  139. public static void DrawEllipse(
  140. Graphics graphics,
  141. GraphicsUnit unit,
  142. RectangleF rectangle,
  143. Color lineColor,
  144. Color fillColor,
  145. float lineWidth,
  146. bool isTransparent)
  147. {
  148. if ((rectangle.Width < 0) || (rectangle.Height < 0))
  149. {
  150. return;
  151. }
  152. GraphicsContainer containerState = graphics.BeginContainer();
  153. graphics.PageUnit = unit;
  154. SmoothingMode smoothingMode = graphics.SmoothingMode;
  155. try
  156. {
  157. if (!isTransparent && (rectangle.Width > 0) && (rectangle.Height > 0))
  158. {
  159. graphics.SmoothingMode = SmoothingMode.Default;
  160. using (Brush brush = new SolidBrush(fillColor))
  161. {
  162. graphics.FillEllipse(brush, rectangle);
  163. }
  164. }
  165. if (lineWidth != 0)
  166. {
  167. float minWidth = LayoutCommon.PixelToMillimeter(1);
  168. using (Pen pen = new Pen(lineColor))
  169. {
  170. if ((rectangle.Width > 0) && (rectangle.Height == 0))
  171. {
  172. pen.Width = minWidth;
  173. graphics.SmoothingMode = SmoothingMode.AntiAlias;
  174. graphics.DrawLine(pen, rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Top);
  175. }
  176. else if ((rectangle.Width == 0) && (rectangle.Height > 0))
  177. {
  178. pen.Width = minWidth;
  179. graphics.SmoothingMode = SmoothingMode.AntiAlias;
  180. graphics.DrawLine(pen, rectangle.Left, rectangle.Top, rectangle.Left, rectangle.Bottom);
  181. }
  182. else
  183. {
  184. float num = Math.Min(rectangle.Width, rectangle.Height) / 2;
  185. num = Math.Min(num, lineWidth);
  186. pen.Width = Math.Max(minWidth, num);
  187. graphics.SmoothingMode = SmoothingMode.Default;
  188. graphics.DrawEllipse(pen, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
  189. }
  190. }
  191. }
  192. }
  193. finally
  194. {
  195. graphics.SmoothingMode = smoothingMode;
  196. graphics.EndContainer(containerState);
  197. }
  198. }
  199. #endregion 绘制椭圆
  200. #region 绘制矩形
  201. /// <summary>
  202. /// 绘制矩形
  203. /// </summary>
  204. /// <param name="graphics">Graphics</param>
  205. /// <param name="rectangle">图形范围</param>
  206. /// <param name="lineColor">边线颜色</param>
  207. /// <param name="fillColor">填充颜色</param>
  208. /// <param name="lineWidth">边线宽(mm)</param>
  209. /// <param name="isTransparent">背景是否透明</param>
  210. public static void DrawRectangle(
  211. Graphics graphics,
  212. RectangleF rectangle,
  213. Color lineColor,
  214. Color fillColor,
  215. float lineWidth,
  216. bool isTransparent)
  217. {
  218. DrawRectangle(graphics, graphics.PageUnit, rectangle,
  219. lineColor, fillColor, lineWidth, isTransparent);
  220. }
  221. /// <summary>
  222. /// 绘制矩形
  223. /// </summary>
  224. /// <param name="graphics">Graphics</param>
  225. /// <param name="unit">GraphicsUnit</param>
  226. /// <param name="rectangle">图形范围</param>
  227. /// <param name="lineColor">边线颜色</param>
  228. /// <param name="fillColor">填充颜色</param>
  229. /// <param name="lineWidth">边线宽(mm)</param>
  230. /// <param name="isTransparent">背景是否透明</param>
  231. public static void DrawRectangle(
  232. Graphics graphics,
  233. GraphicsUnit unit,
  234. RectangleF rectangle,
  235. Color lineColor,
  236. Color fillColor,
  237. float lineWidth,
  238. bool isTransparent)
  239. {
  240. if ((rectangle.Width < 0) || (rectangle.Height < 0))
  241. {
  242. return;
  243. }
  244. GraphicsContainer containerState = graphics.BeginContainer();
  245. graphics.PageUnit = unit;
  246. SmoothingMode smoothingMode = graphics.SmoothingMode;
  247. try
  248. {
  249. if (!isTransparent && (rectangle.Width > 0) && (rectangle.Height > 0))
  250. {
  251. graphics.SmoothingMode = SmoothingMode.Default;
  252. using (Brush brush = new SolidBrush(fillColor))
  253. {
  254. graphics.FillRectangle(brush, rectangle);
  255. }
  256. }
  257. if (lineWidth != 0)
  258. {
  259. float minWidth = LayoutCommon.PixelToMillimeter(1);
  260. using (Pen pen = new Pen(lineColor))
  261. {
  262. if ((rectangle.Width > 0) && (rectangle.Height == 0))
  263. {
  264. pen.Width = minWidth;
  265. graphics.SmoothingMode = SmoothingMode.AntiAlias;
  266. graphics.DrawLine(pen, rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Top);
  267. }
  268. else if ((rectangle.Width == 0) && (rectangle.Height > 0))
  269. {
  270. pen.Width = minWidth;
  271. graphics.SmoothingMode = SmoothingMode.AntiAlias;
  272. graphics.DrawLine(pen, rectangle.Left, rectangle.Top, rectangle.Left, rectangle.Bottom);
  273. }
  274. else
  275. {
  276. float num = Math.Min(rectangle.Width, rectangle.Height) / 2;
  277. num = Math.Min(num, lineWidth);
  278. pen.Width = Math.Max(minWidth, num);
  279. graphics.SmoothingMode = SmoothingMode.Default;
  280. graphics.DrawRectangle(pen, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
  281. }
  282. }
  283. }
  284. }
  285. finally
  286. {
  287. graphics.SmoothingMode = smoothingMode;
  288. graphics.EndContainer(containerState);
  289. }
  290. }
  291. #endregion 绘制矩形
  292. #region 绘制图片
  293. /// <summary>
  294. /// 绘制图片
  295. /// </summary>
  296. /// <param name="graphics">Graphics</param>
  297. /// <param name="rectangle">图片范围</param>
  298. /// <param name="image">图片</param>
  299. public static void DrawImage(
  300. Graphics graphics,
  301. RectangleF rectangle,
  302. Image image)
  303. {
  304. DrawImage(graphics, graphics.PageUnit, rectangle, image);
  305. }
  306. /// <summary>
  307. /// 绘制图片
  308. /// </summary>
  309. /// <param name="graphics">Graphics</param>
  310. /// <param name="unit">GraphicsUnit</param>
  311. /// <param name="rectangle">图片范围</param>
  312. /// <param name="image">图片</param>
  313. public static void DrawImage(
  314. Graphics graphics,
  315. GraphicsUnit unit,
  316. RectangleF rectangle,
  317. Image image)
  318. {
  319. if (image == null || (rectangle.Width < 0) || (rectangle.Height < 0))
  320. {
  321. return;
  322. }
  323. GraphicsContainer containerState = graphics.BeginContainer();
  324. graphics.PageUnit = unit;
  325. graphics.DrawImage(image, rectangle);
  326. graphics.EndContainer(containerState);
  327. }
  328. #endregion 绘制图片
  329. #region 绘制文本
  330. /// <summary>
  331. /// 绘制文本
  332. /// </summary>
  333. /// <param name="graphics">Graphics</param>
  334. /// <param name="rectangleM">绘制范围(余白)</param>
  335. /// <param name="rectangle">绘制范围</param>
  336. /// <param name="context">文本</param>
  337. /// <param name="font">字体</param>
  338. /// <param name="foreColor">字体颜色</param>
  339. /// <param name="lineSpace">行间隔</param>
  340. /// <param name="charSpace">字间隔</param>
  341. /// <param name="charCount">行文字数</param>
  342. /// <param name="alignment">文本对齐方式</param>
  343. /// <param name="alignmentVertical">文本垂直对齐方式</param>
  344. /// <param name="wrap">是否自动文本换行</param>
  345. /// <param name="clip">是否剪裁延伸到边框外侧的文本</param>
  346. /// <param name="selected">是否选择</param>
  347. public static void DrawText(
  348. Graphics graphics,
  349. RectangleF rectangleM,
  350. RectangleF rectangle,
  351. string context,
  352. Font font,
  353. Color foreColor,
  354. float lineSpace,
  355. float charSpace,
  356. int charCount,
  357. TextAlignment alignment,
  358. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  359. TextAlignment alignmentVertical,
  360. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  361. bool wrap,
  362. bool clip,
  363. bool selected)
  364. {
  365. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  366. //DrawText(graphics, graphics.PageUnit, rectangleM, rectangle, context, font, foreColor,
  367. // lineSpace, charSpace, charCount, alignment, wrap, clip, selected);
  368. DrawText(graphics, graphics.PageUnit, rectangleM, rectangle, context, font, foreColor,
  369. lineSpace, charSpace, charCount, alignment, alignmentVertical, wrap, clip, selected);
  370. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  371. }
  372. /// <summary>
  373. /// 绘制文本
  374. /// </summary>
  375. /// <param name="graphics">Graphics</param>
  376. /// <param name="unit">GraphicsUnit</param>
  377. /// <param name="rectangleM">绘制范围(余白)</param>
  378. /// <param name="rectangle">绘制范围</param>
  379. /// <param name="context">文本</param>
  380. /// <param name="font">字体</param>
  381. /// <param name="foreColor">字体颜色</param>
  382. /// <param name="lineSpace">行间隔</param>
  383. /// <param name="charSpace">字间隔</param>
  384. /// <param name="charCount">行文字数</param>
  385. /// <param name="alignment">文本对齐方式</param>
  386. /// <param name="alignmentVertical">文本垂直对齐方式</param>
  387. /// <param name="wrap">是否自动文本换行</param>
  388. /// <param name="clip">是否剪裁延伸到边框外侧的文本</param>
  389. /// <param name="selected">是否选择</param>
  390. public static void DrawText(
  391. Graphics graphics,
  392. GraphicsUnit unit,
  393. RectangleF rectangleM,
  394. RectangleF rectangle,
  395. string context,
  396. Font font,
  397. Color foreColor,
  398. float lineSpace,
  399. float charSpace,
  400. int charCount,
  401. TextAlignment alignment,
  402. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  403. TextAlignment alignmentVertical,
  404. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  405. bool wrap,
  406. bool clip,
  407. bool selected)
  408. {
  409. clip = false;
  410. selected = false;
  411. if (string.IsNullOrEmpty(context)
  412. || rectangle.Width <= 0
  413. || rectangle.Height <= 0)
  414. {
  415. return;
  416. }
  417. GraphicsContainer containerState = graphics.BeginContainer();
  418. graphics.PageUnit = unit;
  419. graphics.SetClip(rectangleM, CombineMode.Intersect);
  420. string[] lines = System.Text.RegularExpressions.Regex
  421. .Split(context, System.Environment.NewLine);
  422. using (SolidBrush textBrush = new SolidBrush(foreColor))
  423. {
  424. #if DRAWTEST
  425. graphics.DrawRectangle(new Pen(Color.Red, 0.1f), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
  426. #endif
  427. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  428. //DrawString(graphics, lines, font, textBrush, lineSpace, charSpace,
  429. // charCount, rectangle, alignment, wrap, clip, selected);
  430. DrawString(graphics, lines, font, textBrush, lineSpace, charSpace,
  431. charCount, rectangle, alignment, alignmentVertical, wrap, clip, selected);
  432. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  433. }
  434. graphics.EndContainer(containerState);
  435. }
  436. /// <summary>
  437. /// 横向绘制文本
  438. /// </summary>
  439. /// <param name="graphics">Graphics</param>
  440. /// <param name="lines">多行文本</param>
  441. /// <param name="font">字体</param>
  442. /// <param name="textBrush">字体笔刷</param>
  443. /// <param name="lineSpace">行间隔</param>
  444. /// <param name="charSpace">字间隔</param>
  445. /// <param name="charCount">行文字数</param>
  446. /// <param name="rectangle">文本范围</param>
  447. /// <param name="alignment">文本对齐方式</param>
  448. /// <param name="alignmentVertical">文本垂直对齐方式</param>
  449. /// <param name="wrap">是否自动文本换行</param>
  450. /// <param name="clip">是否剪裁延伸到边框外侧的文本</param>
  451. /// <param name="selected">是否选择</param>
  452. private static void DrawString(
  453. Graphics graphics,
  454. string[] lines,
  455. Font font,
  456. SolidBrush textBrush,
  457. float lineSpace,
  458. float charSpace,
  459. int charCount,
  460. RectangleF rectangle,
  461. TextAlignment alignment,
  462. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  463. TextAlignment alignmentVertical,
  464. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  465. bool wrap,
  466. bool clip,
  467. bool selected)
  468. {
  469. SizeF fullSizeF = graphics.MeasureString(LayoutConsts.FULLSHAPE_TEXT,
  470. font,
  471. PointF.Empty,
  472. LayoutCommon.StringFormatHorizontal);
  473. // 单行文字数限制。
  474. if (0 < charCount)
  475. {
  476. System.Text.StringBuilder sbLine = new System.Text.StringBuilder();
  477. List<string> newLines = new List<string>();
  478. foreach (string line in lines)
  479. {
  480. char[] chars = line.ToCharArray();
  481. int index = 0;
  482. while (index < chars.Length)
  483. {
  484. int nextIndex = index + charCount;
  485. if (nextIndex <= chars.Length)
  486. {
  487. for (int i = index; i < nextIndex; i++)
  488. {
  489. sbLine.Append(chars[i]);
  490. }
  491. }
  492. else
  493. {
  494. for (int i = index; i < chars.Length; i++)
  495. {
  496. sbLine.Append(chars[i]);
  497. }
  498. }
  499. newLines.Add(sbLine.ToString());
  500. sbLine.Length = 0;
  501. index = nextIndex;
  502. }
  503. }
  504. lines = newLines.ToArray();
  505. if (charCount == 1)
  506. {
  507. alignment = TextAlignment.Evenness;
  508. }
  509. else
  510. {
  511. alignment = TextAlignment.LeftOrTop;
  512. charSpace = (rectangle.Width - fullSizeF.Width * charCount)
  513. / (charCount - 1);
  514. }
  515. }
  516. SizeF halfSizeF = graphics.MeasureString(LayoutConsts.HALFSHAPE_TEXT,
  517. font,
  518. PointF.Empty,
  519. LayoutCommon.StringFormatHorizontal);
  520. // 单行文字绘制开始
  521. bool isRowStart = false;
  522. // 单行文字绘制结束
  523. bool isRowEnd = false;
  524. // 一行文字绘制开始
  525. //bool isLineStart = true;
  526. // 一行文字绘制结束
  527. bool isLineEnd = false;
  528. // 多行文字绘制开始
  529. bool isLinesStart = true;
  530. // 多行文字绘制结束
  531. bool isLinesEnd = false;
  532. // 文字整体(字间隔,行间隔)范围
  533. float pointerTop = rectangle.Top;
  534. float pointerBottom = rectangle.Top + fullSizeF.Height;
  535. float pointerLeft = rectangle.Left;
  536. // 文字范围
  537. float textTop = rectangle.Top;
  538. float textLeft = rectangle.Left;
  539. //// 选择状态行间隔范围
  540. //RectangleF lineSpaceSelectedRectangleF = RectangleF.Empty;
  541. // 文字范围
  542. List<TextRectangleF> textRectangleFs = new List<TextRectangleF>();
  543. // 文本垂直对齐方式 modify by chenxy 2014-03-28 begin
  544. List<TextRectangleF[]> allTextRectFs = new List<TextRectangleF[]>();
  545. // 文本垂直对齐方式 modify by chenxy 2014-03-28 end
  546. // 文本绘制
  547. for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
  548. {
  549. // 一行文本绘制
  550. //isLineStart = true;
  551. isLineEnd = false;
  552. int colIndex = 0;
  553. int lineCharCount = lines[lineIndex].Length;
  554. char[] chars = lines[lineIndex].ToCharArray();
  555. while (true)
  556. {
  557. isRowStart = true;
  558. isRowEnd = false;
  559. textLeft = rectangle.Left;
  560. pointerLeft = rectangle.Left;
  561. if (colIndex < lineCharCount)
  562. {
  563. // 单行文字绘制
  564. for (int charIndex = colIndex; charIndex < lineCharCount; charIndex++, colIndex++)
  565. {
  566. SizeF nextTeatSizeF;
  567. TextRectangleF nextTextRectangleF = new TextRectangleF();
  568. nextTextRectangleF.Text = chars[charIndex].ToString();
  569. // 单行文字数限制
  570. if (0 < charCount)
  571. {
  572. nextTeatSizeF = fullSizeF;
  573. }
  574. else
  575. {
  576. // 半角空格的时候
  577. if (LayoutConsts.SPACE_HALFSHAPE_CHAR.Equals(chars[charIndex]))
  578. {
  579. nextTeatSizeF = halfSizeF;
  580. nextTeatSizeF.Height = fullSizeF.Height;
  581. }
  582. // 全角空格的时候
  583. else if (LayoutConsts.SPACE_FULLSHAPE_CHAR.Equals(chars[charIndex]))
  584. {
  585. nextTeatSizeF = fullSizeF;
  586. }
  587. // 其他
  588. else
  589. {
  590. nextTeatSizeF = graphics.MeasureString(nextTextRectangleF.Text,
  591. font, PointF.Empty, LayoutCommon.StringFormatHorizontal);
  592. nextTeatSizeF.Height = fullSizeF.Height;
  593. }
  594. }
  595. if (isRowStart)
  596. {
  597. float bottom = textTop;
  598. if (!isLinesStart)
  599. {
  600. bottom += lineSpace;
  601. }
  602. // 剪裁
  603. if (clip)
  604. {
  605. bottom += nextTeatSizeF.Height;
  606. }
  607. // 多行绘制结束
  608. if (rectangle.Bottom < bottom)
  609. {
  610. isLinesEnd = true;
  611. break;
  612. }
  613. //// 选择状态行间隔范围填充
  614. //if (selected
  615. // && 0 < lineSpace
  616. // && lineSpaceSelectedRectangleF != RectangleF.Empty)
  617. //{
  618. // lineSpaceSelectedRectangleF.Height = lineSpace;
  619. // graphics.FillRectangle(LayoutCommon.SelectedBrush, lineSpaceSelectedRectangleF);
  620. // lineSpaceSelectedRectangleF = RectangleF.Empty;
  621. //}
  622. if (0 == charCount)
  623. {
  624. // 自动换行
  625. float right = textLeft;
  626. if (rectangle.Right < right)
  627. {
  628. if (wrap)
  629. {
  630. // 单行结束
  631. isRowEnd = true;
  632. break;
  633. }
  634. else
  635. {
  636. if (clip)
  637. {
  638. // 一行结束
  639. isLineEnd = true;
  640. break;
  641. }
  642. }
  643. }
  644. }
  645. }
  646. else
  647. {
  648. if (0 == charCount)
  649. {
  650. float right = textLeft + charSpace + nextTeatSizeF.Width;
  651. // 自动换行
  652. if (wrap)
  653. {
  654. if (rectangle.Right < right)
  655. {
  656. // 文本对齐方式
  657. float correcting = 0;
  658. if (alignment == TextAlignment.RightOrBottom)
  659. {
  660. correcting = rectangle.Right - textLeft;
  661. if (0 < correcting)
  662. {
  663. foreach (TextRectangleF rf in textRectangleFs)
  664. {
  665. rf.RectangleX = rf.RectangleF.X + correcting;
  666. }
  667. }
  668. }
  669. else if (alignment == TextAlignment.Center)
  670. {
  671. correcting = (rectangle.Right - textLeft) / 2;
  672. if (0 < correcting)
  673. {
  674. foreach (TextRectangleF rf in textRectangleFs)
  675. {
  676. rf.RectangleX = rf.RectangleF.X + correcting;
  677. }
  678. }
  679. }
  680. else if (alignment == TextAlignment.Evenness)
  681. {
  682. if (1 < textRectangleFs.Count)
  683. {
  684. correcting = (rectangle.Right - textLeft)
  685. / (textRectangleFs.Count - 1);
  686. if (0 < correcting)
  687. {
  688. for (int j = 0; j < textRectangleFs.Count; j++)
  689. {
  690. textRectangleFs[j].RectangleX +=
  691. correcting * j;
  692. }
  693. }
  694. }
  695. else
  696. {
  697. textRectangleFs[0].RectangleX +=
  698. (rectangle.Right - textLeft) / 2;
  699. }
  700. }
  701. // 单行结束
  702. isRowEnd = true;
  703. break;
  704. }
  705. }
  706. else if (alignment == TextAlignment.LeftOrTop || alignment == TextAlignment.Evenness)
  707. {
  708. if (clip)
  709. {
  710. if (rectangle.Right < right)
  711. {
  712. // 一行结束
  713. isLineEnd = true;
  714. break;
  715. }
  716. }
  717. else
  718. {
  719. if (rectangle.Right < textLeft + charSpace)
  720. {
  721. // 一行结束
  722. isLineEnd = true;
  723. break;
  724. }
  725. }
  726. }
  727. }
  728. }
  729. nextTextRectangleF.RectangleF = new RectangleF(pointerLeft, pointerTop,
  730. nextTeatSizeF.Width, nextTeatSizeF.Height);
  731. textRectangleFs.Add(nextTextRectangleF);
  732. // 一行绘制结束
  733. if (isLineEnd)
  734. {
  735. break;
  736. }
  737. // 下一个文字位置计算
  738. if (isRowStart)
  739. {
  740. textLeft = textLeft + nextTeatSizeF.Width;
  741. isRowStart = false;
  742. }
  743. else
  744. {
  745. textLeft = textLeft + charSpace + nextTeatSizeF.Width;
  746. }
  747. pointerLeft = pointerLeft + nextTeatSizeF.Width + charSpace;
  748. }
  749. // 多行绘制结束
  750. if (isLinesEnd)
  751. {
  752. break;
  753. }
  754. // 一行绘制结束
  755. if (isLineEnd)
  756. {
  757. break;
  758. }
  759. // 单行绘制结束
  760. if (isRowEnd)
  761. {
  762. if (isLinesStart)
  763. {
  764. textTop = textTop + fullSizeF.Height;
  765. isLinesStart = false;
  766. }
  767. else
  768. {
  769. textTop = textTop + lineSpace + fullSizeF.Height;
  770. }
  771. pointerTop = pointerTop + fullSizeF.Height + lineSpace;
  772. pointerBottom = pointerTop + fullSizeF.Height;
  773. // 单行文字绘制
  774. if (textRectangleFs.Count > 0)
  775. {
  776. //lineSpaceSelectedRectangleF = DrawStringRow(graphics, textRectangleFs, font, textBrush, selected);
  777. TextRectangleF[] trfs = new TextRectangleF[textRectangleFs.Count];
  778. for (int i = 0; i < textRectangleFs.Count; i++)
  779. {
  780. trfs[i] = textRectangleFs[i];
  781. }
  782. textRectangleFs.Clear();
  783. allTextRectFs.Add(trfs);
  784. }
  785. }
  786. }
  787. else
  788. {
  789. // 空白行
  790. if (0 == lineCharCount)
  791. {
  792. float bottom = textTop;
  793. if (!isLinesStart)
  794. {
  795. bottom += lineSpace;
  796. }
  797. // 剪裁
  798. if (clip)
  799. {
  800. bottom += fullSizeF.Height;
  801. }
  802. // 多行绘制结束
  803. if (rectangle.Bottom < bottom)
  804. {
  805. isLinesEnd = true;
  806. break;
  807. }
  808. //// 选择状态行间隔范围填充
  809. //if (selected && 0 < lineSpace && lineSpaceSelectedRectangleF != RectangleF.Empty)
  810. //{
  811. // lineSpaceSelectedRectangleF.Height = lineSpace;
  812. // graphics.FillRectangle(LayoutCommon.SelectedBrush,
  813. // lineSpaceSelectedRectangleF);
  814. // lineSpaceSelectedRectangleF = RectangleF.Empty;
  815. //}
  816. //// 选择状态文本背景绘制
  817. //if (selected)
  818. //{
  819. // float correcting = 0;
  820. // if (alignment == TextAlignment.RightOrBottom)
  821. // {
  822. // correcting = rectangle.Right - textLeft;
  823. // }
  824. // else if (alignment == TextAlignment.Center)
  825. // {
  826. // correcting = (rectangle.Right - textLeft) / 2;
  827. // }
  828. // else if (alignment == TextAlignment.Evenness)
  829. // {
  830. // correcting = (rectangle.Right - textLeft) / 2;
  831. // }
  832. // RectangleF textRectangleF =
  833. // new RectangleF(pointerLeft + correcting,
  834. // pointerTop,
  835. // fullSizeF.Width / 4,
  836. // fullSizeF.Height + lineSpace);
  837. // graphics.FillRectangle(LayoutCommon.SelectedBrush, textRectangleF);
  838. //}
  839. }
  840. // 一行结束
  841. isLineEnd = true;
  842. break;
  843. }
  844. }
  845. // 多行绘制结束
  846. if (isLinesEnd)
  847. {
  848. break;
  849. }
  850. // 一行绘制结束
  851. if (isLineEnd)
  852. {
  853. // 下一个文字位置计算
  854. if (isLinesStart)
  855. {
  856. textTop = textTop + fullSizeF.Height;
  857. isLinesStart = false;
  858. }
  859. else
  860. {
  861. textTop = textTop + lineSpace + fullSizeF.Height;
  862. }
  863. pointerTop = pointerTop + fullSizeF.Height + lineSpace;
  864. pointerBottom = pointerTop + fullSizeF.Height;
  865. // 一行文本绘制
  866. //lineSpaceSelectedRectangleF = DrawLineHorizontal(graphics, textRectangleFs,
  867. // font, underline, strikeout, textBrush, rectangle, alignment, selected);
  868. if (textRectangleFs.Count > 0)
  869. {
  870. SetStringAlignmentH(textRectangleFs, rectangle, alignment, wrap, clip);
  871. //lineSpaceSelectedRectangleF = DrawStringRow(graphics, textRectangleFs, font, textBrush, selected);
  872. TextRectangleF[] trfs = new TextRectangleF[textRectangleFs.Count];
  873. for (int i = 0; i < textRectangleFs.Count; i++)
  874. {
  875. trfs[i] = textRectangleFs[i];
  876. }
  877. textRectangleFs.Clear();
  878. allTextRectFs.Add(trfs);
  879. }
  880. }
  881. }
  882. // 文本绘制结束
  883. if (isLinesEnd)
  884. {
  885. //if (selected && isLinesStart && isLinesEnd)
  886. //{
  887. // // 选择状态空文本背景绘制
  888. // graphics.FillRectangle(LayoutCommon.SelectedBrush, rectangle);
  889. //}
  890. if (textRectangleFs.Count > 0)
  891. {
  892. SetStringAlignmentH(textRectangleFs, rectangle, alignment, wrap, clip);
  893. //DrawStringRow(graphics, textRectangleFs, font, textBrush, selected);
  894. TextRectangleF[] trfs = new TextRectangleF[textRectangleFs.Count];
  895. for (int i = 0; i < textRectangleFs.Count; i++)
  896. {
  897. trfs[i] = textRectangleFs[i];
  898. }
  899. textRectangleFs.Clear();
  900. allTextRectFs.Add(trfs);
  901. }
  902. }
  903. // 垂直方向文本位置设定
  904. float correctingV = 0;
  905. if (alignmentVertical == TextAlignment.RightOrBottom)
  906. {
  907. float bottom = allTextRectFs[allTextRectFs.Count - 1][0].RectangleF.Bottom;
  908. correctingV = rectangle.Bottom - bottom;
  909. if (correctingV < 0)
  910. {
  911. correctingV = 0;
  912. }
  913. foreach (TextRectangleF[] rfs in allTextRectFs)
  914. {
  915. foreach (TextRectangleF rf in rfs)
  916. {
  917. rf.RectangleY = rf.RectangleY + correctingV;
  918. graphics.DrawString(rf.Text, font, textBrush, rf.RectangleF,
  919. LayoutCommon.StringFormatHorizontal);
  920. }
  921. }
  922. }
  923. else if (alignmentVertical == TextAlignment.Center)
  924. {
  925. float bottom = allTextRectFs[allTextRectFs.Count - 1][0].RectangleF.Bottom;
  926. correctingV = (rectangle.Bottom - bottom) / 2;
  927. if (correctingV < 0)
  928. {
  929. correctingV = 0;
  930. }
  931. foreach (TextRectangleF[] rfs in allTextRectFs)
  932. {
  933. foreach (TextRectangleF rf in rfs)
  934. {
  935. rf.RectangleY = rf.RectangleY + correctingV;
  936. graphics.DrawString(rf.Text, font, textBrush, rf.RectangleF,
  937. LayoutCommon.StringFormatHorizontal);
  938. }
  939. }
  940. }
  941. else
  942. {
  943. foreach (TextRectangleF[] rfs in allTextRectFs)
  944. {
  945. foreach (TextRectangleF rf in rfs)
  946. {
  947. graphics.DrawString(rf.Text, font, textBrush, rf.RectangleF,
  948. LayoutCommon.StringFormatHorizontal);
  949. }
  950. }
  951. }
  952. }
  953. /// <summary>
  954. /// 根据横向文本对齐方式,设定文本位子
  955. /// </summary>
  956. /// <param name="textRectangleFs">每个文字的范围</param>
  957. /// <param name="rectangleF">文本范围</param>
  958. /// <param name="alignment">文本对齐方式</param>
  959. /// <param name="wrap">是否自动文本换行</param>
  960. /// <param name="clip">是否剪裁延伸到边框外侧的文本</param>
  961. private static void SetStringAlignmentH(
  962. List<TextRectangleF> textRectangleFs,
  963. RectangleF rectangleF,
  964. TextAlignment alignment,
  965. bool wrap,
  966. bool clip)
  967. {
  968. //if (0 < textRectangleFs.Count)
  969. {
  970. float correcting = 0;
  971. float right = textRectangleFs[textRectangleFs.Count - 1].RectangleF.Right;
  972. // 文本对齐方式
  973. if (alignment == TextAlignment.RightOrBottom)
  974. {
  975. correcting = rectangleF.Right - right;
  976. if (wrap)
  977. {
  978. if (0 < correcting)
  979. {
  980. foreach (TextRectangleF rf in textRectangleFs)
  981. {
  982. rf.RectangleX += correcting;
  983. }
  984. }
  985. }
  986. // 不自动换行
  987. else
  988. {
  989. // 剪裁
  990. if (clip)
  991. {
  992. int count = 0;
  993. foreach (TextRectangleF rf in textRectangleFs)
  994. {
  995. rf.RectangleX += correcting;
  996. if (rf.RectangleX < rectangleF.Left)
  997. {
  998. count++;
  999. }
  1000. }
  1001. if (count > 0)
  1002. {
  1003. textRectangleFs.RemoveRange(0, count);
  1004. }
  1005. }
  1006. // 不剪裁
  1007. else
  1008. {
  1009. int count = 0;
  1010. foreach (TextRectangleF rf in textRectangleFs)
  1011. {
  1012. rf.RectangleX += correcting;
  1013. if (rf.RectangleF.Right < rectangleF.Left)
  1014. {
  1015. count++;
  1016. }
  1017. }
  1018. if (count > 0)
  1019. {
  1020. textRectangleFs.RemoveRange(0, count);
  1021. }
  1022. }
  1023. }
  1024. }
  1025. else if (alignment == TextAlignment.Center)
  1026. {
  1027. correcting = (rectangleF.Right - right) / 2;
  1028. if (wrap)
  1029. {
  1030. if (0 < correcting)
  1031. {
  1032. foreach (TextRectangleF rf in textRectangleFs)
  1033. {
  1034. rf.RectangleX += correcting;
  1035. }
  1036. }
  1037. }
  1038. // 不自动换行
  1039. else
  1040. {
  1041. // 剪裁
  1042. if (clip)
  1043. {
  1044. int index = -1;
  1045. int count = 0;
  1046. int start = -1;
  1047. int length = 0;
  1048. foreach (TextRectangleF rf in textRectangleFs)
  1049. {
  1050. index++;
  1051. rf.RectangleX += correcting;
  1052. if (rf.RectangleX < rectangleF.Left)
  1053. {
  1054. count++;
  1055. }
  1056. else if (rectangleF.Right < rf.RectangleF.Right)
  1057. {
  1058. if (start < 0)
  1059. {
  1060. start = index;
  1061. }
  1062. length++;
  1063. }
  1064. }
  1065. if (length > 0)
  1066. {
  1067. textRectangleFs.RemoveRange(start, length);
  1068. }
  1069. if (count > 0)
  1070. {
  1071. textRectangleFs.RemoveRange(0, count);
  1072. }
  1073. }
  1074. else
  1075. {
  1076. int index = -1;
  1077. int count = 0;
  1078. int start = -1;
  1079. int length = 0;
  1080. foreach (TextRectangleF rf in textRectangleFs)
  1081. {
  1082. index++;
  1083. rf.RectangleX += correcting;
  1084. if (rf.RectangleF.Right < rectangleF.Left)
  1085. {
  1086. count++;
  1087. }
  1088. else if (rectangleF.Right < rf.RectangleX)
  1089. {
  1090. if (start < 0)
  1091. {
  1092. start = index;
  1093. }
  1094. length++;
  1095. }
  1096. }
  1097. if (length > 0)
  1098. {
  1099. textRectangleFs.RemoveRange(start, length);
  1100. }
  1101. if (count > 0)
  1102. {
  1103. textRectangleFs.RemoveRange(0, count);
  1104. }
  1105. }
  1106. }
  1107. }
  1108. else if (alignment == TextAlignment.Evenness)
  1109. {
  1110. if (1 < textRectangleFs.Count)
  1111. {
  1112. correcting = (rectangleF.Right - right) / (textRectangleFs.Count - 1);
  1113. if (correcting > 0)
  1114. {
  1115. for (int i = 0; i < textRectangleFs.Count; i++)
  1116. {
  1117. textRectangleFs[i].RectangleX += correcting * i;
  1118. }
  1119. }
  1120. }
  1121. else
  1122. {
  1123. textRectangleFs[0].RectangleX += (rectangleF.Right - right) / 2;
  1124. }
  1125. }
  1126. }
  1127. }
  1128. // /// <summary>
  1129. // /// 横向绘制单行文本
  1130. // /// </summary>
  1131. // /// <param name="graphics">Graphics</param>
  1132. // /// <param name="textRectangleFs">每个文字的范围</param>
  1133. // /// <param name="font">字体</param>
  1134. // /// <param name="textBrush">文本笔刷</param>
  1135. // /// <param name="selected">是否选择</param>
  1136. // /// <returns>文本行间隔范围</returns>
  1137. // private static RectangleF DrawStringRow(
  1138. // Graphics graphics,
  1139. // List<TextRectangleF> textRectangleFs,
  1140. // Font font,
  1141. // SolidBrush textBrush,
  1142. // bool selected)
  1143. // {
  1144. // //if (0 < textRectangleFs.Count)
  1145. // {
  1146. // //// 文字绘制范围
  1147. // //float width = textRectangleFs[textRectangleFs.Count - 1].RectangleF.Right
  1148. // // - textRectangleFs[0].RectangleF.Left;
  1149. // //RectangleF selectedRectangleF =
  1150. // // new RectangleF(textRectangleFs[0].RectangleF.Left,
  1151. // // textRectangleFs[0].RectangleF.Top,
  1152. // // width,
  1153. // // textRectangleFs[0].RectangleF.Height);
  1154. // //RectangleF lineSpaceSelectedRectangleF = RectangleF.Empty;
  1155. // //if (selected)
  1156. // //{
  1157. // // // 选择状态文字的背景绘制
  1158. // // graphics.FillRectangle(LayoutCommon.SelectedBrush, selectedRectangleF);
  1159. // // lineSpaceSelectedRectangleF.X = selectedRectangleF.Left;
  1160. // // lineSpaceSelectedRectangleF.Y = selectedRectangleF.Bottom;
  1161. // // lineSpaceSelectedRectangleF.Width = selectedRectangleF.Width;
  1162. // //}
  1163. // foreach (TextRectangleF rf in textRectangleFs)
  1164. // {
  1165. //#if DRAWTEST
  1166. // graphics.DrawRectangle(new Pen(Color.Blue, 0.1f), rf.RectangleF.X, rf.RectangleF.Y, rf.RectangleF.Width, rf.RectangleF.Height);
  1167. //#endif
  1168. // graphics.DrawString(rf.Text, font, textBrush, rf.RectangleF,
  1169. // LayoutCommon.StringFormatHorizontal);
  1170. // }
  1171. // textRectangleFs.Clear();
  1172. // //return lineSpaceSelectedRectangleF;
  1173. // }
  1174. // }
  1175. #endregion 绘制文本
  1176. #endregion 函数
  1177. }
  1178. }