- //定义全局变量count,储存当前打印的行数
- int count=0;
- //定义一个方法,接收一个DataTable类型参数及PrintDocument的PrintPage事件传入的参数e以方便操作
- private void PrintTable(DataTable dt, System.Drawing.Printing.PrintPageEventArgs e)
- {
- //取得对应的Graphics对象
- Graphics g = e.Graphics;
- //获得相关页面X坐标、Y坐标、打印区域宽度、长度
- int x = e.PageSettings.Margins.Left;
- int y = e.PageSettings.Margins.Top;
- int width = e.PageSettings.PaperSize.Width -e.PageSettings.Margins.Left - e.PageSettings.Margins.Right;
- int height = e.PageSettings.PaperSize.Height - e.PageSettings.Margins.Top - e.PageSettings.Margins.Bottom;
- //定义打印字体
- Font font = new Font("宋体",15);
- //rowCount是除去打印过的行数后剩下的行数
- int rowCount = dt.Rows.Count-count;
- //maxPageRow是当前设置下该页面可以打印的最大行数
- int maxPageRow=height/(int)font.GetHeight();
- //因为是表格,先画一条水平直线
- g.DrawLine(new Pen(Brushes.Black, 1), new Point(x, y), new Point(x + (dt.Columns.Count) * 135, y));
- //再画出表格各列的列标题
- for (int i = 0; i < dt.Columns.Count; i++)
- {
- string head = dt.Columns[i].ColumnName;
- g.DrawString(head, font, Brushes.Black, x + i * 135, y);
- }
- //画完标题,再画一条直线
- g.DrawLine(new Pen(Brushes.Black, 1), new Point(x, y + (int)font.GetHeight()), new Point(x + (dt.Columns.Count) * 135, y + (int)font.GetHeight()));
- //判断,如果剩下的行数小于可打印的最大行数,则执行下列代码
- if (maxPageRow >= rowCount)
- {
- //当前行数小于Table内总行数时,循环
- while (count < dt.Rows.Count)
- {
- //内循环打印Table内行数据
- int columnCount = 0;
- while (columnCount < dt.Columns.Count)
- {
- string temp = dt.Rows[count][columnCount].ToString();
- //打印每个单元格内的数据
- g.DrawString(temp, font, Brushes.Black, x + columnCount * 135, y + (count % maxPageRow) * (int)font.GetHeight() + (int)font.GetHeight());
- //打印完一行后,继续打印一条直线
- g.DrawLine(new Pen(Brushes.Black, 1), new Point(x, y + (count % maxPageRow) * (int)font.GetHeight() + 2 * (int)font.GetHeight()), new Point(x + (dt.Columns.Count) * 135, y + (count % maxPageRow) * (int)font.GetHeight() + 2 * (int)font.GetHeight()));
- columnCount++;
- }
- count++;
- }
- //所有数据打印完毕后,打印垂直直线
- for (int i = 0; i <= dt.Columns.Count; i++)
- {
- g.DrawLine(new Pen(Brushes.Black), new Point(x + i * 135, y), new Point(x + i * 135, y + rowCount * (int)font.GetHeight() + (int)font.GetHeight()));
- }
- }
- //判断,如果剩下的行数大于可打印的最大行数,则执行下列代码
- else
- {
- do
- {
- //与上面类似,注意下面while的条件
- int columnCount = 0;
- while (columnCount < dt.Columns.Count)
- {
- string temp = dt.Rows[count][columnCount].ToString();
- //打印每个单元格
- g.DrawString(temp, font, Brushes.Black, x + columnCount * 135, y + (count % maxPageRow) * (int)font.GetHeight() + (int)font.GetHeight());
- //打印水平直线
- g.DrawLine(new Pen(Brushes.Black, 1), new Point(x, y + (count % maxPageRow) * (int)font.GetHeight() + 2 * (int)font.GetHeight()), new Point(x + (dt.Columns.Count)*135, y + (count % maxPageRow) * (int)font.GetHeight() + 2 * (int)font.GetHeight()));
- columnCount++;
- }
- count++;
- } while ((count % maxPageRow > 0));
- //打印垂直直线
- for (int i = 0; i <= dt.Columns.Count;i++ )
- {
- g.DrawLine(new Pen(Brushes.Black), new Point(x + i * 135, y), new Point(x + i * 135, y + height + (int)font.GetHeight()));
- }
- }
- //指定HasMorePages值,如果页面最大行数小于剩下的行数,则返回true(还有),否则返回false
- if (maxPageRow<rowCount)
- {
- e.HasMorePages = true;
- }
- else
- {
- e.HasMorePages = false;
- count = 0;
- }
- }
奇长无比,打印的原理就是画,所有东西都是画出来的,大体思路就是这样,其他的无非就是计算跟调整间距问题,多试几次不难,我觉得最难的部分是循环取值及设置HasMorePages属性,PrintDocument的PrintPage方法是打印完一页调用一次,因此当自己做打印设置时,需要清楚的知道哪些变量需要储存为全局变量以方便记录打印位置,HasMorePages属性也需要注意,是不是只需要一个条件就可以指定其值,很多情况下需要多个条件同时满足,另外对画表格这种事情来说,前几页跟最后一页while里条件写法肯定是不同的,写一起就乱套了,最后,在给HasMorePages设置为false后,不要忘记把你的全局变量恢复初始值,否则连点两下打印预览就没数据了,以上是A4大小,如果只实现简单打印,这样足够了,如果设计到调整页面,设置字体等等,抱歉,做不了,这就需要网上DOWN现成的了。下一个说说TextBox里的文本打印。
- //设置全局变量保存截取字符串位置
- int sub=0;
- private void printText(string text, System.Drawing.Printing.PrintPageEventArgs e)
- {
- //取得Graphics实例
- Graphics g = e.Graphics;
- //获得相关点坐标、长度、宽度
- int x = e.PageSettings.Margins.Left;
- int y = e.PageSettings.Margins.Right;
- int width = e.PageSettings.PaperSize.Width-e.PageSettings.Margins.Left-e.PageSettings.Margins.Right;
- int height = e.PageSettings.PaperSize.Height-e.PageSettings.Margins.Top-e.PageSettings.Margins.Bottom;
- //设置字体
- Font font=new Font("宋体",15);
- //这个方法后面讲
- g.MeasureString(text.Substring(sub), font, new SizeF(width, height-10), new StringFormat(), out charnum, out line);
- //打印string
- g.DrawString(text.Substring(sub), font, Brushes.Black, new RectangleF(x, y, width, height), new StringFormat());
- //设置截取位置
- sub += charnum;
- //设置HasMorePage属性
- if (sub < this.txtText.Text.Length)
- {
- e.HasMorePages = true;
- }
- else
- {
- e.HasMorePages = false;
- sub=0;
- }
- }
- //打印预览
- private void button2_Click(object sender, EventArgs e)
- {
- //注意指定其Document属性
- this.printPreviewDialog1.Document = this.printDocument1;
- this.printPreviewDialog1.ShowDialog();
- }
- //打印
- private void button1_Click(object sender, EventArgs e)
- {
- //同样注意指定Document属性
- this.printDialog1.Document = this.printDocument1;
- if (this.printDialog1.ShowDialog() == DialogResult.OK)
- {
- //触发PrintDocument的PrintPage事件
- this.printDocument1.Print();
- }
- }
OK,关于打印就小小的说完了,不怎么重要,掌握原理即可。