protected override void OnPrintPage(PrintPageEventArgs e) { base.OnPrintPage(e); if (m_PageCount == 0) { m_HeaderHeight = this.GetHeaderHeight(e.Graphics); m_TitleHeight = this.GetTitleHeight(e.Graphics); m_FooterHeight = this.GetFooterHeight(e.Graphics); m_PageCount = this.PrecalculatePageCount(e); m_PageNo = 1; } if (m_RangeToPrint.IsEmpty()) return; if ( m_BorderPen == null ) m_BorderPen = new Pen(Color.Black); RectangleF area = new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top + m_HeaderHeight + (m_NextRowToPrint == RangeToPrint.Start.Row ? m_TitleHeight : 0), e.MarginBounds.Width, e.MarginBounds.Height - m_HeaderHeight - (m_NextRowToPrint == RangeToPrint.Start.Row ? m_TitleHeight : 0) - m_FooterHeight); this.DrawHeader(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, m_HeaderHeight), m_PageNo, m_PageCount); if ( m_PageNo == 1 ) this.DrawTitle(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top + m_HeaderHeight, e.MarginBounds.Width, m_TitleHeight), m_PageNo, m_PageCount); List<int> columnHasTopBorder = new List<int>(); List<int> rowHasLeftBorder = new List<int>(); RangeCollection printedRanges = new RangeCollection(); int pageFirstRow = m_NextRowToPrint; int pageFirstColumn = m_NextColumnToPrint; int pageLastColumn = RangeToPrint.End.Column; // Pre-calculate width of the table in current page float pageColumnWidth = 0; for ( int i = m_NextColumnToPrint; i <= RangeToPrint.End.Column; i++ ) { float colWidth = this.GetColumnWidth(e.Graphics, i); if ( i == m_NextColumnToPrint && colWidth > area.Width ) colWidth = area.Width; if ( pageColumnWidth + colWidth <= area.Width ) pageColumnWidth += colWidth; else break; } // Support for fixed row repeat if ( RepeatFixedRows && m_Grid.ActualFixedRows > RangeToPrint.Start.Row ) m_NextRowToPrint = RangeToPrint.Start.Row; float curY = area.Top; while (m_NextRowToPrint <= RangeToPrint.End.Row) { // If repeated rows are printed, resume printing next rows if ( RepeatFixedRows && m_NextRowToPrint >= m_Grid.ActualFixedRows && m_NextRowToPrint < pageFirstRow ) m_NextRowToPrint = pageFirstRow; float rowHeight = this.GetRowHeight(e.Graphics, m_NextRowToPrint); // Check if row fits in current page if ( curY + rowHeight > area.Bottom ) break; float curX = area.Left; while (m_NextColumnToPrint <= pageLastColumn) { float colWidth = this.GetColumnWidth(e.Graphics, m_NextColumnToPrint); // Check if column fits in current page if ( curX + colWidth > area.Right ) { // If single column does not fit in page, force it if ( m_NextColumnToPrint == pageFirstColumn ) colWidth = area.Right - curX; else { pageLastColumn = m_NextColumnToPrint - 1; break; } } RectangleF cellRectangle; Position pos = new Position(m_NextRowToPrint, m_NextColumnToPrint); Range range = m_Grid.PositionToCellRange(pos); // Check if cell is spanned if ( range.ColumnsCount > 1 || range.RowsCount > 1 ) { Size rangeSize = m_Grid.RangeToSize(range); // Is the first position, draw allways if ( range.Start == pos ) { cellRectangle = new RectangleF(curX, curY, rangeSize.Width, rangeSize.Height); printedRanges.Add(range); } else { // Draw only if this cell is not already drawn on current page if ( ! printedRanges.ContainsCell(pos) ) { // Calculate offset float sX = curX; for (int i = pos.Column - 1; i >= range.Start.Column; i--) { float cw = this.GetColumnWidth(e.Graphics, i); sX -= cw; } float sY = curY; for ( int i = pos.Row - 1; i >= range.Start.Row; i-- ) { float cw = this.GetRowHeight(e.Graphics, i); sY -= cw; } cellRectangle = new RectangleF(sX, sY, rangeSize.Width, rangeSize.Height); printedRanges.Add(range); } else cellRectangle = RectangleF.Empty; } } else { cellRectangle = new RectangleF(curX, curY, colWidth, rowHeight); } if ( ! cellRectangle.IsEmpty ) { SourceGrid.Cells.ICellVirtual cell = this.m_Grid.GetCell(pos); if ( cell != null ) { CellContext ctx = new CellContext(m_Grid, pos, cell); RectangleF clip = new RectangleF(Math.Max(cellRectangle.Left, area.Left), Math.Max(cellRectangle.Top, area.Top), Math.Min(cellRectangle.Right, area.Left + pageColumnWidth) - Math.Max(cellRectangle.Left, area.Left), Math.Min(cellRectangle.Bottom, area.Bottom) - Math.Max(cellRectangle.Top, area.Top)); Region prevClip = e.Graphics.Clip; try { e.Graphics.Clip = new Region(clip); this.DrawCell(e.Graphics, ctx, cellRectangle); } finally { // Restore clip region e.Graphics.Clip = prevClip; } // Check if left border can be drawn in current page if ( ! ContainsInRange(rowHasLeftBorder, range.Start.Row, range.End.Row) && cellRectangle.Left >= area.Left ) { e.Graphics.DrawLine(m_BorderPen, cellRectangle.Left, clip.Top, cellRectangle.Left, clip.Bottom); AddRange(rowHasLeftBorder, range.Start.Row, range.End.Row); } // Check if top border can be drawn in current page if ( ! ContainsInRange(columnHasTopBorder, range.Start.Column, range.End.Column) && cellRectangle.Top >= area.Top ) { e.Graphics.DrawLine(m_BorderPen, clip.Left, cellRectangle.Top, clip.Right, cellRectangle.Top); AddRange(columnHasTopBorder, range.Start.Column, range.End.Column); } // Check if right border can be drawn in current page if ( cellRectangle.Right <= area.Right ) e.Graphics.DrawLine(m_BorderPen, cellRectangle.Right, clip.Top, cellRectangle.Right, clip.Bottom); // Check if bottom border can be drawn in current page if ( cellRectangle.Bottom <= area.Bottom ) e.Graphics.DrawLine(m_BorderPen, clip.Left, cellRectangle.Bottom, clip.Right, cellRectangle.Bottom); } } // Set next column position curX += colWidth; m_NextColumnToPrint++; } // Set next row Y position curY += rowHeight; m_NextRowToPrint++; m_NextColumnToPrint = pageFirstColumn; } // If we have not reached last column, we will continue on next page if ( pageLastColumn != RangeToPrint.End.Column ) { m_NextRowToPrint = pageFirstRow; m_NextColumnToPrint = pageLastColumn + 1; } else m_NextColumnToPrint = RangeToPrint.Start.Column; this.DrawFooter(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Bottom - m_FooterHeight, e.MarginBounds.Width, m_FooterHeight), m_PageNo, m_PageCount); // If we have not reached last row we will continue on next page e.HasMorePages = (m_NextRowToPrint <= RangeToPrint.End.Row); // If there are no more pages, release resources if ( e.HasMorePages ) m_PageNo++; }