using FastReport.Engine; using FastReport.Forms; using FastReport.Preview; using FastReport.Utils; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Printing; using System.Threading.Tasks; using System.Windows.Forms; namespace FastReport { partial class Report { #region Private Fields private int tickCount; private EmailSettings emailSettings; private FastReport.Preview.PreviewControl preview; private BaseForm previewForm; private PrintSettings printSettings; private bool isPreviewing; #endregion Private Fields #region Public Properties /// /// Gets the email settings such as recipients, subject, message body. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [SRCategory("Email")] public EmailSettings EmailSettings { get { return emailSettings; } } /// /// Gets or sets the report preview control. /// /// /// Use this property to attach a custom preview to your report. To do this, place the PreviewControl /// control to your form and set the report's Preview property to this control. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Preview.PreviewControl Preview { get { return preview; } set { preview = value; if (value != null) value.SetReport(this); } } /// /// Gets the print settings such as printer name, copies, pages to print etc. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [SRCategory("Print")] public PrintSettings PrintSettings { get { return printSettings; } } /// /// /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsPreviewing { get { return isPreviewing; } } #endregion Public Properties #region Public Methods /// /// Prepares the report and prints it. /// public void Print() { if (Prepare()) PrintPrepared(); } /// /// Prints the report with the "Print" dialog. /// Report should be prepared using the method. /// public void PrintPrepared() { if (PreparedPages != null) PreparedPages.Print(); } /// /// Prints the report without the "Print" dialog. /// Report should be prepared using the method. /// /// Printer-specific settings. /// /// Use the following code if you want to show the "Print" dialog, then print: /// /// if (report.Prepare()) /// { /// PrinterSettings printerSettings = null; /// if (report.ShowPrintDialog(out printerSettings)) /// { /// report.PrintPrepared(printerSettings); /// } /// } /// /// public void PrintPrepared(PrinterSettings printerSettings) { if (PreparedPages != null) PreparedPages.Print(printerSettings, 1); } /// /// Prepares the report and shows it in the preview window. /// public void Show() { Show(true, null); } /// /// Prepares the report and shows it in the preview window. /// /// A value that specifies whether the preview window should be modal. public void Show(bool modal) { Show(modal, null); } /// /// Prepares the report and shows it in the preview window. /// /// A value that specifies whether the preview window should be modal. /// The owner of the preview window. public void Show(bool modal, IWin32Window owner) { if (Prepare()) ShowPrepared(modal, null, owner); else if (Preview != null) { Preview.Clear(); Preview.Refresh(); } } /// /// Prepares the report and shows it in the preview window. /// /// The main MDI form which will be a parent for the preview window. public void Show(Form mdiParent) { if (Prepare()) ShowPrepared(false, mdiParent, null); else if (Preview != null) { Preview.Clear(); Preview.Refresh(); } } /// /// Previews the report. The report should be prepared using the method. /// public void ShowPrepared() { ShowPrepared(true); } /// /// Previews the prepared report. /// /// A value that specifies whether the preview window should be modal. public void ShowPrepared(bool modal) { ShowPrepared(modal, null, null); } /// /// Previews the prepared report. /// /// A value that specifies whether the preview window should be modal. /// The owner of the preview window. public void ShowPrepared(bool modal, IWin32Window owner) { ShowPrepared(modal, null, owner); } /// /// Previews the prepared report. /// /// The main MDI form which will be a parent for the preview window. public void ShowPrepared(Form mdiParent) { ShowPrepared(false, mdiParent, null); } /// /// Shows the "Print" dialog. /// /// Printer-specific settings. /// true if the dialog was closed by "Print" button. /// /// Use the following code if you want to show the "Print" dialog, then print: /// /// if (report.Prepare()) /// { /// PrinterSettings printerSettings = null; /// if (report.ShowPrintDialog(out printerSettings)) /// { /// report.PrintPrepared(printerSettings); /// } /// } /// /// public bool ShowPrintDialog(out PrinterSettings printerSettings) { printerSettings = null; using (PrinterSetupForm dialog = new PrinterSetupForm()) { dialog.Report = this; dialog.PrintDialog = true; if (dialog.ShowDialog() != DialogResult.OK) return false; printerSettings = dialog.PrinterSettings; } return true; } #endregion Public Methods #region Async Prepare/Show methods /* proposed usage: try { if (AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception AsyncPrepareRun(); // run report pages (may be run pseudo async way) } finally { AsyncPrepareFinish(); // cleanup } */ internal async Task AsyncPrepareStart() { SetRunning(true); ClearPreparedPages(); SetPreparedPages(new Preview.PreparedPages(this)); engine = new ReportEngine(this); StartPerformanceCounter(); Compile(); Engine.RunPhase1(); // WPF: dialogs should be run here, before we set up modal preview window (deadlock issue) return await Engine.RunDialogsAsync(); } internal void AsyncPrepareRun() { Engine.RunPhase2(false, null); } internal void AsyncPrepareFinish() { Engine.RunFinished(); StopPerformanceCounter(); SetRunning(false); if (Config.ReportSettings.ShowPerformance) Preview?.ShowPerformance(String.Format(Res.Get("Messages,Performance"), tickCount)); if (ReportInfo.SavePreviewPicture && PreparedPages.Count > 0) SavePreviewPicture(); } /// /// Prepares the report and shows it in the provided PreviewControl (async way). /// /// The preview control. public async Task PrepareAsync(PreviewControl preview) { if (preview == null) throw new ArgumentNullException(nameof(preview)); bool saveProgress = Config.ReportSettings.ShowProgress; Config.ReportSettings.ShowProgress = false; var saveButtons = preview.Buttons; bool finished = false; try { if (await AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception { // setup preview control preview.SetAsyncReportRunning(); preview.Buttons |= PreviewButtons.Close; Preview = preview; SetupPreviewControl(); preview.AsyncReportStart(); var tcs = new System.Threading.Tasks.TaskCompletionSource(); var timer = new Timer() { Interval = 50 }; timer.Tick += (s, args) => { timer.Dispose(); try { AsyncPrepareRun(); // run report pages (pseudo async way). May throw a runtime exception } finally { AsyncPrepareFinish(); // cleanup preview.AsyncReportFinish(); finished = true; tcs.SetResult(true); } }; timer.Start(); Config.PreviewSettings.OnPreviewOpened(Preview); // wait for report to finish await tcs.Task; } } finally { if (!finished) AsyncPrepareFinish(); // cleanup Config.ReportSettings.ShowProgress = saveProgress; preview.Buttons = saveButtons; } } private async Task ShowAsync(bool modal, Form mdiParent, IWin32Window owner) { bool saveProgress = Config.ReportSettings.ShowProgress; Config.ReportSettings.ShowProgress = false; bool finished = false; try { if (await AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception { // create preview form previewForm = CreatePreviewForm(); previewForm.MdiParent = mdiParent; // setup preview control var preview = Preview; preview.SetAsyncReportRunning(); preview.Buttons |= PreviewButtons.Close; SetupPreviewControl(); preview.AsyncReportStart(); previewForm.Shown += (sender, e) => { var timer = new Timer() { Interval = 50 }; timer.Tick += (s, args) => { timer.Dispose(); try { AsyncPrepareRun(); // run report pages (pseudo async way). May throw a runtime exception } finally { AsyncPrepareFinish(); // cleanup preview.AsyncReportFinish(); finished = true; } }; timer.Start(); }; #if AVALONIA await ShowPreviewFormAsync(modal, mdiParent, owner); #else ShowPreviewForm(modal, mdiParent, owner); #endif } } finally { if (!finished) AsyncPrepareFinish(); // cleanup Config.ReportSettings.ShowProgress = saveProgress; finished = true; } } /// /// Prepares the report and shows it in the preview window (async way). /// public async Task ShowAsync() => await ShowAsync(true, null); /// /// Prepares the report and shows it in the preview window (async way). /// /// A value that specifies whether the preview window should be modal. public async Task ShowAsync(bool modal) => await ShowAsync(modal, null); /// /// Prepares the report and shows it in the preview window (async way). /// /// A value that specifies whether the preview window should be modal. /// The owner of the preview window. public async Task ShowAsync(bool modal, IWin32Window owner) => await ShowAsync(modal, null, owner); /// /// Prepares the report and shows it in the preview window (async way). /// /// The main MDI form which will be a parent for the preview window. public async Task ShowAsync(Form mdiParent) => await ShowAsync(false, mdiParent, null); #endregion #region Private Methods private void StartPerformanceCounter() { tickCount = Environment.TickCount; } private void StopPerformanceCounter() { tickCount = Environment.TickCount - tickCount; } private void ClearPreparedPages() { if (preview != null) preview.ClearTabsExceptFirst(); else if (preparedPages != null) preparedPages.Clear(); } private void DisposePreviewForm() { previewForm.Dispose(); previewForm = null; preview = null; } private void OnClosePreview(object sender, FormClosedEventArgs e) { DisposePreviewForm(); } private void SavePreviewPicture() { ReportPage page = PreparedPages.GetCachedPage(0); float pageWidth = page.WidthInPixels; float pageHeight = page.HeightInPixels; float ratio = ReportInfo.PreviewPictureRatio; ReportInfo.Picture = new Bitmap((int)Math.Round(pageWidth * ratio), (int)Math.Round(pageHeight * ratio)); using (Graphics g = Graphics.FromImage(ReportInfo.Picture)) { FRPaintEventArgs args = new FRPaintEventArgs(g, ratio, ratio, GraphicCache); page.Draw(args); } } private void ShowPrepared(bool modal, Form mdiParent, IWin32Window owner) { // create preview form if (Preview == null) { previewForm = CreatePreviewForm(); } SetupPreviewControl(); if (Config.ReportSettings.ShowPerformance) { try { // in case the format string is wrong, use try/catch Preview.ShowPerformance(String.Format(Res.Get("Messages,Performance"), tickCount)); } catch { } } if (ReportInfo.SavePreviewPicture && PreparedPages.Count > 0) SavePreviewPicture(); ShowPreviewForm(modal, mdiParent, owner); } private PreviewForm CreatePreviewForm() { var previewForm = new PreviewForm(); previewForm.ShowInTaskbar = Config.PreviewSettings.ShowInTaskbar; if (Config.PreviewSettings.TopMost) previewForm.TopMost = true; previewForm.Icon = Config.PreviewSettings.Icon; if (String.IsNullOrEmpty(Config.PreviewSettings.Text)) { previewForm.Text = String.IsNullOrEmpty(ReportInfo.Name) ? "" : ReportInfo.Name + " - "; previewForm.Text += Res.Get("Preview"); } else previewForm.Text = Config.PreviewSettings.Text; Preview = previewForm.Preview; Preview.UIStyle = Config.UIStyle; Preview.FastScrolling = Config.PreviewSettings.FastScrolling; Preview.Buttons = Config.PreviewSettings.Buttons; Preview.SaveInitialDirectory = Config.PreviewSettings.SaveInitialDirectory; return previewForm; } private void ShowPreviewForm(bool modal, Form mdiParent, IWin32Window owner) { Config.PreviewSettings.OnPreviewOpened(Preview); isPreviewing = true; if (previewForm != null && !previewForm.Visible) { previewForm.MdiParent = mdiParent; if (modal) { previewForm.ShowDialog(owner); DisposePreviewForm(); } else { previewForm.FormClosed += new FormClosedEventHandler(OnClosePreview); if (mdiParent == null) previewForm.Show(owner); else previewForm.Show(); } isPreviewing = false; } } #if AVALONIA private async Task ShowPreviewFormAsync(bool modal, Form mdiParent, IWin32Window owner) { Config.PreviewSettings.OnPreviewOpened(Preview); isPreviewing = true; if (previewForm != null && !previewForm.Visible) { previewForm.MdiParent = mdiParent; if (modal) { await previewForm.ShowDialogAsync(owner); DisposePreviewForm(); } else { previewForm.FormClosed += new FormClosedEventHandler(OnClosePreview); if (mdiParent == null) previewForm.Show(owner); else previewForm.Show(); } isPreviewing = false; } } #endif internal void SetupPreviewControl() { Preview.ClearTabsExceptFirst(); if (PreparedPages != null) Preview.AddPreviewTab(this, GetReportName, null, true); } #endregion Private Methods } }