亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

winfrom 打印表格 字符串的封裝實現代碼 附源碼下載

2020-01-24 03:35:18
字體:
來源:轉載
供稿:網友

所以對于應用層用著還不是很方便。最近做一個項目順便就封裝了一個調用默認打印機的類。雖說有幾個小bug,但對于目前來說,已經滿足需求了。以后不夠了在來升級吧。

1,關于打印上下左右邊距和紙張的高寬。以往都把這些寫死到代碼里面。既然是調用默認打印機,打印機的型號自然有差異。所以我就把這些配置放到app.config里面。但又怕每次打印都加載config影響效率。故此設計了個PrintPaper類。里面所有屬性都是靜態的。還有一個靜態的構造方法。這樣只有在程序開始運行加載一次config。之后就直接從內存讀取了。

PrintPaper類

復制代碼 代碼如下:

/*CreateBy:Bonker,Date:20121115*/
     /// <summary>
     /// 從配置文件讀取紙張的大小,與邊框的距離
     /// </summary>
     public class PrintPaper
     {
         /// <summary>
         /// 距離上邊界的距離
         /// </summary>
         public static int MarginTop { set; get; }
         /// <summary>
         /// 距離左邊界的距離
         /// </summary>
         public static int MarginLeft { set; get; }
         /// <summary>
         /// 距離右邊界的距離
         /// </summary>
         public static int MarginRight { set; get; }
         /// <summary>
         /// 距離下邊界的距離
         /// </summary>
         public static int MarginBottom { set; get; }
         /// <summary>
         /// 紙張的寬度
         /// </summary>
         public static int Width { set; get; }
         /// <summary>
         /// 紙張的高度
         /// </summary>
         public static int Height { set; get; }
         /// <summary>
         /// 異常情況
         /// </summary>
         public static string Error { set; get; }

         //對于靜態屬性和構造方法。當第一次使用該類的時候,先初始化靜態屬性,然后調用靜態類。
         //故此配置文件只加載一次,以后調用都會從內存中讀取。
         //此中寫法的好處,一次加載,以后不再加載,速度快。弊端:程序運行過程中,改變了config配置。則需重新運行程序。配置才加載生效。
         static PrintPaper()
         {
             //先給異常賦空值,當異常不為空時。說明配置數據有問題,或者程序有異常
             Error = null;
             string marginTop = BonkerConfig.GetConfig("marginTop");
             string marginBottom = BonkerConfig.GetConfig("marginBottom");
             string marginLeft = BonkerConfig.GetConfig("marginLeft");
             string marginRight = BonkerConfig.GetConfig("marginRight");
             //margin的值可以為負值,但是width只能為正,
             //marginTop,等值默認已經為0,如果margin不為空,取值復制給margin
             try
             {
                 if (!string.IsNullOrWhiteSpace(marginTop))
                 {
                     MarginTop = int.Parse(marginTop);
                 }
                 if (!string.IsNullOrWhiteSpace(marginTop))
                 {
                     MarginBottom = int.Parse(marginBottom);
                 }
                 if (!string.IsNullOrWhiteSpace(marginTop))
                 {
                     MarginLeft = int.Parse(marginLeft);
                 }
                 if (!string.IsNullOrWhiteSpace(marginTop))
                 {
                     MarginRight = int.Parse(marginRight);
                 }
             }
             catch (Exception ex)
             {
                 //如果有異常繼續
                 Error = ex.Message;
                 return;
             }
             //判斷紙張寬度
             try
             {
                 //如果paperWidth配置不為正,則為PrintCore類打印的時候,則去默認值
                 string width = BonkerConfig.GetConfig("paperWidth");
                 string height = BonkerConfig.GetConfig("paperWidth");
                 if (!string.IsNullOrWhiteSpace(width))
                 {
                     Width = int.Parse(width);
                 }
                 if (!string.IsNullOrWhiteSpace(height))
                 {
                     Height = int.Parse(width);
                 }
             }
             catch (Exception ex)
             {
                 //如果有異常繼續
                 Error = ex.Message;
                 return;
             }
         }
     }

app.config的內容
復制代碼 代碼如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <!--******************************連接字符串設置************************************-->
    <add key="DBConnectionStr" value=" "/>
    <!--********************************打印邊界設置**********************************-->
    <!--打印紙的距四個邊界的距離,為空這表示默認為0,可以為負值-->
    <!--與上邊界距離-->
    <add key="marginTop" value=""/>
    <!--與上邊界距離-->
    <add key="marginBottom" value=""/>
    <!--與上邊界距離-->
    <add key="marginLeft" value=""/>
    <!--與上邊界距離-->
    <add key="marginRight" value=""/>
    <!--********************************打印紙大小設置**********************************-->
    <!--打印紙張的大小,為空表示取默認值,不可以為負值 -->
    <!--紙張的寬度-->
    <add key="paperWidth" value=""/>
    <!--紙張的高度-->
    <add key="paperHeight" value=""/>
    <!--*******************************************************************************-->
  </appSettings>
</configuration>


2,打印表格,翻閱了很多msdn大神的代碼。大致有點眉目。打印表格是在一點打印完字體后,然后不改變X,Y坐標繼續打印個矩形。所以就有表格了。這樣的表格理論上表格的四個邊框有點細。里面的小格子有點粗。但打印出來后基本就沒差別了。

    打印表格是自適應表格里面的文字最大的寬度。但如果表格里面確實列很少,沒列的最大寬度又很小。打印完真整個表格沒有頁面的紙張寬。那會自動拉寬每一列的寬度。

打印的核心類PrintCore

復制代碼 代碼如下:

/*CreateBy:Bonker,Date:20121115*/
    /// <summary>
    /// 打印類,負責打印表格,普通行等。
    /// </summary>
    public class PrintCore
    {
        /// <summary>
        /// 打印基礎封裝類PrintDocument
        /// </summary>
        public PrintDocument printDoc { set; get; }
        /// <summary>
        /// 當前打印的x坐標
        /// </summary>
        public float currentX { set; get; }
        /// <summary>
        /// 當前打印的Y坐標
        /// </summary>
        public float currentY { set; get; }
        /// <summary>
        /// 默認打印字體
        /// </summary>
        public Font defaultFont { set; get; }
        /// <summary>
        /// 打印的畫刷,默認黑色加粗
        /// </summary>
        public Brush defaultBrush { set; get; }
        /// <summary>
        /// 是否居中打印,默認為false
        /// </summary>
        public bool isCenter { set; get; }
        /// <summary>
        /// 異常錯誤
        /// </summary>
        public string Error { set; get; }

        private Graphics graphic { set; get; }
        /// 構造函數
        /// </summary>
        /// <param name="_printDoc">打印基礎類</param>
        /// <param name="_currentX">打印開始的x坐標,默認為0</param>
        /// <param name="_currentY">打印開始的y坐標,默認為0</param>
        public PrintCore(PrintDocument _printDoc, Graphics _graphics, Font _defaultFont, float _currentX = 0, float _currentY = 0)
        {
            this.printDoc = _printDoc;
            this.currentX = _currentX;
            this.currentY = _currentY;
            this.defaultFont = _defaultFont;
            this.graphic = _graphics;
            this.defaultBrush = new SolidBrush(Color.Black); //默認加粗黑色
            this.isCenter = false;
            //讀取配置文件
            printDocConfig(_printDoc);
            Error = PrintPaper.Error;
        }
        private void printDocConfig(PrintDocument _printDoc)
        {
            _printDoc.DefaultPageSettings.Margins = new Margins(PrintPaper.MarginLeft, PrintPaper.MarginRight, PrintPaper.MarginTop, PrintPaper.MarginBottom);
            //當paper配置的寬度和高度都大于0時,才配置。否則忽略
            if (PrintPaper.Width > 0 && PrintPaper.Height > 0)
            {
                _printDoc.DefaultPageSettings.PaperSize = new PaperSize("", PrintPaper.Width, PrintPaper.Height);
            }

        }
        /// <summary>
        /// 打印字符串,系統可以總動判斷換行打印。
        /// </summary>
        /// <param name="prnStr">打印的字符串</param>
        /// <param name="isPrintLine">打印完成后,是否換行,默認為true</param>
        public void printString(string prnStr, bool isPrintLine = true)
        {
            //打印字符串,根據字符串長度,和紙張寬度,高度等自動換行
            SizeF measure = graphic.MeasureString(prnStr, defaultFont);
            //如果x坐標不為0,或者打印的一行寬度大于紙張的寬度,則居中打印是沒用的。不考慮打印
            if (!isCenter || currentX != 0 || printDoc.DefaultPageSettings.PaperSize.Width < measure.Width)
            {
                //計算打印這么多字要多少行
                int rows = (int)Math.Ceiling(measure.Width / (printDoc.DefaultPageSettings.PaperSize.Width - currentX));
                //根據行,算出要打印的邊界矩形框
                graphic.DrawString(prnStr, defaultFont, defaultBrush, new Rectangle((int)currentX, (int)currentY, (int)Math.Ceiling((printDoc.DefaultPageSettings.PaperSize.Width - currentX)), (int)Math.Ceiling((measure.Height * rows))));
                if (isPrintLine)//如果換行
                {
                    currentY = currentY + measure.Height * rows;
                    currentX = 0;
                }
                else
                {
                    currentY = currentY + measure.Height * (rows - 1);
                    currentX = (measure.Width % (printDoc.DefaultPageSettings.PaperSize.Width - currentX)) + currentX;
                }
            }
            else
            {
                //居中打印一行
                //計算打印前的留白寬度
                float blank = (printDoc.DefaultPageSettings.PaperSize.Width - measure.Width) / 2.0f;
                currentX = currentX + blank;
                graphic.DrawString(prnStr, defaultFont, defaultBrush, currentX, currentY);
                if (isPrintLine)//如果換行
                {
                    currentX = 0;
                    currentY = currentY + measure.Height;
                }
                else
                {
                    currentX = currentX + measure.Width;
                }
            }
        }
        /// <summary>
        /// 打印表格,自適應沒列的寬度
        /// </summary>
        /// <param name="prnDgv"></param>
        /// <param name="isPrintLine"></param>
        public void printDataGridView(DataGridView prnDgv, Font titleFont, Brush titleBrush, Color titleBackGroup, bool isPrintLine = true)
        {
            if (prnDgv == null)
            {
                return;
            }
            prnDgv.AllowUserToAddRows = false;
            //記錄每一列的寬度
            int[] columnWidths = new int[prnDgv.ColumnCount];
            //******************取每列的最大寬度***********************
            //先計算表頭的寬度
            for (int i = 0; i < prnDgv.ColumnCount; i++)
            {
                string celValue = prnDgv.Columns[i].HeaderText;
                SizeF measure = graphic.MeasureString(celValue, titleFont);
                columnWidths[i] = (int)Math.Ceiling(measure.Width);//把打印表頭所占的寬度 先放到columnWidths里面
            }
            //計算表中數據打印的最大寬度
            for (int i = 0; i < prnDgv.Rows.Count; i++)
            {
                for (int j = 0; j < prnDgv.ColumnCount; j++)
                {
                    string celValue = prnDgv[j, i].Value.ToString();
                    SizeF measure = graphic.MeasureString(celValue, defaultFont);
                    if (columnWidths[j] < measure.Width)//如果寬度小于打印寬度,則把長的打印寬度賦值給列寬
                    {
                        columnWidths[j] = (int)Math.Ceiling(measure.Width);
                    }
                }
            }

            //如果表格的寬度小于紙張的寬度,表格沒列的寬度加大
            int allColumsWidth = 0;
            for (int i = 0; i < prnDgv.ColumnCount; i++)
            {
                allColumsWidth += columnWidths[i];//把打印表頭所占的寬度 先放到columnWidths里面
            }
            if (allColumsWidth + prnDgv.ColumnCount < PrintPaper.Width)
            {
                int columnAddWidth = (PrintPaper.Width - allColumsWidth - prnDgv.ColumnCount) / prnDgv.ColumnCount;
                for (int i = 0; i < prnDgv.ColumnCount; i++)
                {
                    columnWidths[i] += columnAddWidth;
                }
            }
            //*************************************************************

            currentX = 0;
            int titleHeight = (int)Math.Ceiling(graphic.MeasureString("1e{(汗", titleFont).Height);
            //打印表頭
            for (int i = 0; i < prnDgv.ColumnCount; i++)
            {
                string celValue = prnDgv.Columns[i].HeaderText;
                //打印背景
                graphic.FillRectangle(new SolidBrush(titleBackGroup), new Rectangle((int)currentX, (int)currentY, columnWidths[i], titleHeight));
                //打印內容
                graphic.DrawString(celValue, titleFont, titleBrush, currentX, currentY);
                //打印表格邊框
                graphic.DrawRectangle(new Pen(titleBrush), new Rectangle((int)currentX, (int)currentY, columnWidths[i], titleHeight));
                currentX = currentX + columnWidths[i];
            }
            currentX = 0;
            currentY = currentY + titleHeight;

            int contentHeight = (int)Math.Ceiling(graphic.MeasureString("1e{(汗", defaultFont).Height);
            //打印內容
            for (int i = 0; i < prnDgv.Rows.Count; i++)
            {
                for (int j = 0; j < prnDgv.ColumnCount; j++)
                {
                    string celValue = prnDgv[j, i].Value.ToString();//打印內容
                    graphic.DrawString(celValue, defaultFont, defaultBrush, currentX, currentY);//打印表格邊框
                    graphic.DrawRectangle(new Pen(defaultBrush), new Rectangle((int)currentX, (int)currentY, columnWidths[j], contentHeight));
                    currentX = currentX + columnWidths[j];
                }
                currentX = 0;
                currentY = currentY + contentHeight;
            }
        }
    }

調用示例代碼

復制代碼 代碼如下:

private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
        {
            PrintCore print = new PrintCore(printDocument1, e.Graphics, new Font("宋體", 14));
            if (print.Error != null)
            {
                e.Cancel = true;
                MessageBox.Show(print.Error);
                return;
            }
            print.isCenter = true;
            print.defaultFont = new Font("宋體", 16);
            print.printString("定積分落實到減肥了減肥了圣誕節死減", true);
            print.isCenter = false;
            print.defaultFont = new Font("宋體", 14);
            print.printString("111定積分落實到減定積分落實到減肥了圣誕節死定了減肥了束帶結發連鎖店減肥了哦定積分落實到減肥了圣誕節死定了減肥了束帶結發連鎖店減肥了哦肥了圣誕節死定了減肥了束帶結發連鎖店減肥了哦");

            print.printDataGridView(dataGridView1,new Font("宋體", 18),Brushes.Black,DefaultBackColor);
        }

總結:以上打印有兩個小問題沒有處理。一個是關于分頁,一個是當表格的寬度過長,超過了頁面的寬度,沒有進行換行處理。

另附上源碼 winfrom_mrdyj_jb51net

作者:Bonker

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧洲永久精品大片ww免费漫画| 欧美日韩一二三四五区| 精品电影在线观看| 久久全国免费视频| 26uuu另类亚洲欧美日本老年| 精品久久久久久久中文字幕| 91久久精品在线| 亚洲国产精品久久精品怡红院| 精品女同一区二区三区在线播放| 亚洲成人a**站| 欧美电影院免费观看| 久久国产一区二区三区| 在线国产精品视频| 午夜精品久久久久久久白皮肤| 日韩视频免费大全中文字幕| 中文字幕亚洲第一| 国产一区二区三区在线看| 亚洲va久久久噜噜噜| 欧美视频在线观看免费网址| 国产精品久久久久久久久久久不卡| 91精品国产自产在线老师啪| 久久国产精品久久国产精品| 亚洲人线精品午夜| 高清一区二区三区日本久| 久久99热精品这里久久精品| 精品小视频在线| 韩国国内大量揄拍精品视频| 日韩精品视频免费在线观看| 欧美大片免费看| 欧美片一区二区三区| 国产精品久久久久影院日本| 欧美电影免费观看网站| 久久久欧美精品| 在线观看日韩av| 色www亚洲国产张柏芝| 日本一本a高清免费不卡| 懂色av中文一区二区三区天美| 亚洲美女av在线| 奇米一区二区三区四区久久| 91久久久久久久久久| 亚洲精品美女网站| 色噜噜国产精品视频一区二区| 国产精品wwwwww| 97涩涩爰在线观看亚洲| 色视频www在线播放国产成人| 欧美激情综合色综合啪啪五月| 国产成人精品一区二区三区| 午夜精品一区二区三区在线视频| 日本韩国欧美精品大片卡二| 国产精品成人免费视频| 国产精品三级在线| 亚洲精品动漫100p| 日本欧美一级片| 中文字幕日韩av综合精品| 亚洲精品日韩欧美| 亚洲国产精品va在线看黑人动漫| 欧美日韩一区免费| 国产精品流白浆视频| 国产91精品黑色丝袜高跟鞋| 欧美国产日本高清在线| 欧美成人免费全部| 精品亚洲一区二区三区在线播放| 日韩在线www| 91久久精品国产91久久| 久久青草精品视频免费观看| 国产va免费精品高清在线观看| 日韩中文字幕欧美| 91性高湖久久久久久久久_久久99| 一本色道久久综合狠狠躁篇怎么玩| 欧美性猛交xxxxx免费看| 亚洲奶大毛多的老太婆| 亚洲国产精品99| 日韩成人xxxx| 尤物tv国产一区| 永久555www成人免费| 欧美成年人在线观看| 日韩欧美国产骚| 亚洲一区中文字幕在线观看| 在线国产精品播放| 在线丨暗呦小u女国产精品| 亚洲第一页中文字幕| 久久精品91久久香蕉加勒比| 91精品国产沙发| 欧美激情国产高清| 亚洲国产精品va在线观看黑人| 国产精品偷伦一区二区| 欧美日韩国产在线看| 亚洲一区二区三| 亚洲欧美一区二区三区情侣bbw| 国产精品专区第二| 国产91亚洲精品| 亚洲国产精久久久久久久| 日日摸夜夜添一区| 日韩av理论片| 岛国av一区二区三区| 日本久久久久久久久久久| 午夜精品久久久久久久久久久久久| 91精品久久久久久久久久久久久久| 亚洲国产精品女人久久久| 亚洲男人天堂视频| 亚洲男人的天堂在线播放| 97免费在线视频| 国产精品自产拍在线观看| 久久综合久久88| 日本中文字幕久久看| 亚洲视频在线视频| 国产在线999| 亚洲电影免费观看高清完整版在线观看| 日韩亚洲成人av在线| 欧美在线视频一二三| 欧美日韩国产一区中文午夜| 欧美黑人极品猛少妇色xxxxx| 国产99久久精品一区二区永久免费| 久久亚洲春色中文字幕| 亚洲自拍高清视频网站| 日本成人免费在线| 亚洲国产成人精品一区二区| 欧美限制级电影在线观看| 日韩av网站大全| 欧美高跟鞋交xxxxhd| 日韩欧中文字幕| 久久影视免费观看| 日本亚洲精品在线观看| 国产精品视频xxx| 欧美成人免费va影院高清| 日韩av片免费在线观看| 91高清在线免费观看| 日韩国产高清视频在线| 日韩成人激情影院| 国产日本欧美视频| 91成人福利在线| 欧美精品久久久久久久| www.日本久久久久com.| 成人在线精品视频| 欧美一级在线播放| 日韩电影中文字幕在线| 欧美激情一级精品国产| 久久精品国产一区二区三区| 国产成人拍精品视频午夜网站| 国产精品视频成人| 欧美精品久久一区二区| 国产精品永久免费视频| 色七七影院综合| 精品久久久久久久久久久久久| 欧美性感美女h网站在线观看免费| 精品毛片三在线观看| 亚洲精品一区二区久| 欧美xxxx综合视频| 亚洲无av在线中文字幕| 日韩精品在线免费观看| 日韩欧美成人区| 欧美日韩成人在线视频| 九九热最新视频//这里只有精品| 久热精品在线视频| 国产精品白丝jk喷水视频一区| 国外成人免费在线播放| 亚洲免费中文字幕| 国产成人av网| 国产精品久久久亚洲| 欧美成年人视频| 欧美性少妇18aaaa视频| 国产精品久久久久影院日本| 日韩成人在线网站| 日韩成人黄色av|