InvoiceLayoutPrinter.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. 
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Data;
  6. using System.Drawing;
  7. using System.Drawing.Printing;
  8. using System.IO;
  9. using System.Runtime.Serialization.Formatters.Binary;
  10. using System.Security.Cryptography;
  11. namespace Dongke.WinForm.Controls.InvoiceLayout
  12. {
  13. public class InvoiceLayoutPrinter
  14. {
  15. #region 常量
  16. #region 保存、读取相关
  17. // TODO 加密保存 解密读取
  18. private static byte[] KEY = new byte[] { 106, 240, 243, 74, 29, 163, 145, 29, 39, 65, 118, 96, 247, 237, 40, 121, 116, 10, 14, 50, 139, 117, 244, 163, 193, 190, 184, 66, 8, 185, 78, 73 };
  19. private static byte[] IV = new byte[] { 26, 122, 25, 28, 97, 211, 152, 32, 223, 110, 120, 242, 170, 35, 96, 93 };
  20. private static ICryptoTransform _decryptor = null;
  21. #endregion 保存、读取相关
  22. #endregion
  23. #region 成员变量
  24. private PropertyOfLayoutBox Property = null;
  25. private GridItem OneGridItem = null;
  26. private List<LayoutItem> LayoutItems = null;
  27. private int PageWidthPixel = 0;
  28. private int PageHeightPixel = 0;
  29. private RectangleF BackImgRectangleF = RectangleF.Empty;
  30. private float _allOffsetX = 0;
  31. private float _allOffsetY = 0;
  32. private int _printPageNum = 1; // 打印页的当前页码
  33. private int _printTotalPageNum = 1; // 总页数
  34. private DataRow _printData = null;
  35. private DataTable _printGridData = null;
  36. private PrintDocument _printDocument = new PrintDocument();
  37. #endregion
  38. #region 构造函数
  39. static InvoiceLayoutPrinter()
  40. {
  41. Rijndael age = Rijndael.Create();
  42. _decryptor = age.CreateDecryptor(KEY, IV);
  43. }
  44. private InvoiceLayoutPrinter()
  45. {
  46. _printDocument.DocumentName = "LayoutDocument";
  47. _printDocument.BeginPrint += new PrintEventHandler(this.printDocument_BeginPrint);
  48. _printDocument.PrintPage += new PrintPageEventHandler(this.PrintDocument_PrintPage);
  49. }
  50. #endregion
  51. private void printDocument_BeginPrint(object sender, PrintEventArgs e)
  52. {
  53. }
  54. private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
  55. {
  56. //try
  57. {
  58. e.Graphics.PageUnit = GraphicsUnit.Millimeter;
  59. e.HasMorePages = DrawPage(e.Graphics);
  60. }
  61. //catch (Exception ex)
  62. {
  63. }
  64. }
  65. public static List<Image> Print(byte[] layout, DataRow data, DataTable detail)
  66. {
  67. if (layout == null || layout.Length == 0)
  68. {
  69. throw new System.ArgumentNullException("InvoiceLayoutPrint's layout is null");
  70. }
  71. if (data == null)
  72. {
  73. throw new System.ArgumentNullException("InvoiceLayoutPrint's data is null");
  74. }
  75. if (detail == null || detail.Rows.Count == 0)
  76. {
  77. throw new System.ArgumentNullException("InvoiceLayoutPrint's detail is null");
  78. }
  79. InvoiceLayoutPrinter printer = new InvoiceLayoutPrinter();
  80. printer.LayoutItems = new List<LayoutItem>();
  81. printer.ReadLayout(layout);
  82. printer._printData = data;
  83. printer._printGridData = detail;
  84. //return printer.DrawImages().ToArray();
  85. return printer.DrawImages();
  86. }
  87. public static void Print(string printerName, short copies, byte[] layout, DataRow data, DataTable detail)
  88. {
  89. if (layout == null || layout.Length == 0)
  90. {
  91. throw new System.ArgumentNullException("InvoiceLayoutPrint's layout is null");
  92. }
  93. if (data == null)
  94. {
  95. throw new System.ArgumentNullException("InvoiceLayoutPrint's data is null");
  96. }
  97. if (detail == null || detail.Rows.Count == 0)
  98. {
  99. throw new System.ArgumentNullException("InvoiceLayoutPrint's detail is null");
  100. }
  101. InvoiceLayoutPrinter printer = new InvoiceLayoutPrinter();
  102. printer.LayoutItems = new List<LayoutItem>();
  103. printer.ReadLayout(layout);
  104. printer._printData = data;
  105. printer._printGridData = detail;
  106. printer._printDocument.PrinterSettings.PrinterName = printerName;
  107. printer._printDocument.PrinterSettings.Copies = copies;
  108. printer._printDocument.Print();
  109. //return printer.DrawImages().ToArray();
  110. //return printer.DrawImages();
  111. }
  112. #region 票据打印
  113. private void ReadLayout(byte[] layout)
  114. {
  115. using (MemoryStream stream = new MemoryStream(layout))
  116. {
  117. stream.Position = 0;
  118. // 反序列化
  119. BinaryFormatter formatter = new BinaryFormatter();
  120. // TODO 解密读取
  121. //if (CryptoStream)
  122. if (true)
  123. {
  124. using (CryptoStream cStream = new CryptoStream(stream, _decryptor, CryptoStreamMode.Read))
  125. {
  126. this.Property = (PropertyOfLayoutBox)formatter.Deserialize(cStream);
  127. }
  128. }
  129. else
  130. {
  131. this.Property = (PropertyOfLayoutBox)formatter.Deserialize(stream);
  132. }
  133. //_lastItemRF = propertyOflayoutBox.LastItemRF;
  134. //_newItemID = propertyOflayoutBox.NewItemID;
  135. //_paperHeight = propertyOflayoutBox.PaperHeight;
  136. //_paperWidth = propertyOflayoutBox.PaperWidth;
  137. //if (_zoomType != ZoomType.Whole)
  138. //{
  139. // ChangePaperSize();
  140. //}
  141. //else
  142. //{
  143. // InitializeZoom();
  144. //}
  145. //paperArea.BackgroundImage = propertyOflayoutBox.BackgroundImage;
  146. //_backgroundImageName = propertyOflayoutBox.BackgroundImageName;
  147. //_isPrintBackground = propertyOflayoutBox.PrintBackground;
  148. //_isPrintAreaVisible = propertyOflayoutBox.PrintAreaVisible;
  149. ArrayList items = this.Property.Items;
  150. if (items != null && 0 < items.Count)
  151. {
  152. foreach (LayoutItem item in items)
  153. {
  154. //item.Init(this, false);
  155. //item.Init();
  156. this.LayoutItems.Add(item);
  157. if (item.ItemType == ItemType.Grid)
  158. {
  159. this.OneGridItem = item as GridItem;
  160. if (this.OneGridItem.HeadRowsHeight == 0)
  161. {
  162. this.OneGridItem.HeadRowsHeight = this.OneGridItem.RowsHeight;
  163. }
  164. }
  165. }
  166. }
  167. //paperArea.Select();
  168. //RefreshItemsBound();
  169. ////paperArea.Refresh();
  170. //return true;
  171. }
  172. }
  173. private List<Image> DrawImages()
  174. {
  175. this.PageWidthPixel = LayoutCommon.MillimeterToPixel(this.Property.PaperWidth);
  176. this.PageHeightPixel = LayoutCommon.MillimeterToPixel(this.Property.PaperHeight);
  177. this._printPageNum = 1;
  178. this._printTotalPageNum = 1;
  179. //if (this.OneGridItem != null)
  180. //{
  181. // foreach (LayoutItem item in this.LayoutItems)
  182. // {
  183. // if (item.ItemType == ItemType.Grid)
  184. // {
  185. // GridItem gItem = (item as GridItem);
  186. // gItem.PrintGridSource = this._printGridData;
  187. // _printTotalPageNum = Math.Max(_printTotalPageNum, gItem.PrintTotalPageNum);
  188. // }
  189. // }
  190. //}
  191. List<Image> images = new List<Image>();
  192. Bitmap pageImage = null;
  193. Graphics pageGraphics = null;
  194. bool hasNextPage = true;
  195. while (hasNextPage)
  196. {
  197. pageImage = new Bitmap(this.PageWidthPixel, this.PageHeightPixel);
  198. pageImage.SetResolution(LayoutCommon.DPI, LayoutCommon.DPI);
  199. pageGraphics = Graphics.FromImage(pageImage);
  200. // TODO 白色背景
  201. pageGraphics.Clear(Color.White);
  202. //pageGraphics.FillRectangle(Brushes.White, pageGraphics.ClipBounds);
  203. pageGraphics.PageUnit = GraphicsUnit.Millimeter;
  204. hasNextPage = DrawPage(pageGraphics);
  205. images.Add(pageImage);
  206. }
  207. return images;
  208. }
  209. private bool DrawPage(Graphics graphics)
  210. {
  211. //try
  212. {
  213. // 背景打印
  214. if (this.Property.PrintBackground)
  215. {
  216. PrintBackgroundImage(graphics);
  217. }
  218. // Item打印
  219. foreach (LayoutItem layoutItem in this.LayoutItems)
  220. {
  221. switch (layoutItem.ItemType)
  222. {
  223. case ItemType.Text:
  224. DrawTextItem(graphics, (TextItem)layoutItem);
  225. break;
  226. case ItemType.Image:
  227. DrawImageItem(graphics, (ImageItem)layoutItem);
  228. break;
  229. case ItemType.Rectangle:
  230. DrawRectangleItem(graphics, (RectangleItem)layoutItem);
  231. break;
  232. case ItemType.Ellipse:
  233. DrawEllipseItem(graphics, (EllipseItem)layoutItem);
  234. break;
  235. //case ItemType.Line:
  236. // DrawLineItem(graphics, (LineItem)layoutItem);
  237. // break;
  238. case ItemType.Grid:
  239. DrawGridItem(graphics, (GridItem)layoutItem);
  240. break;
  241. case ItemType.PageNum:
  242. DrawPageNumItem(graphics, (PageNumItem)layoutItem);
  243. break;
  244. case ItemType.TotalText:
  245. DrawTotalTextItem(graphics, (TotalTextItem)layoutItem);
  246. break;
  247. default:
  248. //throw new NotImplementedException();
  249. break;
  250. }
  251. }
  252. // 表格Item是否有下一页
  253. if (_printPageNum < _printTotalPageNum)
  254. {
  255. _printPageNum++;
  256. //e.HasMorePages = true;
  257. return true;
  258. }
  259. return false;
  260. }
  261. //catch (Exception ex)
  262. //{
  263. // throw ex;
  264. //}
  265. }
  266. #region 绘制
  267. /// <summary>
  268. /// 打印背景图片
  269. /// </summary>
  270. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  271. private void PrintBackgroundImage(Graphics graphics)
  272. {
  273. if (this.Property.BackgroundImage != null)
  274. {
  275. if (this.BackImgRectangleF.IsEmpty)
  276. {
  277. // 背景图片的高宽比例
  278. float imgWHRate = (float)this.Property.BackgroundImage.Width / (float)this.Property.BackgroundImage.Height;
  279. // 打印纸张的高宽比例
  280. float paperWHRate = this.Property.PaperWidth / this.Property.PaperHeight;
  281. // 缩放背景图片,但保持图片高宽比例
  282. if (imgWHRate > paperWHRate)
  283. {
  284. BackImgRectangleF.Width = this.Property.PaperWidth;
  285. BackImgRectangleF.Height = this.Property.PaperWidth / imgWHRate;
  286. BackImgRectangleF.X = 0;
  287. BackImgRectangleF.Y = (this.Property.PaperHeight - BackImgRectangleF.Height) / 2 + 0;
  288. }
  289. else
  290. {
  291. BackImgRectangleF.Width = this.Property.PaperHeight * imgWHRate;
  292. BackImgRectangleF.Height = this.Property.PaperHeight;
  293. BackImgRectangleF.X = (this.Property.PaperWidth - BackImgRectangleF.Width) / 2 + 0;
  294. BackImgRectangleF.Y = 0;
  295. }
  296. }
  297. // 在指定的范围绘制背景图片
  298. graphics.DrawImage(this.Property.BackgroundImage, BackImgRectangleF);
  299. }
  300. }
  301. /// <summary>
  302. /// 打印文本Item
  303. /// </summary>
  304. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  305. /// <param name="textItem">文本Item</param>
  306. private void DrawTextItem(Graphics graphics, TextItem textItem)
  307. {
  308. // 文本Item打印范围
  309. RectangleF rectangleFM = new RectangleF(
  310. _allOffsetX + textItem.Left,
  311. _allOffsetY + textItem.Top,
  312. textItem.Width,
  313. textItem.Height);
  314. RectangleF rectangleF = rectangleFM;
  315. rectangleF.Inflate(0 - LayoutConsts.TEXT_MARGIN, 0 - LayoutConsts.TEXT_MARGIN);
  316. rectangleFM.Height -= LayoutConsts.TEXT_MARGIN;
  317. object value = null;
  318. if (this._printData.Table.Columns.Contains(textItem.DataMember))
  319. {
  320. value = this._printData[textItem.DataMember];
  321. }
  322. textItem.PrintTextItem(value, graphics, rectangleFM, rectangleF);
  323. }
  324. /// <summary>
  325. /// 打印图片Item
  326. /// </summary>
  327. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  328. /// <param name="imageItem">图片Item</param>
  329. private void DrawImageItem(Graphics graphics, ImageItem imageItem)
  330. {
  331. // 图片Item打印范围
  332. RectangleF rectangleF = new RectangleF(
  333. _allOffsetX + imageItem.Left,
  334. _allOffsetY + imageItem.Top,
  335. imageItem.Width,
  336. imageItem.Height);
  337. // 在指定的范围绘制图片Item
  338. LayoutUtility.DrawImage(graphics, rectangleF, imageItem.Image);
  339. }
  340. /// <summary>
  341. /// 打印矩形Item
  342. /// </summary>
  343. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  344. /// <param name="rectangleItem">矩形Item</param>
  345. private void DrawRectangleItem(Graphics graphics, RectangleItem rectangleItem)
  346. {
  347. // 矩形Item打印范围
  348. RectangleF rectangleF = new RectangleF(
  349. _allOffsetX + rectangleItem.Left,
  350. _allOffsetY + rectangleItem.Top,
  351. rectangleItem.Width,
  352. rectangleItem.Height);
  353. float lineWidthDraw = rectangleItem.LineWidth;
  354. // 在指定的范围绘制矩形Item
  355. LayoutUtility.DrawRectangle(graphics, rectangleF, rectangleItem.LineColor,
  356. rectangleItem.FillColor, lineWidthDraw, rectangleItem.Transparent);
  357. }
  358. /// <summary>
  359. /// 打印椭圆Item
  360. /// </summary>
  361. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  362. /// <param name="ellipseItem">椭圆Item</param>
  363. private void DrawEllipseItem(Graphics graphics, EllipseItem ellipseItem)
  364. {
  365. // 椭圆Item打印范围
  366. RectangleF rectangleF = new RectangleF(
  367. _allOffsetX + ellipseItem.Left,
  368. _allOffsetY + ellipseItem.Top,
  369. ellipseItem.Width,
  370. ellipseItem.Height);
  371. float lineWidthDraw = ellipseItem.LineWidth;
  372. // 在指定的范围绘制椭圆Item
  373. LayoutUtility.DrawEllipse(graphics, rectangleF, ellipseItem.LineColor,
  374. ellipseItem.FillColor, lineWidthDraw, ellipseItem.Transparent);
  375. }
  376. /// <summary>
  377. /// 打印表格Item
  378. /// </summary>
  379. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  380. /// <param name="gridItem">表格Item</param>
  381. private void DrawGridItem(Graphics graphics, GridItem gridItem)
  382. {
  383. // 表格Item打印范围
  384. RectangleF rectangleF = new RectangleF(
  385. _allOffsetX + gridItem.Left,
  386. _allOffsetY + gridItem.Top,
  387. gridItem.Width,
  388. gridItem.Height);
  389. // 在指定的范围绘制表格Item
  390. //gridItem.DrawGridItem(graphics, rectangleF, 1, _printPageNum);
  391. gridItem.PrintGridItem(graphics, rectangleF, _printPageNum);
  392. }
  393. /// <summary>
  394. /// 打印页码Item
  395. /// </summary>
  396. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  397. /// <param name="pageNumItem">页码Item</param>
  398. private void DrawPageNumItem(Graphics graphics, PageNumItem pageNumItem)
  399. {
  400. // 文本Item打印范围
  401. RectangleF rectangleFM = new RectangleF(
  402. _allOffsetX + pageNumItem.Left,
  403. _allOffsetY + pageNumItem.Top,
  404. pageNumItem.Width,
  405. pageNumItem.Height);
  406. RectangleF rectangleF = rectangleFM;
  407. rectangleF.Inflate(0 - LayoutConsts.TEXT_MARGIN, 0 - LayoutConsts.TEXT_MARGIN);
  408. rectangleFM.Height -= LayoutConsts.TEXT_MARGIN;
  409. // 在指定的范围绘制文本Item
  410. LayoutUtility.DrawText(graphics,
  411. rectangleFM,
  412. rectangleF,
  413. pageNumItem.GetPrintText(this._printPageNum, this._printTotalPageNum),
  414. pageNumItem.Font,
  415. pageNumItem.TextColor,
  416. 0,
  417. 0,
  418. 0,
  419. pageNumItem.TextAlign,
  420. pageNumItem.TextAlignVertical,
  421. false,
  422. false,
  423. false);
  424. }
  425. /// <summary>
  426. /// 打印合计Item
  427. /// </summary>
  428. /// <param name="graphics">用于绘制的System.Drawing.Graphics</param>
  429. /// <param name="totalTextItem">合计Item</param>
  430. private void DrawTotalTextItem(Graphics graphics, TotalTextItem totalTextItem)
  431. {
  432. // 文本Item打印范围
  433. RectangleF rectangleFM = new RectangleF(
  434. _allOffsetX + totalTextItem.Left,
  435. _allOffsetY + totalTextItem.Top,
  436. totalTextItem.Width,
  437. totalTextItem.Height);
  438. RectangleF rectangleF = rectangleFM;
  439. rectangleF.Inflate(0 - LayoutConsts.TEXT_MARGIN, 0 - LayoutConsts.TEXT_MARGIN);
  440. rectangleFM.Height -= LayoutConsts.TEXT_MARGIN;
  441. if (_printPageNum != _printTotalPageNum && totalTextItem.NotTotalValue != "[#合计值#]")
  442. {
  443. LayoutUtility.DrawText(graphics,
  444. rectangleFM,
  445. rectangleF,
  446. totalTextItem.NotTotalValue,
  447. totalTextItem.NotTotalFont,
  448. totalTextItem.NotTotalColor,
  449. totalTextItem.LineSpace,
  450. totalTextItem.CharacterSpace,
  451. totalTextItem.CharacterCount,
  452. totalTextItem.NotTotalAlign,
  453. totalTextItem.NotTotalAlignVertical,
  454. totalTextItem.Wrap,
  455. totalTextItem.Clip,
  456. false);
  457. return;
  458. }
  459. // 在指定的范围绘制文本Item
  460. object value = null;
  461. if (this._printData.Table.Columns.Contains(totalTextItem.DataMember))
  462. {
  463. value = this._printData[totalTextItem.DataMember];
  464. }
  465. value = totalTextItem.ResetTextValue(value, true);
  466. LayoutUtility.DrawText(graphics,
  467. rectangleFM,
  468. rectangleF,
  469. (value == null? "": value.ToString()),
  470. totalTextItem.Font,
  471. totalTextItem.TextColor,
  472. totalTextItem.LineSpace,
  473. totalTextItem.CharacterSpace,
  474. totalTextItem.CharacterCount,
  475. totalTextItem.TextAlign,
  476. totalTextItem.NotTotalAlignVertical,
  477. totalTextItem.Wrap,
  478. totalTextItem.Clip,
  479. false);
  480. }
  481. #endregion
  482. #endregion
  483. }
  484. }