/* i-net software provides programming examples for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This programming example assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures. i-net software support professionals can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific needs. © i-net software 1998-2013 */ using System; using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; using System.Threading; using Inet.Viewer.Resources; using Inet.Viewer.WinForms; namespace Inet.Viewer.Data { /// <summary> /// Progress implementation for printing a report. /// </summary> public class PrintProgress : Progress { private PrintDocument printDoc; private int currentPage; private ReportDataCache reportDataCache; private int pageCount; private PrinterSettings printerSettings; /// <summary> /// Creates a print progress for the specified render data. /// </summary> /// <param name="renderData">the report to print</param> /// <param name="printerSettings">printing settings</param> /// <param name="errorDelegate">a delegate which will be called on failures during the progress</param> public PrintProgress(IRenderData renderData, PrinterSettings printerSettings, Action<Exception> errorDelegate) : this(new ReportDataCache(renderData), printerSettings, errorDelegate) { } /// <summary> /// Creates a print progress for the specified ReportDataCache instance. /// </summary> /// <param name="reportDataCache">the report to print as ReportDataCache instance</param> /// <param name="printerSettings">printing settings</param> /// <param name="errorDelegate">a delegate which will be called on failures during the progress</param> internal PrintProgress(ReportDataCache reportDataCache, PrinterSettings printerSettings, Action<Exception> errorDelegate) : base(errorDelegate, ProgressType.Print) { this.reportDataCache = reportDataCache; this.printerSettings = printerSettings; printDoc = new PrintDocument(); printDoc.PrinterSettings = printerSettings; printDoc.QueryPageSettings += new QueryPageSettingsEventHandler(printDoc_QueryPageSettings); printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); } /// <summary> /// Gets or sets the report info instance. When the report and the page info instances are set both, no /// additional request to the report data cache is needed before printing. /// </summary> internal ReportInfo ReportInfo { get; set; } /// <summary> /// Gets or sets the page info instance. When the report and the page info instances are set both, no /// additional request to the report data cache is needed before printing. /// </summary> internal PageInfo PageInfo { get; set; } /// <summary> /// Gets or sets the current page of the viewer. Used when the user selects "Current Page" in the /// printing dialog. /// </summary> internal int CurrentViewPage { set; get; } /// <inheritdoc /> protected override void Run() { try { pageCount = reportDataCache.PageCount(); PrintRange rangeType = printerSettings.PrintRange; if (rangeType == PrintRange.SomePages) { currentPage = printerSettings.FromPage; } else if (rangeType == PrintRange.CurrentPage) { currentPage = CurrentViewPage; } else { currentPage = 1; } LoadMetaDataIfRequired(); printDoc.DocumentName = ReportInfo.Title; printDoc.Print(); Status = ProgressStatus.Completed; } catch (Exception e) { ShowError(e); } } /// <summary> /// Called before printing a page. Sets the page settings. /// </summary> /// <param name="sender">not used</param> /// <param name="e">event args which include page settings</param> private void printDoc_QueryPageSettings(object sender, QueryPageSettingsEventArgs e) { e.PageSettings.Margins = PageInfo.PrintMargins; } /// <summary> /// Called when printing the next page. Does the actual output on the printer graphics. /// </summary> /// <param name="sender"></param> /// <param name="ev"></param> private void printDoc_PrintPage(object sender, PrintPageEventArgs ev) { Graphics2DPainter painter = new Graphics2DPainter(true); PrinterPageView pageView = new PrinterPageView(ErrorDelegate, reportDataCache, ev); byte[] pageData = reportDataCache.PageData(currentPage, false); pageView.Page = currentPage; PageLoader pLoader = new PageLoader(painter, pageView); pLoader.PaintPage(pageData); currentPage++; PrintRange rangeType = ev.PageSettings.PrinterSettings.PrintRange; if (rangeType == PrintRange.SomePages) { ev.HasMorePages = currentPage <= Math.Min( pageCount, ev.PageSettings.PrinterSettings.ToPage); } else if (rangeType == PrintRange.CurrentPage) { ev.HasMorePages = false; } else { ev.HasMorePages = currentPage <= pageCount; } ev.Cancel = Status == ProgressStatus.Canceled; } /// <inheritdoc/> public override string Name { get { return strings.Print; } } /// <inheritdoc/> public override void Cancel() { Status = ProgressStatus.Canceled; } /// <summary> /// Updates the default page settings of the printer settings. This will change the PrinterSettings /// instance specified via the constructor when creating this progress. /// If no meta data (ReportInfo / PageInfo) was set manually, the required properties are loaded /// directly from the underlying IRenderData instance. /// Since this method may invoke blocking I/O operations, it should not be called form a UI thread. /// </summary> public void UpdatePageSettings() { LoadMetaDataIfRequired(); printerSettings.DefaultPageSettings.Landscape = PageInfo.PageAlign == (int)PageOrientation.Landscape; printerSettings.DefaultPageSettings.Margins = PageInfo.PrintMargins; } /// <summary> /// Loads the meta data if not set yet. /// </summary> private void LoadMetaDataIfRequired() { if (ReportInfo == null || PageInfo == null) { // meta data not set yet => parse the first page PageMetaReceiver pageMetaReceiver = new PageMetaReceiver(); PageLoader loader = new PageLoader(null, pageMetaReceiver); loader.Data = reportDataCache.PageData(1, false); loader.ReadTokens(); if (pageMetaReceiver.Error != null) { ShowError(pageMetaReceiver.Error); return; } ReportInfo = pageMetaReceiver.ReportInfo; PageInfo = pageMetaReceiver.PageInfo; } } } }