Friday, December 13, 2024

A print service based on C#

   

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;

//
// Author:  Barret
//

namespace Infor.SunSystems.V4 {
    /// <summary>
    /// Print Service
    /// </summary>
    public class PrintService {
        /// <summary>
        /// Contruct method to register the print page event
        /// </summary>
        public PrintService() {
            _docToPrint.PrintPage += new PrintPageEventHandler(docToPrint_PrintPage);
        }

        /// <summary>
        /// Show the print dialog and execute print action if necessary
        /// </summary>
        /// <param name="printType"></param>
        /// <param name="font"></param>
        private void Print(PrintType printType, Font font) {
            _printType = printType;
            _printFont = font;
           
            // Allow the user to choose the page range he or she would
            // like to print.
            PrintDialog printDialog = new PrintDialog();

            printDialog.AllowSomePages = true;
           
            printDialog.UseEXDialog = false;

            // Show the help button.
            printDialog.ShowHelp = true;

            // Set the Document property to the PrintDocument for
            // which the PrintPage Event has been handled. To display the
            // dialog, either this property or the PrinterSettings property
            // must be set
            printDialog.Document = _docToPrint;
           
            DialogResult result = printDialog.ShowDialog();

            // If the result is OK then print the document.
            if (result == DialogResult.OK) {
                _docToPrint.Print();
            }
        }
       
        /// <summary>
        /// Set properties on the PrintDialog object and then display the dialog.
        /// </summary>
        /// <param name="printer"></param>
        /// <param name="pages"></param>
        /// <param name="font"></param>
        public void StartPrint(string printer, IList<string> pages, int linesPerPage, Font font) {
            _pagesToPrint = pages;
            _linesPerPage = linesPerPage;
            // Set the default printer
            if (!string.IsNullOrEmpty(printer)) {
                _docToPrint.PrinterSettings.PrinterName = printer;
            }

            // Initialize the page range
            if (_pagesToPrint.Count > 1) {
                _docToPrint.PrinterSettings.MinimumPage = MINMUM_PAGE;
                _docToPrint.PrinterSettings.MaximumPage = _pagesToPrint.Count;
                _docToPrint.PrinterSettings.FromPage = _docToPrint.PrinterSettings.MinimumPage;
                _docToPrint.PrinterSettings.ToPage = _docToPrint.PrinterSettings.MaximumPage;
            }

            Print(PrintType.TextPages, font);
        }

        /// <summary>
        /// Set properties on the PrintDialog object and then display the dialog.
        /// </summary>
        /// <param name="pages"></param>
        /// <param name="font"></param>
        public void StartPrint(IList<string> pages, int linesPerPage, Font font) {
            StartPrint(null, pages, linesPerPage, font);
        }
       
        /// <summary>
        /// Set properties on the PrintDialog object and then display the dialog.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="font"></param>
        public void StartPrint(string text, Font font) {
            _textToPrint = text;

            Print(PrintType.Text, font);
        }
       
        /// <summary>
        /// Set properties on the PrintDialog object and then display the dialog.
        /// </summary>
        /// <param name="streamToPrint"></param>
        /// <param name="printType"></param>
        /// <param name="font"></param>
        public void StartPrint(Stream streamToPrint, PrintType printType, Font font) {
            _streamToPrint = streamToPrint;

            Print(printType, font);
        }
       
        /// <summary>
        /// Handling the document's PrintPage event. The PrintDialog will print the document by call back this method.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void docToPrint_PrintPage(object sender, PrintPageEventArgs e) {
            // Insert code to render the page here.
            // This code will be called when the control is drawn.

            switch (_printType) {
                case PrintType.TextPages:
                    if (e.PageSettings.PrinterSettings.PrintRange == PrintRange.SomePages && _currentPage == 0) {
                        _currentPage = e.PageSettings.PrinterSettings.FromPage - 1;
                    }

                    ScaleReport(e);

                    e.Graphics.DrawString(_pagesToPrint[_currentPage], _printFont, Brushes.Black, e.MarginBounds.X,
                                          e.MarginBounds.Y);

                    _currentPage += 1;

                    ProcessMorePages(e);
                    break;
                   
                case PrintType.Text:
                    e.Graphics.DrawString(_textToPrint, _printFont, Brushes.Black, e.MarginBounds.X,
                                          e.MarginBounds.Y);
                    break;
                   
                case PrintType.Image:
                    Image image = Image.FromStream(_streamToPrint);
                    int x = e.MarginBounds.X;
                    int y = e.MarginBounds.Y;
                    int width = image.Width;
                    int height = image.Height;
                    if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height)) {
                        width = e.MarginBounds.Width;
                        height = image.Height * e.MarginBounds.Width / image.Width;
                    } else {
                        height = e.MarginBounds.Height;
                        width = image.Width * e.MarginBounds.Height / image.Height;
                    }
                   
                    Rectangle destRect = new Rectangle(x, y, width, height);
                    e.Graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);

                    break;
                   
                default:
                    break;
            }
        }

        /// <summary>
        /// Set property HasMorePages for event argument when there is more page to print
        /// </summary>
        /// <param name="e"></param>
        private void ProcessMorePages(PrintPageEventArgs e) {
            bool anyMorePage = (e.PageSettings.PrinterSettings.PrintRange != PrintRange.SomePages &&
                                _currentPage < _pagesToPrint.Count) ||
                               (e.PageSettings.PrinterSettings.PrintRange == PrintRange.SomePages &&
                                _currentPage < e.PageSettings.PrinterSettings.ToPage);
                   
            // Set the true for e.HasMorePages when there any more page waiting for print. Otherwise, set false to it.
            if (anyMorePage) {
                e.HasMorePages = true;
            } else {
                _currentPage = 0;
                e.HasMorePages = false;
            }
        }

        /// <summary>
        /// Scale the report to adapt to the width of paper when it is not enough for the whole repot width
        /// </summary>
        /// <param name="e"></param>
        private void ScaleReport(PrintPageEventArgs e) {
            float widthScale = GetScale(e, true);

            float heightScale = GetScale(e, false);

            e.Graphics.ScaleTransform(widthScale, heightScale);
        }

        private float GetScale(PrintPageEventArgs e, bool isWidth) {
            float scale = 1;
            int paperValue;
            float contentValue;
           
            if (isWidth) {
                paperValue = e.MarginBounds.Width;
                contentValue = (int)e.Graphics.MeasureString(ONE_LINE_REPORT, _printFont).Width;
            } else {
                paperValue = e.MarginBounds.Height;
                contentValue = (int)e.Graphics.MeasureString(ONE_LINE_REPORT, _printFont).Height * _linesPerPage;
            }
           
            // Evaluate the scale
            if ((contentValue > paperValue) && (paperValue > 0)) {
                scale = paperValue / contentValue;

                // Paper value is 'int' and it is not exact. So here to just it advance
                if (scale < 1 - 0.046F) {
                    scale += 0.046F;
                }
            }
           
            return scale;
        }

        // Declare the PrintDocument object.
        private PrintDocument _docToPrint = new PrintDocument();
       
        private PrintType _printType;
        private Font _printFont;

        private int _currentPage = 0;
        private int _linesPerPage;
       
        private IList<string> _pagesToPrint;
        private string _textToPrint;
        private Stream _streamToPrint;

        private static string ONE_LINE_REPORT = "------------------------------------------------------------------------------------------------------------------------------------";
        private static int MINMUM_PAGE = 1;
    }

    public enum PrintType {
        TextPages,
        Text,
        Image
    }
}

  

No comments:

Post a Comment