C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一)

news2024/11/15 19:31:11

文章目录

      • 前言
      • 相关内容了解
      • 打印预览功能
        • 1 创建winform工程
        • 2 创建要打印的测试数据
        • 3 绘制打印页
        • 绘制页脚
        • 绘制内容
        • PrintPage事件
      • 完整的代码工程
      • 小节

前言

有这么个需求:DataTable中有一些数据是需要给显示或直接可以连接打印机进行打印的, 查阅了一下资料,发现官方就有组件PrintPreviewDialog和PrintDocument能实现这个功能。

相关内容了解

1 PrintPreviewDialog是一个打印预览的对话框,有打印,缩放、页面显示、选择页数、关闭等按钮。
长得就是这个样子。
在这里插入图片描述
2 PrintDocument类:是一个可以发送到打印机上的对象

3 PrintDocument.PrintPage 事件 当需要为当前页打印的输出时发生
4 PaperSize 类 指定纸张的大小
5 PageSettings.PaperSize 属性 获取或设置该页的纸张大小
6 PrinterSettings 类 指定打印时如何打印文档的信息,包括打印文档的打印机
7 PaperKind 枚举 指定标准纸张大小

8 Margins 类 指定打印页的边距尺寸

左上角的坐标点是(MarginBounds.X, MarginBounds.Y)

e.MarginBounds.Right = e.MarginBounds.Left + e.MarginBounds.Width
e.MarginBounds.Bottom = e.MarginBounds.Top + e.MarginBounds.Height

在这里插入图片描述
具体可以查看MSDN的介绍:
1、PrintDocument 类 https://learn.microsoft.com/zh-cn/dotnet/api/system.drawing.printing.printdocument?view=dotnet-plat-ext-7.0
2、Margins 类 https://learn.microsoft.com/zh-cn/dotnet/api/system.drawing.printing.margins?view=dotnet-plat-ext-7.0

打印预览功能

1 创建winform工程

先创建一个winform工程,在窗体上放置了一个Button,名称是btnPreView打印预览的入口按钮,
还有一个PrintDocument组件,名称是myDocument用于呈现要打印的内容。

在这里插入图片描述

2 创建要打印的测试数据

使用一个全局DataTable 名为saveTable存放测试数据。这里创建了100 行* 5列的数据,每列分别是 序号、名称、当前值、描述和默认值这五列。当然这只是我赋予的意义,为了好记而已。

        /// <summary>
        /// 构建临时数据表
        /// </summary>
        /// <returns></returns>
        private DataTable CreateTable()
        {
            DataTable dt = new DataTable();
            DataColumn col1 = new DataColumn("Num", typeof(string)); //序号
            DataColumn col2 = new DataColumn("Name", typeof(string)); //名称
            DataColumn col3 = new DataColumn("Val", typeof(string));  //当前值
            DataColumn col4 = new DataColumn("Des", typeof(string));  //描述
            DataColumn col5 = new DataColumn("Set", typeof(string)); //默认值

            dt.Columns.Add(col1);
            dt.Columns.Add(col2);
            dt.Columns.Add(col3);
            dt.Columns.Add(col4);
            dt.Columns.Add(col5);

            Random random = new Random();
            List<string> nameList = new List<string>
            {
                "A", "BB", "CCC", "D",
                "E", "F", "G","H","II",
                "JJ", "LL", "M"
            };

            List<string> tempList = new List<string>
            {
                "dsd", "sdfdgvre", "Hello", "Gilrs",
                "Today", "YYYY", "dfgre","GSD","fdgfer",
                "Wesd", "DLG", "fsdahfi;o"
            };

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    DataRow dr = dt.NewRow();
                    //序号
                    dr[0] = "KK" + i.ToString("d2") + "." + j.ToString("d2");
                    //名称
                    dr[1] = nameList[j];

                    //当前值
                    if (j % 3 == 0)
                    {
                        dr[2] = random.NextDouble().ToString("f3");
                    }
                    else
                    {
                        dr[2] = i * j - random.Next(0, 30);
                    }
                    //描述
                    dr[3] = tempList[j];

                    //出厂值
                    dr[4] = random.NextDouble().ToString("f2");

                    //添加新行
                    dt.Rows.Add(dr);
                }
            }

            return dt;
        }

3 绘制打印页

这里的绘制分为三个部分,表头、内容和页脚。绘制方法都是大同小异,只是为了模块化,划分了不同区域。使用Draw绘制,重要的是找到要绘制点的X 、Y 坐标,通过MeasureString计算字体的高度, 其余的功能都还比较简单。
先看一下要打印的模板,类似下图。在这里插入图片描述

绘制标题(页眉) 序号 名称

        /// <summary>
        /// 绘制标题头
        /// </summary>
        /// <param name="e">绘图对象</param>
        /// <param name="tempTop">Y轴坐标</param>
        /// <param name="tempFormat">字符串格式</param>
        private void DrawTitle(System.Drawing.Printing.PrintPageEventArgs e,
            int tempTop, StringFormat tempFormat)
        {
            //绘制水平线
            e.Graphics.DrawLine(Pens.Black,
                new Point(e.MarginBounds.Left, tempTop),
                new Point(e.MarginBounds.Right, tempTop));

            Font printFont = new Font(fontName, fontNum);

            //计算字体的高度 K00ARk, 根据使用到的字进行组合成串
            int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height);

            //画刷
            SolidBrush brush = new SolidBrush(Color.Black);

            //填充背景色
            e.Graphics.FillRectangle(Brushes.LightBlue,
                new RectangleF(e.MarginBounds.Left, tempTop, e.MarginBounds.Width, fontHeight));


            //列的序号
            int col = 0;

            //列 序号
            string drawString = TitleStr[col];
            //矩形框
            RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop,
                                       (int)cellWidth[col], fontHeight);

            e.Graphics.DrawString(drawString, printFont,
                                  brush, rectangle, tempFormat);
            col++;

            //列 名称
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 设定值
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 默认值
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
        }

绘制页脚

在底部添加公司信息和页码作为页脚。

        /// <summary>
        /// 绘制页脚
        /// </summary>
        /// <param name="e">绘图对象</param>
        /// <param name="pageNo">页面序号</param>
        private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, int pageNo)
        {
            Font font = new Font("微软雅黑", 10);

            //绘制直线
            e.Graphics.DrawLine(new Pen(Color.Black, 1),
                new Point(e.MarginBounds.Left, e.MarginBounds.Bottom),
                new Point(e.MarginBounds.Right, e.MarginBounds.Bottom));

            //公司信息标注
            string tempStr = "Test for Windows(C) by 唠嗑一夏 Electric Corporation";

            e.Graphics.DrawString(tempStr,
              font, Brushes.Black,
              e.MarginBounds.Left,
              e.MarginBounds.Bottom+2);
            
            //页脚序号
            tempStr = pageNo.ToString();
            e.Graphics.DrawString(tempStr,
                font, Brushes.Black,
                e.MarginBounds.Right -  e.Graphics.MeasureString(tempStr, font).Width,
                e.MarginBounds.Bottom+2);
        }

绘制内容

一行一行的绘制DataTable中的数据内容。

        /// <summary>
        /// 绘制内容
        /// </summary>
        ///  <param name="e">绘图对象</param>
        ///  <param name="printIndex">数据行索引</param>
        /// <param name="tempTop">Y轴坐标</param>
        /// <param name="tempFormat">字符串格式</param>
        private void DrawContent(System.Drawing.Printing.PrintPageEventArgs e, 
                     int printIndex, int tempTop, StringFormat tempFormat)
        {
            Font printFont = new Font(fontName, fontNum);

            //计算字体的高度 K00ARk, 根据使用到的字进行组合成串
            int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height);

            //画刷
            SolidBrush brush = new SolidBrush(Color.Black);

            //列的序号
            int col = 0;

            //列 序号
            string drawString = saveTable.Rows[printIndex][0].ToString() + saveTable.Rows[printIndex][1].ToString();
             //矩形框
            RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop,
                                       (int)cellWidth[col], fontHeight);

            e.Graphics.DrawString(drawString, printFont,
                                  brush, rectangle, tempFormat);
            col++;

            //列 名称
            drawString = saveTable.Rows[printIndex][3].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 设定值
            drawString = saveTable.Rows[printIndex][2].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 默认值
            drawString = saveTable.Rows[printIndex][4].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
        }

PrintPage事件

计算每列占的比例,在事件中判断是否需要换页以及是否绘制结束。

   /// <summary>
        /// 当前页打印发生的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MyDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            //页面大小
            PaperSize pageSize = e.PageSettings.PaperSize;

            //根据页面大小,按比例划分列宽
            //序号
            cellWidth[0] = (float)(pageSize.Width * 0.098);
            //描述
            cellWidth[1] = (float)(pageSize.Width * 0.36);
            //当前值
            cellWidth[2] = (float)(pageSize.Width * 0.2);
            //出厂值
            cellWidth[3] = (float)(pageSize.Width * 0.1176);

            //计算列的起始位置
            cellLeft[0] = e.PageSettings.Margins.Left;
            cellLeft[1] = cellLeft[0] + cellWidth[0];
            cellLeft[2] = cellLeft[1] + cellWidth[1];
            cellLeft[3] = cellLeft[2] + cellWidth[2];

            //高度
            int tempTop = e.MarginBounds.Top;
            //是否新的页面
            bool tempIsNewPage = true;
           
            //设置打印字符串的格式
            StringFormat tempStrFormat = new StringFormat
            {
                Alignment = StringAlignment.Near,
                LineAlignment = StringAlignment.Center,
                Trimming = StringTrimming.EllipsisCharacter
            };

            //设置字体
            Font printFont = new Font("宋体", 9);
            //计算字体的高度
            int fontHeight = (int)e.Graphics.MeasureString("KK00.10序号", printFont).Height;

            //指定高质量、低速度呈现
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            try
            {
                string printStr;

                while(printPoint < saveTable.Rows.Count)
                {//逐行分页打印所有参数

                    if (tempTop + fontHeight > e.MarginBounds.Bottom)
                    {//判断当前打印是否超出页面范围,决定是否换页

                        //打印页脚
                        DrawFooter(e, PageNo);
                        PageNo++;
                        //继续分页打印
                        e.HasMorePages = true;
                        return;
                    }

                    //打印当前页的内容
                    //KK00.00
                    printStr = saveTable.Rows[printPoint][0].ToString().Substring(5);
                    if (printStr.Equals("00") || tempIsNewPage)
                    {//一组数据的开始
                        tempIsNewPage = false;
                        tempTop += 2;
                        //绘制标题
                        DrawTitle(e, tempTop, tempStrFormat);
                        tempTop += fontHeight;
                    }
                    
                        //绘制内容
                        DrawContent(e, printPoint, tempTop, tempStrFormat);
                        //更新Y轴高度
                        tempTop += fontHeight;

                    //序号自增
                    printPoint++;
                    //判断是否已经到终点
                    if(printPoint >= saveTable.Rows.Count)
                    {
                        //绘制页脚
                        DrawFooter(e, PageNo);
                        //重置打印参数
                        PageNo = 1;
                        printPoint = 0;
                        return;
                    }
                }
            }
            catch
            {
            }
        }

完整的代码工程

下面是完整的代码工程,设计界面的代码就不列出来了。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PrintDemo
{
    public partial class Form1 : Form
    {

        //打印序号
        int printPoint = 0;
        //页码
        int PageNo = 1;
        //表头名称
        string[] TitleStr = new string[]
        {
            "序号", "名称", "当前值", "出厂值"
        };

        //列宽
        float[] cellWidth = new float[4];
        //列左侧的起始位置
        float[] cellLeft = new float[4];

        //数据表
        DataTable saveTable;

        string fontName = "宋体";
        int fontNum = 9;


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //数据
            saveTable = CreateTable();
            //打印预览按钮
            btnPreView.Click += BtnPreView_Click;
            //当前页打印发生的事件
            myDocument.PrintPage += MyDocument_PrintPage;
        }

     
        /// <summary>
        /// 构建临时数据表
        /// </summary>
        /// <returns></returns>
        private DataTable CreateTable()
        {
            DataTable dt = new DataTable();
            DataColumn col1 = new DataColumn("Num", typeof(string)); //序号
            DataColumn col2 = new DataColumn("Name", typeof(string)); //名称
            DataColumn col3 = new DataColumn("Val", typeof(string));  //当前值
            DataColumn col4 = new DataColumn("Des", typeof(string));  //描述
            DataColumn col5 = new DataColumn("Set", typeof(string)); //默认值

            dt.Columns.Add(col1);
            dt.Columns.Add(col2);
            dt.Columns.Add(col3);
            dt.Columns.Add(col4);
            dt.Columns.Add(col5);

            Random random = new Random();
            List<string> nameList = new List<string>
            {
                "A", "BB", "CCC", "D",
                "E", "F", "G","H","II",
                "JJ", "LL", "M"
            };

            List<string> tempList = new List<string>
            {
                "dsd", "sdfdgvre", "Hello", "Gilrs",
                "Today", "YYYY", "dfgre","GSD","fdgfer",
                "Wesd", "DLG", "fsdahfi;o"
            };

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    DataRow dr = dt.NewRow();
                    //序号
                    dr[0] = "KK" + i.ToString("d2") + "." + j.ToString("d2");
                    //名称
                    dr[1] = nameList[j];

                    //当前值
                    if (j % 3 == 0)
                    {
                        dr[2] = random.NextDouble().ToString("f3");
                    }
                    else
                    {
                        dr[2] = i * j - random.Next(0, 30);
                    }
                    //描述
                    dr[3] = tempList[j];

                    //出厂值
                    dr[4] = random.NextDouble().ToString("f2");

                    //添加新行
                    dt.Rows.Add(dr);
                }
            }

            return dt;
        }


        /// <summary>
        /// 打印预览
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnPreView_Click(object sender, EventArgs e)
        {
            //打印预览对话框
            PrintPreviewDialog dialog = new PrintPreviewDialog();
            dialog.Document = myDocument;
            dialog.ShowIcon = false;
            dialog.ShowDialog();
        }

        /// <summary>
        /// 当前页打印发生的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MyDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            //页面大小
            PaperSize pageSize = e.PageSettings.PaperSize;

            //根据页面大小,按比例划分列宽
            //序号
            cellWidth[0] = (float)(pageSize.Width * 0.098);
            //描述
            cellWidth[1] = (float)(pageSize.Width * 0.36);
            //当前值
            cellWidth[2] = (float)(pageSize.Width * 0.2);
            //出厂值
            cellWidth[3] = (float)(pageSize.Width * 0.1176);

            //计算列的起始位置
            cellLeft[0] = e.PageSettings.Margins.Left;
            cellLeft[1] = cellLeft[0] + cellWidth[0];
            cellLeft[2] = cellLeft[1] + cellWidth[1];
            cellLeft[3] = cellLeft[2] + cellWidth[2];

            //高度
            int tempTop = e.MarginBounds.Top;
            //是否新的页面
            bool tempIsNewPage = true;
           
            //设置打印字符串的格式
            StringFormat tempStrFormat = new StringFormat
            {
                Alignment = StringAlignment.Near,
                LineAlignment = StringAlignment.Center,
                Trimming = StringTrimming.EllipsisCharacter
            };

            //设置字体
            Font printFont = new Font("宋体", 9);
            //计算字体的高度
            int fontHeight = (int)e.Graphics.MeasureString("KK00.10序号", printFont).Height;

            //指定高质量、低速度呈现
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            try
            {
                string printStr;

                while(printPoint < saveTable.Rows.Count)
                {//逐行分页打印所有参数

                    if (tempTop + fontHeight > e.MarginBounds.Bottom)
                    {//判断当前打印是否超出页面范围,决定是否换页

                        //打印页脚
                        DrawFooter(e, PageNo);
                        PageNo++;
                        //继续分页打印
                        e.HasMorePages = true;
                        return;
                    }

                    //打印当前页的内容
                    //KK00.00
                    printStr = saveTable.Rows[printPoint][0].ToString().Substring(5);
                    if (printStr.Equals("00") || tempIsNewPage)
                    {//一组数据的开始
                        tempIsNewPage = false;
                        tempTop += 2;
                        //绘制标题
                        DrawTitle(e, tempTop, tempStrFormat);
                        tempTop += fontHeight;
                    }
                    
                        //绘制内容
                        DrawContent(e, printPoint, tempTop, tempStrFormat);
                        //更新Y轴高度
                        tempTop += fontHeight;

                    //序号自增
                    printPoint++;
                    //判断是否已经到终点
                    if(printPoint >= saveTable.Rows.Count)
                    {
                        //绘制页脚
                        DrawFooter(e, PageNo);
                        //重置打印参数
                        PageNo = 1;
                        printPoint = 0;
                        return;
                    }
                }
            }
            catch
            {
            }
        }

        /// <summary>
        /// 绘制页脚
        /// </summary>
        /// <param name="e">绘图对象</param>
        /// <param name="pageNo">页面序号</param>
        private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, int pageNo)
        {
            Font font = new Font("微软雅黑", 10);

            //绘制直线
            e.Graphics.DrawLine(new Pen(Color.Black, 1),
                new Point(e.MarginBounds.Left, e.MarginBounds.Bottom),
                new Point(e.MarginBounds.Right, e.MarginBounds.Bottom));

            //公司信息标注
            string tempStr = "Test for Windows(C) by 唠嗑一夏 Electric Corporation";

            e.Graphics.DrawString(tempStr,
              font, Brushes.Black,
              e.MarginBounds.Left,
              e.MarginBounds.Bottom+2);
            
            //页脚序号
            tempStr = pageNo.ToString();
            e.Graphics.DrawString(tempStr,
                font, Brushes.Black,
                e.MarginBounds.Right -  e.Graphics.MeasureString(tempStr, font).Width,
                e.MarginBounds.Bottom+2);
        }


        /// <summary>
        /// 绘制标题头
        /// </summary>
        /// <param name="e">绘图对象</param>
        /// <param name="tempTop">Y轴坐标</param>
        /// <param name="tempFormat">字符串格式</param>
        private void DrawTitle(System.Drawing.Printing.PrintPageEventArgs e,
            int tempTop, StringFormat tempFormat)
        {
            //绘制水平线
            e.Graphics.DrawLine(Pens.Black,
                new Point(e.MarginBounds.Left, tempTop),
                new Point(e.MarginBounds.Right, tempTop));

            Font printFont = new Font(fontName, fontNum);

            //计算字体的高度 K00ARk, 根据使用到的字进行组合成串
            int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height);

            //画刷
            SolidBrush brush = new SolidBrush(Color.Black);

            //填充背景色
            e.Graphics.FillRectangle(Brushes.LightBlue,
                new RectangleF(e.MarginBounds.Left, tempTop, e.MarginBounds.Width, fontHeight));


            //列的序号
            int col = 0;

            //列 序号
            string drawString = TitleStr[col];
            //矩形框
            RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop,
                                       (int)cellWidth[col], fontHeight);

            e.Graphics.DrawString(drawString, printFont,
                                  brush, rectangle, tempFormat);
            col++;

            //列 名称
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 设定值
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 默认值
            drawString = TitleStr[col];
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
        }

        /// <summary>
        /// 绘制内容
        /// </summary>
        ///  <param name="e">绘图对象</param>
        ///  <param name="printIndex">数据行索引</param>
        /// <param name="tempTop">Y轴坐标</param>
        /// <param name="tempFormat">字符串格式</param>
        private void DrawContent(System.Drawing.Printing.PrintPageEventArgs e, 
                     int printIndex, int tempTop, StringFormat tempFormat)
        {
            Font printFont = new Font(fontName, fontNum);

            //计算字体的高度 K00ARk, 根据使用到的字进行组合成串
            int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height);

            //画刷
            SolidBrush brush = new SolidBrush(Color.Black);

            //列的序号
            int col = 0;

            //列 序号
            string drawString = saveTable.Rows[printIndex][0].ToString() + saveTable.Rows[printIndex][1].ToString();
             //矩形框
            RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop,
                                       (int)cellWidth[col], fontHeight);

            e.Graphics.DrawString(drawString, printFont,
                                  brush, rectangle, tempFormat);
            col++;

            //列 名称
            drawString = saveTable.Rows[printIndex][3].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 设定值
            drawString = saveTable.Rows[printIndex][2].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
            col++;

            //列 默认值
            drawString = saveTable.Rows[printIndex][4].ToString();
            //水平向右平移 并设置矩形框的宽度
            rectangle.X = cellLeft[col];
            rectangle.Width = cellWidth[col];
            e.Graphics.DrawString(drawString, printFont,
                brush, rectangle, tempFormat);
        }

    }
}

最后的效果图
在这里插入图片描述
在这里插入图片描述

小节

1 使用PrintPreviewDialog + PrintDocument 可以实现打印预览功能

2 页面的绘制是在PrintDocument 的PrintDocument.PrintPage打印页事件中绘制

3 System.Drawing.Printing.PrintPageEventArgs e 在 e.Graphics的画布上进行绘制,DrawString绘制文本,DrawLine绘制直线,FillRectangle填充背景色,根据实际需要选择相应的接口。

4 绘制需要注意绘制点的X Y 坐标,可以以页面的边距e.MarginBounds作为参考点,使用e.Graphics.MeasureString可以测量该字符串占用的高和宽。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/498318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jenkins共享ci阶段

jenkins共享ci阶段 需求 一个产品包含多个服务&#xff0c;这些服务的流水线都是类似的&#xff1a;制作制品构建并推送镜像构建并推送chart包触发自动部署。我们期望将流水线拆分为ci流水线、cd流水线&#xff0c;ci流水线包含&#xff1a;制作制品构建并推送镜像构建并推送…

蓝牙协议栈之L2CAP使用

目录 前言一、逻辑链路层及自适应协议层&#xff08;L2CAP&#xff09;二、常用的L2CAP术语三、L2CAP的工作模式四、L2CAP通道五、L2CAP帧类型六、Fragmentation/Recombination七、Segmentation/Reassembly八、L2CAP MTU九、Controller to Host Flow Control十、总结 前言 本文…

七个值得推荐的物联网分析平台

物联网分析平台是一种软件工具&#xff0c;可以帮助企业收集和分析来自其广泛的物联网设备的数据。企业可以通过物联网收集大量数据&#xff0c;从消费者支出模式到流量使用&#xff0c;物联网数据分析平台在帮助企业获得竞争优势所需的洞察力方面至关重要。 物联网分析平台已…

「2023 最新」 Github、Gitlab Git 工作流「常用」 git 命令、规范以及操作总结

Git commit 规范 关于提交信息的格式&#xff0c;可以遵循以下的规则&#xff1a; feat: 新特性&#xff0c;添加功能fix: 修改 bugrefactor: 代码重构docs: 文档修改style: 代码格式修改test: 测试用例修改chore: 其他修改, 比如构建流程, 依赖管理 Git 基础知识 当我们通过…

Midjourney生成LOGO指南

目录 常见的Logo 宠物店Logo Graphic Logo​ Lettermark Logo​ Geometric Logo​ Mascot Logo​ 增加风格——艺术运动​ 每个产品都有自己的专属名称&#xff0c;也有自己专属的Logo&#xff0c;经过前几篇的学习&#xff0c;我相信你也有了一定的基础&#xff0c;今天…

TiDB实战篇-PD调度常见问题处理方法

常见的问题 调度产生和执行 常见的调度类型 参数调度的速度 调度典型场景 Leader分布不均匀监控 leader分布算法&#xff0c;每一个leader的size作为总和&#xff0c;还有TiKV的剩余空间等等。 可以手动设置权重。 分布不均衡处理 TiKV节点下线速度慢 TiKV下线速度慢解决方法 …

一文说透IO多路复用select/poll/epoll

概述 如果我们要开发一个高并发的TCP程序。常规的做法是&#xff1a;多进程或者多线程。即&#xff1a;使用其中一个线程或者进程去监听有没有客户端连接上来&#xff0c;一旦有新客户端连接&#xff0c;就新开一个线程(进程)&#xff0c;将其扔到线程&#xff08;或进程&…

C++——类和对象[下]

0.关注博主有更多知识 C知识合集 目录 1.再谈构造函数 1.1初始化列表 1.2初始化列表的初始化顺序 1.3构造函数的隐式类型转换 1.4explicit关键字 2.static成员 2.1static成员变量 2.2static成员函数 3.友元 3.1友元函数 3.2友元类 4.内部类 5.匿名对象 6.编译器…

美颜sdk对于移动端视频直播的优化效果研究报告

随着移动互联网的快速发展&#xff0c;移动端视频直播应用也越来越受到用户的青睐。然而&#xff0c;对于许多用户来说&#xff0c;直播的画质却成为了一个令人头疼的问题。为了解决这个问题&#xff0c;许多直播应用开始引入美颜sdk&#xff0c;以期提升直播画质和用户体验。本…

凌思微-蓝牙框架-流程理解

1.蓝牙SOC芯片主函数流程 int main() { sys_init_app(); ble_init(); dev_manager_init(dev_manager_callback); gap_manager_init(gap_manager_callback); gatt_manager_init(gatt_manager_callback); rtos_init(); ble_task_init(); app_task_init(); vTaskStartScheduler();…

第8章:聚合函数

目录 一、常见的聚合函数 二、GROUP BY 的使用 三、HAVING 的使用&#xff0c;过滤数据 四、SQL底层的执行原理 五、练习 一、常见的聚合函数 1.概念 聚合函数作用于一组数据&#xff0c;并对一组数据返回一个值。 2.聚合函数的类型 AVG(),SUM(),MAX(),MIN(),COUNT() 3. AV…

【Spring篇】AOP

&#x1f353;系列专栏:Spring系列专栏 &#x1f349;个人主页:个人主页 目录 一、AOP简介 1.什么是AOP? 2.AOP作用 3.AOP核心概念 二、AOP入门案例 1.需求分析 2.思路分析 3.环境准备 4.AOP实现步骤 三、AOP工作流程 1.AOP工作流程 2.AOP核心概念 四、AOP配置管…

Python小姿势 - 1. Python的设计理念

Python的设计理念 Python的设计理念是“优雅”、“明确”、“简单”。 优雅&#xff1a;Python代码风格优美&#xff0c;语法简洁明了&#xff0c;代码可读性高&#xff0c;易于理解和维护。 明确&#xff1a;Python语言规范清晰&#xff0c;标准库丰富&#xff0c;可用于开发各…

第五章 作业(123)【编译原理】

第五章 作业【编译原理】 前言推荐第五章 作业123 随堂练习课前热身04-17随堂练习04-17课前热身04-24 最后 前言 2023-5-3 22:12:46 以下内容源自《【编译原理】》 仅供学习交流使用 推荐 第四章 作业&#xff08;123&#xff09;【编译原理】 第五章 作业 1 1.令文法G为…

医生的百科词条怎么创建?医生的百科词条创建技巧值得你收藏

医生是医学领域中的专业人员&#xff0c;主要负责诊断、治疗和预防疾病。在现代社会中&#xff0c;医生的角色越来越重要&#xff0c;是社会中不可或缺的职业之一。 而随着互联网的发展&#xff0c;百度百科已成为人们获取信息的重要途径&#xff0c;医生想要提高自己的知名度和…

SpringBoot项目简单入门

一、创建项目 1、选择Spring Initializr 2、为了提高项目构建效率&#xff0c;可以尝试修改阿里脚手架&#xff0c;地址如下&#xff1a; https://start.aliyun.com 3、点击下一步 4、选择Web与spring Web&#xff0c;然后点击完成开始项目构建 5、项目构建完成如图所示 二、…

Linux基础知识—Linux

文章目录 1.认识Linux2.常见命令2.1ls2.2pwd2.3cd2.4touch2.5mkdir2.6rm2.7cp2.8mv2.9man2.10date2.11grep2.12ps2.13netstat 3.文件内容的操作3.1cat3.2vim3.3less3.4head3.5tail3.6管道|3.7重定向 4.管理软件4.1yum&#xff08;在线的方式管理&#xff09;4.2rpm&#xff08;…

OnlineJudge-负载均衡式在线OJ

关于个人项目是在找实习以及参加秋招非常重要的简历内容&#xff0c;今天博主来介绍一下自己的一个项目。 开发环境&#xff1a;CentOS7、Makefile、g、vscode、MySQL Workbench 所用技术&#xff1a;C STL 标准库、Boost 准标准库(字符串切割)、cpp-httplib 第三方开源网络库 …

数据结构(C语言):两个字符串比较大小

一、一个小插曲 在写这篇文章之前&#xff0c;作者想先和大家分享一个小故事。如果你不想看这个小故事的话&#xff0c;可以直接跳到第二点哦。 为了锻炼自己的编码能力&#xff0c;平时作业和实验题的代码我都是不看书、不看老师的PPT&#xff0c;按照自己的思路一行一行敲出…

【STM32CubeMX】F103RTC时钟

前言 本文记录了我学习STM32CubeMX的过程&#xff0c;方便以后回忆。我们使用的开发板是基于STM32F103C6T6的。本章记录了RTC时钟的基础配置。下文调试时用到的串口来查看&#xff0c;不过串口的配置省略了。 步骤 实验目标&#xff1a;基于RTC时钟&#xff0c;查看它的秒计时…