DataGridView Printer



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

namespace Mesoft.Control
{
    public class DataGridViewPrinter
    {
        private DataGridView TheDataGridView; // The DataGridView Control which will be printed
        private PrintDocument ThePrintDocument; // The PrintDocument to be used for printing
        private bool IsCenterOnPage; // Determine if the report will be printed in the Top-Center of the page
        private bool IsWithTitle; // Determine if the page contain title text
        private string TheTitleText; // The title text to be printed in each page (if IsWithTitle is set to true)
        private Font TheTitleFont; // The font to be used with the title text (if IsWithTitle is set to true)
        private Color TheTitleColor; // The color to be used with the title text (if IsWithTitle is set to true)
        private bool IsWithPaging; // Determine if paging is used
        static int CurrentRow; // A static parameter that keep track on which Row (in the DataGridView control) that should be printed
        static int PageNumber;
        private int PageWidth;
        private int PageHeight;
        private int LeftMargin;
        private int TopMargin;
        private int RightMargin;
        private int BottomMargin;
        private float CurrentY; // A parameter that keep track on the y coordinate of the page, so the next object to be printed will start from this y coordinate
        private float RowHeaderHeight;
        private List RowsHeight;
        private List ColumnsWidth;
        private float TheDataGridViewWidth;
        // Maintain a generic list to hold start/stop points for the column printing
        // This will be used for wrapping in situations where the DataGridView will not fit on a single page
        private List mColumnPoints;
        private List mColumnPointsWidth;
        private int mColumnPoint;
        // The class constructor
        public DataGridViewPrinter(DataGridView aDataGridView, PrintDocument aPrintDocument, bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
        {
            TheDataGridView = aDataGridView;
            ThePrintDocument = aPrintDocument;
            IsCenterOnPage = CenterOnPage;
            IsWithTitle = WithTitle;
            TheTitleText = aTitleText;
            TheTitleFont = aTitleFont;
           TheTitleColor = aTitleColor;
            IsWithPaging = WithPaging;
            PageNumber = 0;
            RowsHeight = new List();
            ColumnsWidth = new List();
            mColumnPoints = new List();
            mColumnPointsWidth = new List();
            // Claculating the PageWidth and the PageHeight
            if (!ThePrintDocument.DefaultPageSettings.Landscape)
            {
                PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width;
                PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height;
            }
            else
            {
                PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width;
                PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height;
            }
            // Claculating the page margins
            LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left;
            TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top;
            RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right;
            BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom;
            // First, the current row to be printed is the first row in the DataGridView control
            CurrentRow = 0;
        }
        // The function that calculate the height of each row (including the header row), the width of each column (according to the longest text in all its cells including the header cell), and the whole DataGridView width
        private void Calculate(Graphics g)
        {
            if (PageNumber == 0) // Just calculate once
            {
                SizeF tmpSize = new SizeF();
                Font tmpFont;
                float tmpWidth;
                TheDataGridViewWidth = 0;
                for (int i = 0; i < TheDataGridView.Columns.Count; i++)
                {
                    tmpFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
                    if (tmpFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
                        tmpFont = TheDataGridView.DefaultCellStyle.Font;
                    tmpSize = g.MeasureString(TheDataGridView.Columns[i].HeaderText, tmpFont);
                    tmpWidth = tmpSize.Width;
                    RowHeaderHeight = tmpSize.Height;
                    for (int j = 0; j < TheDataGridView.Rows.Count; j++)
                    {
                        tmpFont = TheDataGridView.Rows[j].DefaultCellStyle.Font;
                        if (tmpFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control
                           tmpFont = TheDataGridView.DefaultCellStyle.Font;
                        tmpSize = g.MeasureString("Anything", tmpFont);
                        RowsHeight.Add(tmpSize.Height);
                        tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
                        if (tmpSize.Width > tmpWidth)
                            tmpWidth = tmpSize.Width;
                    }
                    if (TheDataGridView.Columns[i].Visible)
                        TheDataGridViewWidth += tmpWidth;
                    ColumnsWidth.Add(tmpWidth);
                }
                // Define the start/stop column points based on the page width and the DataGridView Width
                // We will use this to determine the columns which are drawn on each page and how wrapping will be handled
                // By default, the wrapping will occurr such that the maximum number of columns for a page will be determine
                int k;
                int mStartPoint = 0;
                for (k = 0; k < TheDataGridView.Columns.Count; k++)
                    if (TheDataGridView.Columns[k].Visible)
                    {
                        mStartPoint = k;
                        break;
                    }
                int mEndPoint = TheDataGridView.Columns.Count;
                for (k = TheDataGridView.Columns.Count - 1; k >= 0; k--)
                    if (TheDataGridView.Columns[k].Visible)
                    {
                        mEndPoint = k + 1;
                        break;
                    }
                float mTempWidth = TheDataGridViewWidth;
                float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;
                // We only care about handling where the total datagridview width is bigger then the print area
                if (TheDataGridViewWidth > mTempPrintArea)
                {
                    mTempWidth = 0.0F;
                    for (k = 0; k < TheDataGridView.Columns.Count; k++)
                    {
                        if (TheDataGridView.Columns[k].Visible)
                        {
                           mTempWidth += ColumnsWidth[k];
                            // If the width is bigger than the page area, then define a new column print range
                            if (mTempWidth > mTempPrintArea)
                            {
                               mTempWidth -= ColumnsWidth[k];
                                mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });
                                mColumnPointsWidth.Add(mTempWidth);
                                mStartPoint = k;
                                mTempWidth = ColumnsWidth[k];
                            }
                        }
                        // Our end point is actually one index above the current index
                        mEndPoint = k + 1;
                    }
                }
                // Add the last set of columns
                mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });
                mColumnPointsWidth.Add(mTempWidth);
                mColumnPoint = 0;
            }
        }
        // The funtion that print the title, page number, and the header row
        private void DrawHeader(Graphics g)
        {
            CurrentY = (float)TopMargin;
            // Printing the page number (if isWithPaging is set to true)
            if (IsWithPaging)
            {
                PageNumber++;
                string PageString = "Page " + PageNumber.ToString();
                StringFormat PageStringFormat = new StringFormat();
                PageStringFormat.Trimming = StringTrimming.Word;
                PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                PageStringFormat.Alignment = StringAlignment.Far;
                Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);
                RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);
                g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);
                CurrentY += g.MeasureString(PageString, PageStringFont).Height;
            }
            // Printing the title (if IsWithTitle is set to true)
            if (IsWithTitle)
            {
                StringFormat TitleFormat = new StringFormat();
                TitleFormat.Trimming = StringTrimming.Word;
                TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                if (IsCenterOnPage)
                    TitleFormat.Alignment = StringAlignment.Center;
                else
                    TitleFormat.Alignment = StringAlignment.Near;
                RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(TheTitleText, TheTitleFont).Height);
                g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);
                CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
            }
            // Calculating the starting x coordinate that the printing process will start from
            float CurrentX = (float)LeftMargin;
            if (IsCenterOnPage)
                CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
            // Setting the HeaderFore style
            Color HeaderForeColor = TheDataGridView.ColumnHeadersDefaultCellStyle.ForeColor;
            if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style
                HeaderForeColor = TheDataGridView.DefaultCellStyle.ForeColor;
            SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);
            // Setting the HeaderBack style
            Color HeaderBackColor = TheDataGridView.ColumnHeadersDefaultCellStyle.BackColor;
            if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style
                HeaderBackColor = TheDataGridView.DefaultCellStyle.BackColor;
            SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);
            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen TheLinePen = new Pen(TheDataGridView.GridColor, 1);
            // Setting the HeaderFont style
            Font HeaderFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
            if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
                HeaderFont = TheDataGridView.DefaultCellStyle.Font;
            // Calculating and drawing the HeaderBounds
            RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);
            g.FillRectangle(HeaderBackBrush, HeaderBounds);
            // Setting the format that will be used to print each cell of the header row
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
            // Printing each visible cell of the header row
            RectangleF CellBounds;
            float ColumnWidth;
            for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)
            {
                if (!TheDataGridView.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration
                ColumnWidth = ColumnsWidth[i];
                // Check the CurrentCell alignment and apply it to the CellFormat
                if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
                    CellFormat.Alignment = StringAlignment.Far;
                else if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
                    CellFormat.Alignment = StringAlignment.Center;
                else
                    CellFormat.Alignment = StringAlignment.Near;
                CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
                // Printing the cell text
                g.DrawString(TheDataGridView.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);
                // Drawing the cell bounds
                if (TheDataGridView.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None
                    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
                CurrentX += ColumnWidth;
            }
            CurrentY += RowHeaderHeight;
        }
        // The function that print a bunch of rows that fit in one page
        // When it returns true, meaning that there are more rows still not printed, so another PagePrint action is required
        // When it returns false, meaning that all rows are printed (the CureentRow parameter reaches the last row of the DataGridView control) and no further PagePrint action is required
        private bool DrawRows(Graphics g)
        {
            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen TheLinePen = new Pen(TheDataGridView.GridColor, 1);
            // The style paramters that will be used to print each cell
            Font RowFont;
            Color RowForeColor;
            Color RowBackColor;
            SolidBrush RowForeBrush;
            SolidBrush RowBackBrush;
            SolidBrush RowAlternatingBackBrush;
            // Setting the format that will be used to print each cell
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit;
            // Printing each visible cell
            RectangleF RowBounds;
            float CurrentX;
            float ColumnWidth;
            while (CurrentRow < TheDataGridView.Rows.Count)
            {
                if (TheDataGridView.Rows[CurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible
                {
                    // Setting the row font style
                    RowFont = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font;
                    if (RowFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control
                        RowFont = TheDataGridView.DefaultCellStyle.Font;
                    // Setting the RowFore style
                    RowForeColor = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.ForeColor;
                    if (RowForeColor.IsEmpty) // If the there is no special RowFore style of the CurrentRow, then use the default one associated with the DataGridView control
                        RowForeColor = TheDataGridView.DefaultCellStyle.ForeColor;
                    RowForeBrush = new SolidBrush(RowForeColor); 
                    // Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles
                    RowBackColor = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.BackColor;
                    if (RowBackColor.IsEmpty) // If the there is no special RowBack style of the CurrentRow, then use the default one associated with the DataGridView control
                    {
                        RowBackBrush = new SolidBrush(TheDataGridView.DefaultCellStyle.BackColor);
                        RowAlternatingBackBrush = new SolidBrush(TheDataGridView.AlternatingRowsDefaultCellStyle.BackColor);
                    }
                    else // If the there is a special RowBack style of the CurrentRow, then use it for both the RowBack and the RowAlternatingBack styles
                    {
                        RowBackBrush = new SolidBrush(RowBackColor);
                        RowAlternatingBackBrush = new SolidBrush(RowBackColor);
                    }
                    // Calculating the starting x coordinate that the printing process will start from
                    CurrentX = (float)LeftMargin;
                    if (IsCenterOnPage)
                        CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
                    // Calculating the entire CurrentRow bounds
                    RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);
                    // Filling the back of the CurrentRow
                    if (CurrentRow % 2 == 0)
                        g.FillRectangle(RowBackBrush, RowBounds);
                    else
                        g.FillRectangle(RowAlternatingBackBrush, RowBounds);
                    // Printing each visible cell of the CurrentRow
                    for (int CurrentCell = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)
                    {
                        if (!TheDataGridView.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration
                        // Check the CurrentCell alignment and apply it to the CellFormat
                        if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))
                            CellFormat.Alignment = StringAlignment.Far;
                        else if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))
                            CellFormat.Alignment = StringAlignment.Center;
                        else
                            CellFormat.Alignment = StringAlignment.Near;
                        ColumnWidth = ColumnsWidth[CurrentCell];
                        RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
                        // Printing the cell text
                        g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);
                        // Drawing the cell bounds
                        if (TheDataGridView.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None
                            g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
                        CurrentX += ColumnWidth;
                    }
                    CurrentY += RowsHeight[CurrentRow];
                    // Checking if the CurrentY is exceeds the page boundries
                    // If so then exit the function and returning true meaning another PagePrint action is required
                    if ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))
                    {
                        CurrentRow++;
                        return true;
                    }
                }
                CurrentRow++;
            }
            CurrentRow = 0;
            mColumnPoint++; // Continue to print the next group of columns
            if (mColumnPoint == mColumnPoints.Count) // Which means all columns are printed
            {
                mColumnPoint = 0;
                return false;
            }
            else
                return true;
        }
        // The method that calls all other functions
        public bool DrawDataGridView(Graphics g)
        {
            try
            {
                Calculate(g);
                DrawHeader(g);
                bool bContinue = DrawRows(g);
                return bContinue;
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
                return false;
            }
        }
        //Customize
        private void DrawHeaderNew(Graphics g)
        {
            //CurrentY = (float)PageHeight;
            CurrentY = (float)(PageHeight - BottomMargin);
            // Printing the page number (if isWithPaging is set to true)
            if (IsWithPaging)
            {
                PageNumber++;
                //string PageString = "Page " + PageNumber.ToString();
                string PageString = "©Callahan & Associates, Inc (800-446-7453)";
                StringFormat PageStringFormat = new StringFormat();
                PageStringFormat.Trimming = StringTrimming.Word;
                PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                PageStringFormat.Alignment = StringAlignment.Far;
                Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);
                RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);
                g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);
                CurrentY = (float)TopMargin;
                //CurrentY += g.MeasureString(PageString, PageStringFont).Height;
            }
            // Printing the title (if IsWithTitle is set to true)
            if (IsWithTitle)
            {
                StringFormat TitleFormat = new StringFormat();
                TitleFormat.Trimming = StringTrimming.Word;
                TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                if (IsCenterOnPage)
                    TitleFormat.Alignment = StringAlignment.Center;
                else
                    TitleFormat.Alignment = StringAlignment.Near;
                RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(TheTitleText, TheTitleFont).Height);
                g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);
                CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
            }
            // Calculating the starting x coordinate that the printing process will start from
            float CurrentX = (float)LeftMargin;
            if (IsCenterOnPage)
                CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
            // Setting the HeaderFore style
            Color HeaderForeColor = TheDataGridView.ColumnHeadersDefaultCellStyle.ForeColor;
            if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style
                HeaderForeColor = TheDataGridView.DefaultCellStyle.ForeColor;
            SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);
            // Setting the HeaderBack style
            Color HeaderBackColor = TheDataGridView.ColumnHeadersDefaultCellStyle.BackColor;
            if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style
                HeaderBackColor = TheDataGridView.DefaultCellStyle.BackColor;
            SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);
            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen TheLinePen = new Pen(TheDataGridView.GridColor, 1);
            // Setting the HeaderFont style
            Font HeaderFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
            if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
                HeaderFont = TheDataGridView.DefaultCellStyle.Font;
            // Calculating and drawing the HeaderBounds
            RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);
            g.FillRectangle(HeaderBackBrush, HeaderBounds);
            // Setting the format that will be used to print each cell of the header row
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
            // Printing each visible cell of the header row
            RectangleF CellBounds;
            float ColumnWidth;
            for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)
            {
                if (!TheDataGridView.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration
                ColumnWidth = ColumnsWidth[i];
                // Check the CurrentCell alignment and apply it to the CellFormat
                if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
                    CellFormat.Alignment = StringAlignment.Far;
                else if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
                    CellFormat.Alignment = StringAlignment.Center;
                else
                    CellFormat.Alignment = StringAlignment.Near;
                CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
                // Printing the cell text
                g.DrawString(TheDataGridView.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);
                // Drawing the cell bounds
                if (TheDataGridView.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None
                    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
                CurrentX += ColumnWidth;
            }
            CurrentY += RowHeaderHeight;
        }
        public bool DrawDataGridViewNew(Graphics g)
        {
            try
            {
                Calculate(g);
                DrawHeaderNew(g);
                bool bContinue = DrawRows(g);
                return bContinue;
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
                return false;
            }
        }
    }
}
/**************************************************************
* IMPLEMENT THIS CODE AS PER BELOW
***************************************************************/
//Setting For The Printer
private bool fnc_SetupThePrinting()
{
    try
    {
        PrintDialog MyPrintDialog = new PrintDialog();
        MyPrintDialog.AllowCurrentPage = false;
        MyPrintDialog.AllowPrintToFile = false;
        MyPrintDialog.AllowSelection = false;
        MyPrintDialog.AllowSomePages = false;
        MyPrintDialog.PrintToFile = false;
        MyPrintDialog.ShowHelp = false;
        MyPrintDialog.ShowNetwork = false;
        if (MyPrintDialog.ShowDialog() != DialogResult.OK)
        return false;
        MyPrintDocument.DocumentName = this.Text;
        MyPrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
        MyPrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
        MyPrintDocument.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40);
        MyDataGridViewPrinter = new DataGridViewPrinter(dgvView, MyPrintDocument, false, true, this.Text, new Font("Tahoma", 12, FontStyle.Bold, GraphicsUnit.Point), Color.Black, true);
        return true;
    }
    catch (Exception ex)
    {
        objGL.pro_ErrorMessage(ex);
        return false;
    }
}
//Print Button Click event
private void btnPrint_Click(object sender, EventArgs e)
{
    try
    {
    // For Print Preview
    if (fnc_SetupThePrinting())
    {
       PrintPreviewDialog MyPrintPreviewDialog = new PrintPreviewDialog();
        MyPrintPreviewDialog.Document = MyPrintDocument;
        MyPrintPreviewDialog.ShowDialog();
    }
    }
    catch (Exception ex)
    {
        objGL.pro_ErrorMessage(ex);
    }

Watermark Textbox with Email & number validation




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace Mesoft.Control
{
    public partial class MeTextBox : TextBox
    {
        private string MeTempText = "";
        private Boolean IsNum = false;
        private Boolean IsEmail = false;

        public MeTextBox()
        {
            TextWithWaterMark = false;
            this.Size = new System.Drawing.Size(169, 20);
            this.TextChanged += new System.EventHandler(this.meText_TextChanged);
            this.Leave += new System.EventHandler(this.meText_Leave);
            this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.meText_KeyPress);
            this.Enter += new System.EventHandler(this.meText_Enter);
            this.Validating += new CancelEventHandler(meText_Validating);
        }
        #region "CUSTOME PROPERTIES"
        [Category("Mesoft")]
        [Description("get or set watermark text")]
        public String WaterMarkText
        {
            get
            {
                return MeTempText;
            }
            set
            {
                MeTempText = value;
                this.Text = MeTempText;
                SetTextColor();
            }
        }
        [Category("Mesoft")]
        public new string Text
        {
            get
            {
                if (!TextWithWaterMark)
                {
                    if (base.Text == WaterMarkText)
                    {
                        return "";
                    }
                    else
                    {
                        return base.Text;
                    }
                }
                else
                {
                    return base.Text;
                }
            }
            set
            {
                base.Text = value;
            }
        }
        [Category("Mesoft")]
        public String TextWithNull
        {
            get
            {
                if (this.Text == WaterMarkText)
                {
                    return "NULL";
                }
                else
                {
                    return Text;
                }
            }
        }
        [Category("Mesoft")]
        [Description("set true metextbox as numbertextbox")]
        public Boolean NumberTextBox
        {
            get
            {
                return IsNum;
            }
            set
            {
                IsNum = value;
                if (IsNum)
                {
                    IsEmail = false;
                }
            }
        }
        [Category("Mesoft")]
        [Description("set true metextbox email validate textbox")]
        public Boolean EmailTextBox
        {
            get
            {
                return IsEmail;
            }
            set
            {
                IsEmail = value;
                if (IsEmail)
                {
                    IsNum = false;
                }
            }
        }
        [Category("Mesoft")]
        [Description("If you want return text with watermark also make it true.")]
        public Boolean TextWithWaterMark
        {
            get;
            set;
        }
        #endregion
        #region "CUSTOME METHOD"
        private void SetTextColor()
        {
            try
            {
                string temp = this.Text;
                if (temp == "")
                {
                    temp = WaterMarkText;
                }
                if (temp == WaterMarkText)
                {
                    this.ForeColor = Color.Silver;
                }
                else
                {
                    this.ForeColor = Color.Black;
                }
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
            }
        }
        protected override void OnCreateControl()
        {
            base.OnCreateControl();
        }
        public new void Clear()
        {
            this.Text = WaterMarkText;
        }
        #endregion
        #region "EVETN"
        private void meText_TextChanged(object sender, EventArgs e)
        {
            try
            {
                SetTextColor();
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
            }
        }
        private void meText_Enter(object sender, EventArgs e)
        {
            try
            {
                string temp = this.Text;
                if (temp == "")
                {
                    temp = WaterMarkText;
                }
                if (temp == WaterMarkText)
                {
                    this.Text = "";
                }
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
            }
        }
        private void meText_Leave(object sender, EventArgs e)
        {
            try
            {
                if (this.Text == "")
                {
                    this.Text = WaterMarkText;
                }
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
            }
        }
        private void meText_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
               if (NumberTextBox)
                {
                    if (!char.IsNumber(e.KeyChar) && e.KeyChar != '.' && e.KeyChar != '\b')
                    {
                        e.Handled = true;
                    }
                }
            }
            catch (Exception ex)
            {
                General.ErrorMessage(ex.Message);
            }
        }
        private void meText_Validating(object sender, CancelEventArgs e)
        {
            try
            {
                if (IsEmail)
                {
                    if (this.Text != "" && this.Text != WaterMarkText)
                    {
                        Mesoft.Extra.Validation ObjVal = new Mesoft.Extra.Validation();
                        ObjVal.IsValidationEmail(this.Text);
                    }
                }
            }
            catch (Exception ex)
            {
                e.Cancel = true;
                General.ErrorMessage(ex.Message);
            }
        }
        #endregion
    }
}

Time Column For DataGridView



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Mesoft.Control
{
    using System.Windows.Forms;
    public class TimeColumn : DataGridViewColumn
    {
        public TimeColumn()
            : base(new TimeCell())
        { 
        }
        public TimeColumn(string frm)
            : base(new TimeCell(frm))
        {
        }
        public void setValue(string frm)
        {
            base.CellTemplate.Value = frm;
        }
        [Category("Mesoft")]
        public override DataGridViewCell CellTemplate
        {
            get
            {
                return base.CellTemplate;
            }
            set
            {
                if (value != null && !value.GetType().IsAssignableFrom(typeof(TimeCell)))
                {
                    throw new InvalidCastException("Must be a TimeCell");
                }
                base.CellTemplate = value;
            }
        }
    }
    public class TimeCell : DataGridViewTextBoxCell
    {
        public TimeCell()
            : base()
        {
            this.Style.Format = "hh:mm tt";
        }
        public TimeCell(string frm)
            : base()
        {
            this.Style.Format = frm;
        }
        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
        {
            try
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
                TimeEditingControl ctl = DataGridView.EditingControl as TimeEditingControl;
                ctl.Format = DateTimePickerFormat.Time;
                ctl.ShowUpDown = true;
                ctl.Value = (DateTime)this.Value;
            }
            catch { }
        }
        [Category("Mesoft")]
        public override Type EditType
        {
            get
            {
                return typeof(TimeEditingControl);
            }
        }
        [Category("Mesoft")]
        public override Type ValueType
        {
            get
            {
                return typeof(DateTime);
            }
        }
        [Category("Mesoft")]
        public override object DefaultNewRowValue
        {
            get
            {
                return DateTime.Now;
            }
        }
    }
    class TimeEditingControl : DateTimePicker, IDataGridViewEditingControl
    {
        DataGridView dataGridView;
        private bool valueChanged = false;
        int rowIndex;
        public TimeEditingControl()
        {
            this.Format = DateTimePickerFormat.Custom;
        }
        [Category("Mesoft")]
        public object EditingControlFormattedValue
        {
            get
            {
                return this.Value.ToShortTimeString();
            }
            set
            {
                String newValue = value as String;
                if (newValue != null)
                {
                    this.Value = DateTime.Parse(newValue);
                }
            }
        }
        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }
        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
        }
        [Category("Mesoft")]
        public int EditingControlRowIndex
        {
            get
            {
                return rowIndex;
            }
            set
            {
               rowIndex = value;
            }
        }
        public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
        {
            switch (key & Keys.KeyCode)
            {
                case Keys.Left:
               case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.PageDown:
                case Keys.PageUp:
                case Keys.Tab:
                    return true;
                default:
                    return false;
            }
        }
        public void PrepareEditingControlForEdit(bool selectAll){}
        [Category("Mesoft")]
        public bool RepositionEditingControlOnValueChange
        {
            get
            {
                return false;
            }
        }
        [Category("Mesoft")]
        public DataGridView EditingControlDataGridView
        {
            get
            {
               return dataGridView;
            }
            set
            {
                dataGridView = value;
           }
        }
        [Category("Mesoft")]
       public bool EditingControlValueChanged
       {
            get
            {
                return valueChanged;
            }
            set
            {
                valueChanged = value;
            }
        }
        [Category("Mesoft")]
        public Cursor EditingPanelCursor
        {
            get
            {
                return base.Cursor;
            }
        }
        protected override void OnValueChanged(EventArgs eventargs)
        {
            valueChanged = true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnValueChanged(eventargs);
        }
    }
}

CalenderColumn For DataGridView





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace Mesoft.Control
{
    public class CalendarColumn : DataGridViewColumn
    {
        public CalendarColumn() : base(new CalendarCell())
        {
        }
        public override DataGridViewCell CellTemplate
        {
            get
            {
                return base.CellTemplate;
            }
            set
           {
                if (value != null && !value.GetType().IsAssignableFrom(typeof(CalendarCell)))
                {
                    throw new InvalidCastException("Must be a CalendarCell");
                }
                base.CellTemplate = value;
            }
        }
    }
    public class CalendarCell : DataGridViewTextBoxCell
    {
        public CalendarCell(): base()
        {
            this.Style.Format = "d";
        }
        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
        {
            base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);
            CalendarEditingControl ctl =
            DataGridView.EditingControl as CalendarEditingControl;
            ctl.Value = (DateTime)this.Value;
        }
        public override Type EditType
        {
            get
            {
                return typeof(CalendarEditingControl);
            }
        }
        public override Type ValueType
        {
            get
            {
                return typeof(DateTime);
            }
        }
        public override object DefaultNewRowValue
        {
            get
            {
                return DateTime.Now;
            }
        }
    }
    class CalendarEditingControl : DateTimePicker, IDataGridViewEditingControl
    {
        DataGridView dataGridView;
        private bool valueChanged = false;
        int rowIndex;
        public CalendarEditingControl()
        {
            this.Format = DateTimePickerFormat.Short;
        }
        [Category("Mesoft")]
        public object EditingControlFormattedValue
        {
            get
            {
                return this.Value.ToShortDateString();
            }
            set
            {
                if (value is String)
                {
                    this.Value = DateTime.Parse((String)value);
                }
            }
        }
        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }
        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
            this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
            this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
        }
        [Category("Mesoft")]
        public int EditingControlRowIndex
        {
            get
            {
                return rowIndex;
            }
            set
            {
                rowIndex = value;
            }
        }
        public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
        {
            switch (key & Keys.KeyCode)
            {
                case Keys.Left:
                case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.PageDown:
                case Keys.PageUp:
                    return true;
                default:
                    return false;
            }
        }
        public void PrepareEditingControlForEdit(bool selectAll)
        {
        }
        [Category("Mesoft")]
        public bool RepositionEditingControlOnValueChange
        {
            get
            {
                return false;
            }
        }
        [Category("Mesoft")]
        public DataGridView EditingControlDataGridView
        {
            get
            {
                return dataGridView;
            }
            set
            {
                dataGridView = value;
            }
        }
        [Category("Mesoft")]
        public bool EditingControlValueChanged
        {
            get
            {
                return valueChanged;
            }
            set
            {
                valueChanged = value;
            }
        }
        [Category("Mesoft")]
        public Cursor EditingPanelCursor
        {
            get
            {
                return base.Cursor;
            }
        }
        protected override void OnValueChanged(EventArgs eventargs)
        {
            valueChanged = true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnValueChanged(eventargs);
        }
    }
}

Customize TitleBar





using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesoft.Control
{
    public partial class TitleBar : UserControl
    {
        public const int WM_NCLBUTTONDOWN = 0xA1;
        public const int HT_CAPTION = 0x2;
        [DllImportAttribute("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd,int Msg, int wParam, int lParam);
        [DllImportAttribute("user32.dll")]
        public static extern bool ReleaseCapture();
        public TitleBar()
        {
            InitializeComponent();
        }
        private void TitleBar_Load(object sender, EventArgs e)
        {
            this.Dock = DockStyle.Top;
            lblTitle.ForeColor = Color.White;
            this.SendToBack();
            this.lblTitle.Font = new System.Drawing.Font("Calibri", 11.25F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        }
        private void pbTitle_MouseDown(object sender, MouseEventArgs e)
        {
        }
        private void pbTitle_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (frmControlBox.Maximize)
            {
                if (this.ParentForm.WindowState == FormWindowState.Maximized)
                {
                    this.ParentForm.WindowState = FormWindowState.Normal;
                    this.ParentForm.Show();
                }
                else if (this.ParentForm.WindowState == FormWindowState.Normal)
                {
                    this.ParentForm.WindowState = FormWindowState.Maximized;
                    this.ParentForm.Show();
                }
            }
        }
        private void Caption_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if ((e.Clicks == 1) && (this.ParentForm.WindowState != FormWindowState.Maximized))
                {
                    ReleaseCapture();
                    SendMessage(this.ParentForm.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                }
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets the font of the title")
        public Font TitleFont
        {
            set
            {
                lblTitle.Font = value;
            }
            get
            {
                return lblTitle.Font;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets the title of the title bar")]
        public string Titl
        {
            set
            {
                lblTitle.Text = value;
            }
            get
            {
                return lblTitle.Text;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets the title align")]
        public ContentAlignment TitleTextAlign
        {
            set
            {
              lblTitle.TextAlign = value;
            }
            get
            {
                return lblTitle.TextAlign
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets the title text color")]
        public Color TitleForeColor
        {
            set
            {
                lblTitle.ForeColor = value;
            }
            get
            {
                return lblTitle.ForeColor;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets the title background color")]
        [DisplayName("TitleColor")]
        public Color TitleBackColor
        {
            set
            {
                lblTitle.BackColor = value;
            }
            get
            {
                return lblTitle.BackColor;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets maximize button visibility")]
        public bool Maximize
        {
            set
            {
                frmControlBox.Maximize = value;
            }
            get
            {
                return frmControlBox.Maximize;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets minimize button visibility")]
        public bool Minimize
        {
            set
            {
               frmControlBox.Minimize = value;
            }
            get
            {
                return frmControlBox.Minimize;
            }
        }
        [Category("Mesoft")]
        [Description("Gets or sets close button visibility")]
        public bool Close
        {
            set
            {
                frmControlBox.Close = value;
            }
            get
            {
                return frmControlBox.Close;
            }
        }
        private void lblTitle_DoubleClick(object sender, EventArgs e)
        {
            if (frmControlBox.Maximize)
            {
                if (this.ParentForm.WindowState == FormWindowState.Maximized)
                {
                    this.ParentForm.WindowState = FormWindowState.Normal;
                    this.ParentForm.Show();
                }
                else if (this.ParentForm.WindowState == FormWindowState.Normal)
                {
                    this.ParentForm.WindowState = FormWindowState.Maximized;
                    this.ParentForm.Show();
                }
            }
        }
    }
}