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;
using System.Diagnostics;
// This module contains two classes
// #1: 'VVX.DGVPrinter': Adapted from "The DataGridViewPrinter Class", By Salan Al-Ani.
// See http://www.codeproject.com/csharp/datagridviewprinter.asp
// #2: 'VVX.Print': My own VVX.Print "wrapper"
namespace VVX
{
#region DGVPrinter
/// <summary>
/// This is a renamed, refactored and slightly modified version of DataGridViewPrinter
/// originally created by Salan Al-Ani and downloaded from CodeProject (around Mar 10,2007)
/// </summary>
class DGVPrinter
{
private string mNameOfClient = "Unknown";
// The PrintDocument to be used for printing.
PrintDocument mPrintDoc;
PrintDialog mPrintDlg;
Margins mPageMargins = new Margins(0, 0, 0, 0);
Margins mCellMargins = new Margins(2, 2, 2, 2);
private DataGridView mTheDataGridView; // The DataGridView Control which will be printed
private PrintDocument mThePrintDocument; // The PrintDocument to be used for printing
private bool mIsCenterOnPage; // Determine if the report will be printed in the Top-Center of the page
private bool mIsWithTitle; // Determine if the page contain title text
private string mTheTitleText; // The title text to be printed in each page (if IsWithTitle is set to true)
private Font mTheTitleFont; // The font to be used with the title text (if IsWithTitle is set to true)
private Color mTheTitleColor; // The color to be used with the title text (if IsWithTitle is set to true)
private bool mIsWithPaging; // Determine if paging is used
private bool mIsWithColHeaders = true; // Determines if header is printed
private int mPageNumber; //was static
private int mCurrentRow; // A static parameter that keep track on which Row (in the DataGridView control) that should be printed
private float mCurrentY; // 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 int mPageWidth;
private int mPageHeight;
private float mColHeaderHeight;
private List<float> mRowHeight;
private List<float> mColumnWidthPadded;
private float mTheDataGridViewWidth;
private float mColumnWidthMin = 0.0f; //in in 1/100th inches
private float mColumnWidthMax = 300.0f; //in in 1/100th inches
// 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<int[]> mColumnRange;
private List<float> mColumnRangeWidth;
private int mColumnRangeCur;
//*****************************************************************************
// Properties
//*****************************************************************************
/// <summary>
/// This is used to set PrintDocument.Name (not the printed Title)
/// </summary>
public string NameOfClient
{
get { return mNameOfClient; }
set { mNameOfClient = value; }
}
/// <summary>
/// Max column width in inches
/// </summary>
public float ColumnWidthMax
{
get { return mColumnWidthMax/100f; }
set { mColumnWidthMax = value*100f; }
}
/// <summary>
/// Min column width in inches
/// </summary>
public float ColumnWidthMin
{
get { return mColumnWidthMin / 100f; }
set { mColumnWidthMin = value * 100f; }
}
public Margins PageMargins
{
get { return mPageMargins; }
set { mPageMargins = value; }
}
public string PageTitle
{
get { return mTheTitleText; }
set { mTheTitleText = value; }
}
public Font PageTitleFont
{
get { return mTheTitleFont; }
set { mTheTitleFont = value; }
}
public Color PageTitleColor
{
get { return mTheTitleColor; }
set { mTheTitleColor = value; }
}
public Margins CellMargins
{
get { return mCellMargins; }
set { mCellMargins = value; }
}
public bool ShowPageNumbers
{
get { return mIsWithPaging; }
set { mIsWithPaging = value; }
}
public bool HorizontallyCenterOnPage
{
get { return mIsCenterOnPage; }
set { mIsCenterOnPage = value; }
}
//*****************************************************************************
// The class constructor
//*****************************************************************************
public DGVPrinter(DataGridView aDataGridView)
{
mTheDataGridView = aDataGridView;
//bool mbCenterOnPage = true; //MsgBox.Confirm("Center on the page?");
//bool mTitleShow = true;
//string mTitleText = "Customers";
//Font mTitleFont = new Font("Tahoma", 18, FontStyle.Bold, GraphicsUnit.Point);
//Color mTitleColor = Color.Black;
//bool mPagingEnabled = true;
mIsCenterOnPage = true;
mIsWithTitle = true;
mTheTitleText = "Customers";
mTheTitleFont = new Font("Tahoma", 12, FontStyle.Bold, GraphicsUnit.Point);
mTheTitleColor = Color.Black;
mIsWithPaging = true;
DoInit();
}
public DGVPrinter(DataGridView aDataGridView
, PrintDocument aPrintDocument
, bool CenterOnPage
, bool WithTitle
, string aTitleText
, Font aTitleFont
, Color aTitleColor
, bool WithPaging)
{
mTheDataGridView = aDataGridView;
mThePrintDocument = aPrintDocument;
mIsCenterOnPage = CenterOnPage;
mIsWithTitle = WithTitle;
mTheTitleText = aTitleText;
mTheTitleFont = aTitleFont;
mTheTitleColor = aTitleColor;
mIsWithPaging = WithPaging;
DoInit();
}
//*****************************************************************************
// The class constructor helper
//*****************************************************************************
private void DoInit()
{
if (mPrintDoc == null)
{
this.mPrintDoc = new PrintDocument();
this.mPrintDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.OnPrintPage);
}
mThePrintDocument = this.mPrintDoc;
mPageNumber = 0;
mRowHeight = new List<float>();
mColumnWidthPadded = new List<float>();
mColumnRange = new List<int[]>();
mColumnRangeWidth = new List<float>();
// Calculating the PageWidth and the PageHeight
if (!mThePrintDocument.DefaultPageSettings.Landscape)
{
mPageWidth = mThePrintDocument.DefaultPageSettings.PaperSize.Width;
mPageHeight = mThePrintDocument.DefaultPageSettings.PaperSize.Height;
}
else
{
mPageHeight = mThePrintDocument.DefaultPageSettings.PaperSize.Width;
mPageWidth = mThePrintDocument.DefaultPageSettings.PaperSize.Height;
}
//--- Calculate the page margins
//this.mPageMargins = mThePrintDocument.DefaultPageSettings.Margins;
// Set current row to be printed is the first row in the DataGridView control
mCurrentRow = 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 (mPageNumber == 0) // Just calculate once
{
mColHeaderHeight = 0;
mTheDataGridViewWidth = 0;
//----------------------------------------------------------------
// loop through all the COLUMNS
//----------------------------------------------------------------
bool bSaveRowHeight = true;
for (int iCol = 0; iCol < mTheDataGridView.Columns.Count; iCol++)
{
if (mTheDataGridView.Columns[iCol].Visible == false)
continue;
float colWidth = 0;
//----------------------------------------------------------------
// first do calc for the HEADER
//----------------------------------------------------------------
if(this.mIsWithColHeaders)
{
Font hdrFont;
SizeF hdrSize = new SizeF();
// get the header font
hdrFont = mTheDataGridView.ColumnHeadersDefaultCellStyle.Font;
if (hdrFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
hdrFont = mTheDataGridView.DefaultCellStyle.Font;
//--- get the header size
hdrSize = g.MeasureString(mTheDataGridView.Columns[iCol].HeaderText, hdrFont);
hdrSize.Width += this.mCellMargins.Left + this.mCellMargins.Right;
hdrSize.Height += this.mCellMargins.Top + this.mCellMargins.Bottom;
//--- the column should be at least as wide as the header (incl padding)
colWidth = hdrSize.Width;
if (mColHeaderHeight < hdrSize.Height)
mColHeaderHeight = hdrSize.Height;
}
//----------------------------------------------------------------
// then do calc for the ROWS
//----------------------------------------------------------------
//--- loop through all the ROWS in the current COLUMN
for (int jRow = 0; jRow < mTheDataGridView.Rows.Count; jRow++)
{
Font rowFont;
SizeF cellSize;// = new SizeF();
//--- get the CELL font
rowFont = mTheDataGridView.Rows[jRow].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 = mTheDataGridView.DefaultCellStyle.Font;
//--- set the height of the row
// (for now, only use the first column)
if (bSaveRowHeight)
{
cellSize = g.MeasureString("Anything", rowFont);
float rowHt = cellSize.Height
+ this.mCellMargins.Top + this.mCellMargins.Bottom;
mRowHeight.Add(rowHt);
}
//--- set the width of the column
string cellValue = mTheDataGridView[iCol,jRow].EditedFormattedValue.ToString();
//cellValue = mTheDataGridView.Rows[jRow].Cells[iCol].EditedFormattedValue.ToString();
cellSize = g.MeasureString(cellValue, rowFont);
if (colWidth < cellSize.Width)
colWidth = cellSize.Width;
}
//--- now save the width of the column
//if (mTheDataGridView.Columns[iCol].Visible)
// mTheDataGridViewWidth += colWidth;
colWidth += this.mCellMargins.Left + this.mCellMargins.Right;
//--- test for min
if (colWidth < mColumnWidthMin && mColumnWidthMin > 0)
colWidth = mColumnWidthMin;
//--- test for max
if (mColumnWidthMax > 0)
{
if (colWidth > mColumnWidthMax)
colWidth = mColumnWidthMax;
}
else
{
float maxPrintableWidth = this.DoGetPrintableWidth()
- this.mTheDataGridViewWidth - 1;
if (colWidth > maxPrintableWidth)
colWidth = maxPrintableWidth;
}
mTheDataGridViewWidth += colWidth;
mColumnWidthPadded.Add(colWidth);
if (mRowHeight.Count > 0)
{
// assuming all cells in row are same height
bSaveRowHeight = false;
}
}
//----------------------------------------------------------------
// 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 col;
int colStart = 0;
for (col = 0; col < mTheDataGridView.Columns.Count; col++)
{
if (mTheDataGridView.Columns[col].Visible)
{
colStart = col;
break;
}
}
int colEnd = mTheDataGridView.Columns.Count;
for (col = mTheDataGridView.Columns.Count - 1; col >= 0; col--)
{
if (mTheDataGridView.Columns[col].Visible)
{
colEnd = col + 1;
break;
}
}
float pageWidthUsed = 0f;
float pagePrintableWidth = this.DoGetPrintableWidth();
for (col = 0; col < mTheDataGridView.Columns.Count; col++)
{
if (mTheDataGridView.Columns[col].Visible)
{
pageWidthUsed += mColumnWidthPadded[col];
// If the width is bigger than the page area,
// then define a new column print range
if (pageWidthUsed > pagePrintableWidth)
{
pageWidthUsed -= mColumnWidthPadded[col];
mColumnRange.Add(new int[] { colStart, colEnd });
mColumnRangeWidth.Add(pageWidthUsed);
colStart = col;
pageWidthUsed = mColumnWidthPadded[col];
}
}
// Our end point is actually one index above the current index
colEnd = col + 1;
}
// Add the last set of columns
mColumnRange.Add(new int[] { colStart, colEnd });
mColumnRangeWidth.Add(pageWidthUsed);
mColumnRangeCur = 0;
}
#if !true
{
int n;
string sMsg = "";
for (n = 0; n < this.mColumnRangeWidth.Count; n++)
{
sMsg = String.Format("n={0}\t Width={1}", n, this.mColumnRangeWidth[n]);
Debug.WriteLine(sMsg);
}
for (n = 0; n < this.mColumnWidthPadded.Count; n++)
{
sMsg = String.Format("n={0}\t Width={1}", n, this.mColumnWidthPadded[n]);
Debug.WriteLine(sMsg);
}
}
#endif
}
//*****************************************************************************
// Helper function
//*****************************************************************************
private int DoGetPrintableWidth()
{
int pagePrintWidth = this.mPageWidth
- this.mPageMargins.Left
- this.mPageMargins.Right;
return pagePrintWidth;
}
//*****************************************************************************
// Helper function
//*****************************************************************************
private int DoGetPrintableHeight()
{
int pagePrintHeight = this.mPageHeight
- this.mPageMargins.Top
- this.mPageMargins.Bottom;
return pagePrintHeight;
}
//*****************************************************************************
// The funtion that prints the page number
//*****************************************************************************
private void DrawPageNumber(Graphics g)
{
//mCurrentY = (float)this.mPageMargins.Top;
float pagePrintWidth = this.DoGetPrintableWidth();
//-------------------------------------------------------------
// Printing the page number (if isWithPaging is set to true)
//-------------------------------------------------------------
if (mIsWithPaging)
{
mPageNumber++;
string pageString = "Page " + mPageNumber.ToString();
StringFormat pageStringFormat = new StringFormat();
pageStringFormat.Trimming = StringTrimming.Word;
pageStringFormat.FormatFlags = StringFormatFlags.NoWrap
| StringFormatFlags.LineLimit
| StringFormatFlags.NoClip;
//pageStringFormat.Alignment = StringAlignment.Far;
pageStringFormat.Alignment = StringAlignment.Center;
Font pageStringFont = new Font("Tahoma", 8
, FontStyle.Regular
, GraphicsUnit.Point);
float pagePageStringHeight = g.MeasureString(pageString, pageStringFont).Height;
float pageNumberX = (float)this.mPageMargins.Left;
float pageNumberY = 0;
bool bPrintAtBottom = true;
if (bPrintAtBottom)
{
pageNumberY = this.mPageHeight - this.mPageMargins.Bottom;
pageNumberY += pagePageStringHeight;
}
else
{
pageNumberY = this.mPageMargins.Top;
pageNumberY -= pagePageStringHeight;
}
RectangleF pagePrintArea = new RectangleF(pageNumberX, pageNumberY,
pagePrintWidth, pagePageStringHeight);
g.DrawString(pageString, pageStringFont, new SolidBrush(Color.DarkGray)
, pagePrintArea, pageStringFormat);
//mCurrentY += g.MeasureString(pageString, pageStringFont).Height;
}
}
//*****************************************************************************
// The funtion that prints the title
//*****************************************************************************
private void DrawPageTitle(Graphics g)
{
float pagePrintWidth = this.DoGetPrintableWidth();
if (mIsWithTitle)
{
StringFormat titleFormat = new StringFormat();
titleFormat.Trimming = StringTrimming.Word;
titleFormat.FormatFlags = StringFormatFlags.NoWrap
| StringFormatFlags.LineLimit
| StringFormatFlags.NoClip;
float titleHt = g.MeasureString(mTheTitleText, mTheTitleFont).Height;
float titleX = (float)this.mPageMargins.Left;
float titleY = this.mPageMargins.Top
- titleHt * 1.8f;
if (mIsCenterOnPage)
{
titleFormat.Alignment = StringAlignment.Center; //HCenter
//titleFormat.LineAlignment = StringAlignment.Near;
}
else
{
titleFormat.Alignment = StringAlignment.Near; //Left
//titleFormat.LineAlignment = StringAlignment.Near;
}
RectangleF titleRectangle = new RectangleF(titleX, titleY,
pagePrintWidth, titleHt);
g.DrawString(mTheTitleText, mTheTitleFont, new SolidBrush(mTheTitleColor)
, titleRectangle, titleFormat);
}
}
//*****************************************************************************
// The funtion that prints the title, page number, and the header row
//*****************************************************************************
private void DrawHeader(Graphics g)
{
mCurrentY = (float)this.mPageMargins.Top;
float pagePrintWidth = this.DoGetPrintableWidth();
//-------------------------------------------------------------
// Printing the page number (if isWithPaging is set to true)
//-------------------------------------------------------------
#if false
if (mIsWithPaging)
{
mPageNumber++;
string pageString = "Page " + mPageNumber.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);
float pagePageStringHeight = g.MeasureString(pageString, pageStringFont).Height;
RectangleF pagePrintArea = new RectangleF((float)this.mPageMargins.Left, mCurrentY,
pagePrintWidth, pagePageStringHeight);
g.DrawString(pageString, pageStringFont, new SolidBrush(Color.Black), pagePrintArea, pageStringFormat);
//mCurrentY += g.MeasureString(pageString, pageStringFont).Height;
}
//-------------------------------------------------------------
// Printing the title (if mIsWithTitle is set to true)
//-------------------------------------------------------------
if (mIsWithTitle)
{
StringFormat titleFormat = new StringFormat();
titleFormat.Trimming = StringTrimming.Word;
titleFormat.FormatFlags = StringFormatFlags.NoWrap
| StringFormatFlags.LineLimit
| StringFormatFlags.NoClip;
if (mIsCenterOnPage)
titleFormat.Alignment = StringAlignment.Center;
else
titleFormat.Alignment = StringAlignment.Near;
float titleHt = g.MeasureString(mTheTitleText, mTheTitleFont).Height;
RectangleF titleRectangle
= new RectangleF((float)this.mPageMargins.Left, mCurrentY,
pagePrintWidth, titleHt);
g.DrawString(mTheTitleText, mTheTitleFont, new SolidBrush(mTheTitleColor)
, titleRectangle, titleFormat);
mCurrentY += g.MeasureString(mTheTitleText, mTheTitleFont).Height;
}
#endif
//-------------------------------------------------------------
// printing the header itself
//-------------------------------------------------------------
if(mIsWithColHeaders)
{
// --- Setting the HeaderFore style
Color headerForeColor = mTheDataGridView.ColumnHeadersDefaultCellStyle.ForeColor;
if (headerForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style
headerForeColor = mTheDataGridView.DefaultCellStyle.ForeColor;
SolidBrush headerForeBrush = new SolidBrush(headerForeColor);
// --- Setting the HeaderBack style
Color headerBackColor = mTheDataGridView.ColumnHeadersDefaultCellStyle.BackColor;
if (headerBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style
headerBackColor = mTheDataGridView.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(mTheDataGridView.GridColor, 1);
// --- Setting the HeaderFont style
Font headerFont = mTheDataGridView.ColumnHeadersDefaultCellStyle.Font;
if (headerFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
headerFont = mTheDataGridView.DefaultCellStyle.Font;
//-------------------------------------------------------------
// Calculating and drawing the HeaderBounds
//-------------------------------------------------------------
// --- Calculating the starting x coordinate that the printing process
// will start from
float currentX = (float)this.mPageMargins.Left;
float colRangeWidth = mColumnRangeWidth[mColumnRangeCur];
if (mIsCenterOnPage)
{
currentX += (pagePrintWidth - colRangeWidth) / 2.0F;
}
//--- fill the background of the header area
RectangleF headerBounds = new RectangleF(currentX, mCurrentY,
colRangeWidth, mColHeaderHeight);
//headerBounds.Inflate(this.mCellMargins.Left, this.mCellMargins.Top);
g.FillRectangle(headerBackBrush, headerBounds);
//--- Set 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;
//--- Print each visible cell of the header row
RectangleF cellBounds;
float columnWidth;
for (int iCol = (int)mColumnRange[mColumnRangeCur].GetValue(0);
iCol < (int)mColumnRange[mColumnRangeCur].GetValue(1);
iCol++)
{
if (!mTheDataGridView.Columns[iCol].Visible)
continue; // If the column is not visible then ignore this iteration
columnWidth = mColumnWidthPadded[iCol];
//--- Check the CurrentCell alignment and apply it to the CellFormat
if (mTheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
cellFormat.Alignment = StringAlignment.Far;
else if (mTheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
cellFormat.Alignment = StringAlignment.Center;
else
cellFormat.Alignment = StringAlignment.Near;
//--- set the bounding rectangle for the header cell
cellBounds = new RectangleF(currentX, mCurrentY,
columnWidth, mColHeaderHeight);
cellBounds.Offset(this.mCellMargins.Left, this.mCellMargins.Top);
// Printing the cell text
g.DrawString(mTheDataGridView.Columns[iCol].HeaderText, headerFont
, headerForeBrush, cellBounds, cellFormat);
// Drawing the cell bounds
// only if the HeaderBorderStyle is not None
if (mTheDataGridView.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None)
{
g.DrawRectangle(theLinePen, currentX, mCurrentY,
columnWidth, mColHeaderHeight);
}
currentX += columnWidth;
}
mCurrentY += mColHeaderHeight;
}
}
//*****************************************************************************
// 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 mCurrentRow
// parameter reaches the last row of the DataGridView control) and no further
// PagePrint action is required
//*****************************************************************************
private bool DrawRows(Graphics g)
{
//--- Set the LinePen that will be used to draw lines and rectangles
// (derived from the GridColor property of the DataGridView control)
Pen theLinePen = new Pen(mTheDataGridView.GridColor, 1);
//--- Set the style parameters that will be used to print each cell
Font rowFont;
Color rowForeColor;
Color rowBackColor;
SolidBrush rowForeBrush;
SolidBrush rowBackBrush;
SolidBrush rowAlternatingBackBrush;
//--- Set the format that will be used to print each cell
StringFormat cellFormat = new StringFormat();
cellFormat.Trimming = StringTrimming.Word;
cellFormat.Trimming = StringTrimming.EllipsisCharacter;
cellFormat.FormatFlags = StringFormatFlags.NoWrap
| StringFormatFlags.LineLimit;
//| StringFormatFlags.LineLimit
//| StringFormatFlags.NoClip;
//--- Print each visible cell
RectangleF rowBounds;
float currentX;
float columnWidth;
bool bUpdateColumnCount = true;
int nColsPrinted = 0;
while (mCurrentRow < mTheDataGridView.Rows.Count)
{
float rowHeight = mRowHeight[mCurrentRow];
if (mTheDataGridView.Rows[mCurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible
{
//--- Set the row font style
rowFont = mTheDataGridView.Rows[mCurrentRow].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 = mTheDataGridView.DefaultCellStyle.Font;
//--- Set the RowFore style
rowForeColor = mTheDataGridView.Rows[mCurrentRow].DefaultCellStyle.ForeColor;
// If the there is no special RowFore style of the CurrentRow,
// then use the default one associated with the DataGridView control
if (rowForeColor.IsEmpty)
rowForeColor = mTheDataGridView.DefaultCellStyle.ForeColor;
rowForeBrush = new SolidBrush(rowForeColor);
//--- Set the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles
rowBackColor = mTheDataGridView.Rows[mCurrentRow].DefaultCellStyle.BackColor;
// If the there is no special RowBack style of the CurrentRow,
// then use the default one associated with the DataGridView control
if (rowBackColor.IsEmpty)
{
rowBackBrush = new SolidBrush(mTheDataGridView.DefaultCellStyle.BackColor);
rowAlternatingBackBrush = new SolidBrush(mTheDataGridView.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);
}
//--- Calculate the starting X coordinate that the printing process
// will start from
currentX = (float)this.mPageMargins.Left;
float pagePrintWidth = this.DoGetPrintableWidth();
float colRangeWidth = mColumnRangeWidth[mColumnRangeCur];
if (mIsCenterOnPage)
currentX += (pagePrintWidth - colRangeWidth) / 2.0F;
//--- Calculate the entire CurrentRow bounds
rowBounds = new RectangleF(currentX, mCurrentY,
colRangeWidth, rowHeight);
//--- Fill the back of the CurrentRow
if (mCurrentRow % 2 == 0)
g.FillRectangle(rowBackBrush, rowBounds);
else
g.FillRectangle(rowAlternatingBackBrush, rowBounds);
//--- Print each visible cell of the CurrentRow
int colStart = (int)mColumnRange[mColumnRangeCur].GetValue(0);
int colEnd = (int)mColumnRange[mColumnRangeCur].GetValue(1);
for (int iCol = colStart; iCol < colEnd; iCol++)
{
// If the cell is belong to invisible column,
// then ignore this iteration
if (!mTheDataGridView.Columns[iCol].Visible)
continue;
Type cellType = mTheDataGridView.Columns[iCol].CellType;
bool bCellIsAnImage
= (cellType.ToString() == "System.Windows.Forms.DataGridViewImageCell");
// Adjust the height of the row if there is an image
if (bCellIsAnImage) //REWORK
{
if (mTheDataGridView.Rows[this.mCurrentRow].Cells[iCol].Value != null)
{
Image mTempImage = (Image)mTheDataGridView.Rows[mCurrentRow].Cells[iCol].Value;
if (mTempImage.Height > rowHeight)
rowHeight = mTempImage.Height;
}
}
// Check the CurrentCell alignment and apply it to the CellFormat
if (mTheDataGridView.Columns[iCol].DefaultCellStyle.Alignment.ToString().Contains("Right"))
cellFormat.Alignment = StringAlignment.Far;
else if (mTheDataGridView.Columns[iCol].DefaultCellStyle.Alignment.ToString().Contains("Center"))
cellFormat.Alignment = StringAlignment.Center;
else
cellFormat.Alignment = StringAlignment.Near;
columnWidth = mColumnWidthPadded[iCol];
RectangleF cellBounds = new RectangleF(currentX, mCurrentY,
columnWidth, rowHeight);
//Printing the cell text OR draw the image
if (bCellIsAnImage)
{
// Only try drawing the image if one is assigned to the cell
if (mTheDataGridView.Rows[mCurrentRow].Cells[iCol].Value != null)
{
Image img = (Image)mTheDataGridView.Rows[mCurrentRow].Cells[iCol].Value;
g.DrawImage(img, (float)currentX, (float)mCurrentY,
(float)columnWidth, (float)rowHeight);
}
}
else
{
// There was no image, so just draw the text
//cellBounds.Inflate(-mCellMargins.Left, -mCellMargins.Top); //REWORK
cellBounds.Offset(mCellMargins.Left, mCellMargins.Top); //REWORK
string cellValue = mTheDataGridView.Rows[mCurrentRow].Cells[iCol].EditedFormattedValue.ToString();
g.DrawString(cellValue, rowFont, rowForeBrush, cellBounds, cellFormat);
}
//--- Draw the cell's bounds
if (mTheDataGridView.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None
g.DrawRectangle(theLinePen, currentX, mCurrentY,
columnWidth, rowHeight);
currentX += columnWidth;
if(bUpdateColumnCount)
nColsPrinted++;
}
bUpdateColumnCount = false;
mCurrentY += rowHeight;
// 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)mCurrentY > (mPageHeight - this.mPageMargins.Top - this.mPageMargins.Bottom))
if ((int)this.mCurrentY > this.DoGetPrintableHeight())
{
mCurrentRow++;
return true;
}
}
mCurrentRow++;
}
//if (true)
//{
// string sMsg = String.Format("DrawRows:DGV.Rows={0}; Row={1}", mTheDataGridView.Rows.Count, this.mCurrentRow);
// Debug.WriteLine(sMsg);
//}
mCurrentRow = 0;
// Continue to print the next group of columns
mColumnRangeCur ++; //= nColsPrinted;
if (mColumnRangeCur >= mColumnRange.Count) // Which means all columns are printed
{
mColumnRangeCur = 0;
return false;
}
else
return true;
}
//*****************************************************************************
// The method that calls all other functions
//*****************************************************************************
private bool DrawDataGridView(Graphics g)
{
bool bContinue;
try
{
Calculate(g);
DrawHeader(g);
DrawPageTitle(g);
DrawPageNumber(g);
bContinue = DrawRows(g);
}
catch (Exception ex)
{
MessageBox.Show("Operation failed: " + ex.Message.ToString(), Application.ProductName + " - Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
bContinue = false;
}
return bContinue;
}
//*****************************************************************************
//*****************************************************************************
public bool SetupThePrinting(bool bPreview)
{
if (mPrintDlg == null)
{
mPrintDlg = new PrintDialog();
//set the default
mPrintDlg.AllowCurrentPage = false;
mPrintDlg.AllowPrintToFile = false;
mPrintDlg.AllowSelection = false;
mPrintDlg.AllowSomePages = false;
mPrintDlg.PrintToFile = false;
mPrintDlg.ShowHelp = false;
mPrintDlg.ShowNetwork = false;
mPrintDlg.UseEXDialog = true;
//mPrintDlg.PrinterSettings.
}
//--- now get the options from the user
if (DialogResult.OK == mPrintDlg.ShowDialog())
{
mPrintDoc.DocumentName = this.mNameOfClient + ":" + this.PageTitle;
mPrintDoc.PrinterSettings = mPrintDlg.PrinterSettings;
mPrintDoc.DefaultPageSettings = mPrintDlg.PrinterSettings.DefaultPageSettings;
if(this.mPageMargins.Left!=0 && this.mPageMargins.Top != 0)
mPrintDoc.DefaultPageSettings.Margins = mPageMargins;
if (true)
{
// Calculating the PageWidth and the PageHeight
if (!mPrintDoc.DefaultPageSettings.Landscape)
{
mPageWidth = mPrintDoc.DefaultPageSettings.PaperSize.Width;
mPageHeight = mPrintDoc.DefaultPageSettings.PaperSize.Height;
}
else
{
mPageHeight = mPrintDoc.DefaultPageSettings.PaperSize.Width;
mPageWidth = mPrintDoc.DefaultPageSettings.PaperSize.Height;
}
//--- Calculate the page margins
this.mPageMargins = mPrintDoc.DefaultPageSettings.Margins;
}
if (bPreview)
{
PrintPreviewDialog previewDlg = new PrintPreviewDialog();
previewDlg.Document = this.mThePrintDocument;
previewDlg.ShowDialog();
}
else
{
this.mThePrintDocument.Print();
}
return true;
}
else
{
return false;
}
}
private void OnPrintPage(object sender, PrintPageEventArgs e)
{
bool more = this.DrawDataGridView(e.Graphics);
if (more == true)
e.HasMorePages = true;
else
{
this.mPageNumber = 0; //reset it
this.mCurrentRow = 0;
this.mColumnRangeCur = 0;
this.DoInit();
}
}
}
#endregion //DGVPrinter
#region VVX.Print Wrapper
class Print
{
#region Enums
public enum HowToPrintDGV
{
Everything,
SelectedColumns
}
#endregion //Enums
#region Member Variables (Private)
//PrintDocument mPrintDoc;
//PrintDialog mPrintDlg;
private DataGridView mDGV;
private bool mbPrint;
private string msTitle = "";
private bool mbPrintSetup;
private bool mbPrintPreview;
private HowToPrintDGV mPrintHowDGV = HowToPrintDGV.Everything;
#endregion //Member Variables (Private)
#region Properties (Public)
/// <summary>
/// Set or Get the DataGridView [to be] printed
/// </summary>
public DataGridView PrintWhichDGV
{
get { return mDGV; }
set { mDGV = value; }
}
public HowToPrintDGV PrintHowDGV
{
get { return mPrintHowDGV; }
set { mPrintHowDGV = value; }
}
private string msPrintJobName = "VVX.Print";
/// <summary>
/// Name of the print job displayed by Windows, Drivers, or the Printer itself, etc.
/// </summary>
public string PrintJobName
{
get { return msPrintJobName; }
set { msPrintJobName = value; }
}
/// <summary>
/// Determines if the Print Setup Dialog is displayed before printing or previewing
/// </summary>
public bool PrintSetup
{
get { return mbPrintSetup; }
set { mbPrintSetup = value; }
}
/// <summary>
/// Determines if Previewing occurs before printing
/// </summary>
public bool PrintPreview
{
get { return mbPrintPreview; }
set { mbPrintPreview = value; }
}
/// <summary>
/// Name of the print job displayed by Windows, Drivers, or the Printer itself, etc.
/// </summary>
public string PrintTitle
{
get { return msTitle; }
set { msTitle = value; }
}
#endregion //Properties (Public)
#region Constructors
/// <summary>
/// Constructor (mainly for using PrintControl)
/// </summary>
public Print()
{
}
/// <summary>
/// Constructor for printing contents of a DataGridView
/// </summary>
/// <param name="dgv"></param>
/// <param name="bSetup"></param>
/// <param name="bPreview"></param>
/// <param name="bPrint"></param>
public Print(DataGridView dgv, bool bSetup, bool bPreview, bool bPrint)
{
this.mDGV = dgv;
this.mbPrintSetup = bSetup;
this.mbPrintPreview = bPreview;
this.mbPrint = bPrint;
}
#endregion //Constructors
#region Methods (Public)
/// <summary>
/// Prints the contents of the DataGridView
/// </summary>
/// <returns></returns>
public bool DoPrintDGV()
{
bool bRet = false;
string sMsg = "";
string sEOL = Environment.NewLine;
if (this.mDGV != null)
{
switch (this.mPrintHowDGV)
{
default:
case HowToPrintDGV.Everything:
// Use VVX.Print class DGVPrinter
// Adapted from "The DataGridViewPrinter Class", By Salan Al-Ani.
// See http://www.codeproject.com/csharp/datagridviewprinter.asp
VVX.DGVPrinter dgvPrint = new DGVPrinter(this.mDGV);
dgvPrint.NameOfClient = this.PrintJobName;
dgvPrint.PageTitle = this.PrintTitle;
if (dgvPrint != null)
{
bRet = dgvPrint.SetupThePrinting(this.mbPrintPreview);
}
break;
case HowToPrintDGV.SelectedColumns:
// Use VVX.Print class PrintDGV
// Adapted from "DataGridView Printing by Selecting Columns and Rows", By Afrasiab Cheraghi
// See http://www.codeproject.com/csharp/PrintDataGridView.asp
bRet = PrintDGV.Print_DataGridView(this.mDGV, this.PrintTitle);
break;
}
}
else
{
sMsg = "You need to initialize 'VVX.Print.mDGV'"
+ " either with an appropriate constructor"
+ " or with the VVX.Print.PrintWhichDGV property" + sEOL;
MsgBox.Error(sMsg);
Debug.WriteLine(sMsg);
}
sMsg += String.Format("VVX.Print successful? {0} ", bRet.ToString());
Debug.WriteLine(sMsg);
return bRet;
}
/// <summary>
/// Displays a PrintDialog and allows the user to choose a printer
/// and various settings (such as orientation)
/// </summary>
/// <param name="printDocSettings">PrinterSettings settings to be used by the PrintDocument</param>
/// <returns>'true' if user clicked 'Print' in the PrintDialog, 'false' otherwise</returns>
public bool DoGetPrinterAndSettingsFromUser(PrinterSettings printDocSettings)
{
PrintDialog printDlg = new PrintDialog();
if (printDlg != null)
{
printDlg.PrinterSettings = printDocSettings;
//--- now get the options from the user
if (DialogResult.OK != printDlg.ShowDialog())
{
return false;
}
else
{
//--- update the settings
printDocSettings = printDlg.PrinterSettings;
return true;
#if !true
if (mPrintDoc == null)
{
this.mPrintDoc = new PrintDocument();
this.mPrintDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.OnPrintPage);
}
mPrintDoc.DocumentName = this.nameOfClient + ":" + this.PageTitle;
mPrintDoc.PrinterSettings = mPrintDlg.PrinterSettings;
mPrintDoc.DefaultPageSettings = mPrintDlg.PrinterSettings.DefaultPageSettings;
if (this.mPageMargins.Left != 0 && this.mPageMargins.Top != 0)
mPrintDoc.DefaultPageSettings.Margins = mPageMargins;
if (true)
{
// Calculating the PageWidth and the PageHeight
if (!mPrintDoc.DefaultPageSettings.Landscape)
{
mPageWidth = mPrintDoc.DefaultPageSettings.PaperSize.Width;
mPageHeight = mPrintDoc.DefaultPageSettings.PaperSize.Height;
}
else
{
mPageHeight = mPrintDoc.DefaultPageSettings.PaperSize.Width;
mPageWidth = mPrintDoc.DefaultPageSettings.PaperSize.Height;
}
//--- Calculate the page margins
this.mPageMargins = mPrintDoc.DefaultPageSettings.Margins;
}
if (bPreview)
{
PrintPreviewDialog previewDlg = new PrintPreviewDialog();
previewDlg.Document = this.mThePrintDocument;
previewDlg.ShowDialog();
}
else
{
this.mThePrintDocument.Print();
}
return true;
#endif
}
}
return false;
}
public void DoPrintControl(Control controlToPrint
, bool bSetup, bool bPreview, bool bPrint, bool bDoNotResize)
{
try
{
int width = controlToPrint.Width;
int height = controlToPrint.Height;
ControlPrint printDoc = new ControlPrint(controlToPrint, width, height, bDoNotResize);
bool bOk = true;
//bool bTemp;
//bTemp = printDoc.PrinterSettings.DefaultPageSettings.Landscape;
if (bSetup)
{
bOk = this.DoGetPrinterAndSettingsFromUser(printDoc.PrinterSettings);
}
//bTemp = printDoc.PrinterSettings.DefaultPageSettings.Landscape;
if (bOk)
{
if (bPreview)
{
PrintPreviewDialog ppvDlg = new PrintPreviewDialog(); ;
ppvDlg.Document = (PrintDocument)printDoc;
ppvDlg.ShowDialog();
}
else
{
printDoc.Print();
}
}
}
catch (Exception ex)
{
MsgBox.Error(ex.ToString());
}
}
#endregion //Methods (Public)
}
#endregion //VVX.Print Wrapper
}