winfrom printed form string packaging implementation code with source download

  • 2020-05-09 19:10:58
  • OfStack

So it's not very convenient for the application layer. A recent project encapsulates a class that calls the default printer. There are a few small bug, but for now, it's enough. Not enough in the future to upgrade it.

1. About the printing margins and the height and width of the paper. We used to write them into code. Since you are calling the default printer, the model of the printer naturally varies. So I'm going to put these configurations in app.config. But I fear that loading config every time I print will affect my efficiency. So an PrintPaper class was designed. All the properties are static. There's also a static constructor. This only loads config once the program starts running. It then reads directly from memory.

PrintPaper class


/*CreateBy:Bonker,Date:20121115*/
     /// <summary>
     ///  Read the size of the paper from the configuration file, the distance from the border 
     /// </summary>
     public class PrintPaper
     {
         /// <summary>
         ///  Distance from the upper boundary 
         /// </summary>
         public static int MarginTop { set; get; }
         /// <summary>
         ///  The distance to the left 
         /// </summary>
         public static int MarginLeft { set; get; }
         /// <summary>
         ///  The distance to the right 
         /// </summary>
         public static int MarginRight { set; get; }
         /// <summary>
         ///  The distance from the lower boundary 
         /// </summary>
         public static int MarginBottom { set; get; }
         /// <summary>
         ///  Width of paper 
         /// </summary>
         public static int Width { set; get; }
         /// <summary>
         ///  Height of paper 
         /// </summary>
         public static int Height { set; get; }
         /// <summary>
         ///  Abnormal situation 
         /// </summary>
         public static string Error { set; get; }

         // For static properties and constructors. When the first 1 The next time you use the class, initialize the static properties, and then call the static class. 
         // The configuration file is loaded only 1 Each subsequent call is read from memory. 
         // The benefits of this notation, 1 Second load, no later load, fast. Cons: in the process of running the program , Changed the config Configuration. Rerun the program. Configuration to load.  
         static PrintPaper()
         {
             // Assign a null value to the exception first, when the exception is not null. Indicates that there is a problem with configuration data or an exception to the program 
             Error = null;
             string marginTop = BonkerConfig.GetConfig("marginTop");
             string marginBottom = BonkerConfig.GetConfig("marginBottom");
             string marginLeft = BonkerConfig.GetConfig("marginLeft");
             string marginRight = BonkerConfig.GetConfig("marginRight");
             //margin Can be negative, but width It can only be positive, 
             //marginTop, The equivalent default is already zero 0 If the margin It's not empty, it copies the value 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)
             {
                 // If there is an exception continue 
                 Error = ex.Message;
                 return;
             }
             // Judge paper width 
             try
             {
                 // if paperWidth If the configuration is not positive, then is PrintCore When the class is printed, go to the default value 
                 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)
             {
                 // If there is an exception continue 
                 Error = ex.Message;
                 return;
             }
         }
     }

app config content

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!--****************************** Connection string Settings ************************************-->
    <add key="DBConnectionStr" value=" "/>
    <!--******************************** Print boundary setting **********************************-->
    <!-- The offset of a printed paper 4 The distance between the boundaries , Is null this means that the default is 0, It could be negative -->
    <!-- Distance from the upper boundary -->
    <add key="marginTop" value=""/>
    <!-- Distance from the upper boundary -->
    <add key="marginBottom" value=""/>
    <!-- Distance from the upper boundary -->
    <add key="marginLeft" value=""/>
    <!-- Distance from the upper boundary -->
    <add key="marginRight" value=""/>
    <!--******************************** Print paper size setting **********************************-->
    <!-- Print the size of the paper , The null representation takes the default value , You can't think of negative values  -->
    <!-- Width of paper -->
    <add key="paperWidth" value=""/>
    <!-- Height of paper -->
    <add key="paperHeight" value=""/>
    <!--*******************************************************************************-->
  </appSettings>
</configuration>

2. Printed out forms and browsed through a lot of msdn codes. It has a general outline. The printed form is printed at 1 o 'clock after the font is printed, and then the X coordinates are not changed. The Y coordinates continue to print rectangles. So there's a table. In theory, the four borders of the table are a little thin. The inside is a little bit thick. But when you print it out, there's almost no difference.

The       printed table is the maximum width of text in the adaptive table. But if the table does have very few columns, the maximum width without columns is very small. The entire table is not as wide as the page. That will automatically stretch the width of each column.

Print the core class PrintCore


/*CreateBy:Bonker,Date:20121115*/
    /// <summary>
    ///  Print class, responsible for printing the form , Regular lines, etc. 
    /// </summary>
    public class PrintCore
    {
        /// <summary>
        ///  Print the basic package class PrintDocument
        /// </summary>
        public PrintDocument printDoc { set; get; }
        /// <summary>
        ///  Currently printed x coordinates 
        /// </summary>
        public float currentX { set; get; }
        /// <summary>
        ///  Currently printed Y coordinates 
        /// </summary>
        public float currentY { set; get; }
        /// <summary>
        ///  Default print font 
        /// </summary>
        public Font defaultFont { set; get; }
        /// <summary>
        ///  Print brush, default black bold 
        /// </summary>
        public Brush defaultBrush { set; get; }
        /// <summary>
        ///  Whether to print in the center, the default is false 
        /// </summary>
        public bool isCenter { set; get; }
        /// <summary>
        ///  Exception error 
        /// </summary>
        public string Error { set; get; }
        private Graphics graphic { set; get; }
        ///  The constructor 
        /// </summary>
        /// <param name="_printDoc"> Print base class </param>
        /// <param name="_currentX"> Print started x The default is 0</param>
        /// <param name="_currentY"> Print started y The default is 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); // The default is bold black 
            this.isCenter = false;
            // Read the configuration file 
            printDocConfig(_printDoc);
            Error = PrintPaper.Error;
        }
        private void printDocConfig(PrintDocument _printDoc)
        {
            _printDoc.DefaultPageSettings.Margins = new Margins(PrintPaper.MarginLeft, PrintPaper.MarginRight, PrintPaper.MarginTop, PrintPaper.MarginBottom);
            // when paper The width and height of the configuration are greater than 0 Is configured when. Otherwise ignore 
            if (PrintPaper.Width > 0 && PrintPaper.Height > 0)
            {
                _printDoc.DefaultPageSettings.PaperSize = new PaperSize("", PrintPaper.Width, PrintPaper.Height);
            }
        }
        /// <summary>
        ///  Print string , The system can always judge the newline printing. 
        /// </summary>
        /// <param name="prnStr"> Printed string </param>
        /// <param name="isPrintLine"> After printing , Whether to wrap or not, the default is true</param>
        public void printString(string prnStr, bool isPrintLine = true)
        {
            // Print a string, wrap it according to the length of the string, the width of the page, the height of the page, etc 
            SizeF measure = graphic.MeasureString(prnStr, defaultFont);
            // if x Coordinates to 0, Or printed 1 If the line width is larger than the width of the paper, it is useless to print in the middle. Don't think about printing 
            if (!isCenter || currentX != 0 || printDoc.DefaultPageSettings.PaperSize.Width < measure.Width)
            {
                // Calculate how many lines it will take to print so many words 
                int rows = (int)Math.Ceiling(measure.Width / (printDoc.DefaultPageSettings.PaperSize.Width - currentX));
                // Calculate the bounding rectangle box to print based on the line 
                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)// If a newline 
                {
                    currentY = currentY + measure.Height * rows;
                    currentX = 0;
                }
                else
                {
                    currentY = currentY + measure.Height * (rows - 1);
                    currentX = (measure.Width % (printDoc.DefaultPageSettings.PaperSize.Width - currentX)) + currentX;
                }
            }
            else
            {
                // Center of the print 1 line 
                // Calculate the width of white space before printing 
                float blank = (printDoc.DefaultPageSettings.PaperSize.Width - measure.Width) / 2.0f;
                currentX = currentX + blank;
                graphic.DrawString(prnStr, defaultFont, defaultBrush, currentX, currentY);
                if (isPrintLine)// If a newline 
                {
                    currentX = 0;
                    currentY = currentY + measure.Height;
                }
                else
                {
                    currentX = currentX + measure.Width;
                }
            }
        }
        /// <summary>
        ///  Print the table to fit the width of no columns 
        /// </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;
            // Record every 1 The width of the column 
            int[] columnWidths = new int[prnDgv.ColumnCount];
            //****************** Take the maximum width of each column ***********************
            // Calculate the width of the header first 
            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);// Print the width occupied by the header   In the first columnWidths inside 
            }
            // Calculates the maximum width to print data in a table 
            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)// If the width is less than the print width, assign the long print width to the column width 
                    {
                        columnWidths[j] = (int)Math.Ceiling(measure.Width);
                    }
                }
            }

            // If the width of the table is less than the width of the paper, the width of the table without columns is increased 
            int allColumsWidth = 0;
            for (int i = 0; i < prnDgv.ColumnCount; i++)
            {
                allColumsWidth += columnWidths[i];// Print the width occupied by the header   In the first columnWidths inside 
            }
            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{( Khan, ", titleFont).Height);
            // Print the header 
            for (int i = 0; i < prnDgv.ColumnCount; i++)
            {
                string celValue = prnDgv.Columns[i].HeaderText;
                // Print background 
                graphic.FillRectangle(new SolidBrush(titleBackGroup), new Rectangle((int)currentX, (int)currentY, columnWidths[i], titleHeight));
                // Print the content 
                graphic.DrawString(celValue, titleFont, titleBrush, currentX, currentY);
                // Print table border 
                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{( Khan, ", defaultFont).Height);
            // Print the content 
            for (int i = 0; i < prnDgv.Rows.Count; i++)
            {
                for (int j = 0; j < prnDgv.ColumnCount; j++)
                {
                    string celValue = prnDgv[j, i].Value.ToString();// Print the content 
                    graphic.DrawString(celValue, defaultFont, defaultBrush, currentX, currentY);// Print table border 
                    graphic.DrawRectangle(new Pen(defaultBrush), new Rectangle((int)currentX, (int)currentY, columnWidths[j], contentHeight));
                    currentX = currentX + columnWidths[j];
                }
                currentX = 0;
                currentY = currentY + contentHeight;
            }
        }
    }

Invoke sample code


private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
        {
            PrintCore print = new PrintCore(printDocument1, e.Graphics, new Font(" Song typeface ", 14));
            if (print.Error != null)
            {
                e.Cancel = true;
                MessageBox.Show(print.Error);
                return;
            }
            print.isCenter = true;
            print.defaultFont = new Font(" Song typeface ", 16);
            print.printString(" Definite points to implement weight loss weight loss Christmas dead minus ", true);
            print.isCenter = false;
            print.defaultFont = new Font(" Song typeface ", 14);
            print.printString("111 Definite integral in the definite integral to lose some weight reduction Christmas dead weight band, pulls the chain reduce weight oh definite integral to lose weight the Christmas dead weight band, pulls the chain reduce weight oh fat Christmas dead weight band, pulls the chain reduce weight oh ");

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

Summary: there are two small problems with the above printing. One is about paging, and one is about not wrapping when the width of the table is too long, exceeding the width of the page.

Attached is the source code winfrom_mrdyj_jb51net

Author: Bonker


Related articles: