Table of Contents

Custom previewing (C++)

Note

This demo is available in your FlexCel installation at <FlexCel Install Folder>\Demo\Cpp\Modules\25.Printing and Exporting\20.CustomPreview and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​VCL-​demos/​tree/​master/​Cpp/​Modules/​25.​Printing and Exporting/​20.​Custom​Preview

Overview

FlexCel comes with a full featured viewer that you can use to display a preview of Excel files in your application, and without having any printer installed.

Concepts

  • How to create a preview form that you can embed inside your application, including thumbnails, navigation, etc.

  • How to Export to PDF from a thread, allowing the user to cancel it.

Files

CustomPreview.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------

USEFORM("UCustomPreview.cpp", FCustomPreview);
USEFORM("UPasswordDialog.cpp", PasswordDialog);
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TFCustomPreview), &FCustomPreview);
		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");
		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
		}
	}
	return 0;
}
//---------------------------------------------------------------------------

UCustomPreview.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UCustomPreview.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFCustomPreview *FCustomPreview;
//---------------------------------------------------------------------------
__fastcall TFCustomPreview::TFCustomPreview(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::FormCreate(TObject *Sender)
{
  Xls = new TXlsFile(1, false);
  Xls->Protection->OnPassword = GetPassword;
  ImgExport = new TFlexCelImgExport(Xls, false);
  ImgExport->AllVisibleSheets = false;
  MainPreview->Document = ImgExport;
  Thumbs->Document = ImgExport;
  RegisterForHDPI(this, DPIChanged);
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::FormDestroy(TObject *Sender)
{
  PrintingThread->Free();
  PdfThread->Free();
  ImgExport->Free();
  Xls->Free(); //after freeing the threads, so we don't free the xls object while they are working.
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::ActionCloseExecute(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------

#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older, this should be "TOnPasswordEventArgs * const e".
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
void __fastcall TFCustomPreview::GetPassword(const TOnPasswordEventArgs* e)
{
  TPasswordDialog* Pwd = new TPasswordDialog(NULL);
  try
  {
	Pwd->SetFileName(OpenDialog->FileName);
	if (Pwd->ShowModal() != mrOk) return;

	//We need this cast because the delphi object is a constant pointer, not a pointer to a constant.
	const_cast<TOnPasswordEventArgs*>(e)->Password = Pwd->Password();
  }
  __finally
  {
	Pwd->Free();
  }
}
#else
//XE3 has fixed the bug, now we need to define the event correctly
void __fastcall TFCustomPreview::GetPassword(TOnPasswordEventArgs* const e)
{
  TPasswordDialog* Pwd = new TPasswordDialog(NULL);
  try
  {
	Pwd->SetFileName(OpenDialog->FileName);
	if (Pwd->ShowModal() != mrOk) return;

	e->Password = Pwd->Password();
  }
  __finally
  {
	Pwd->Free();
  }
}
#endif


void __fastcall TFCustomPreview::ActionOpenExecute(TObject *Sender)
{
  if (!(OpenDialog->Execute())) return;
  LoadFile(OpenDialog->FileName);
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::LoadFile(String FileName)
{
  PanelPdfOk->Visible = false;
  PanelPdfError->Visible = false;
  PanelPdf->Visible = false;
  PanelPrintingOk->Visible = false;
  PanelPrintingError->Visible = false;
  PanelPrinting->Visible = false;


  OpenDialog->FileName = FileName;
  lbSheets->Items->Clear();

  try
  {
	Xls->Open(FileName);
  }
  catch (Exception* ex)
  {
	EnableCommonActions(false);
	ActionPrint->Enabled = false;
	ActionPdf->Enabled = false;
	ActionZoom->Enabled = false;
	ActionAutofit->Enabled = false;
	ActionOpen->Enabled = true;
	PanelSelectPage->Visible = false;
	Xls->NewFile(1, TExcelFileFormat::v2019);
	Caption = "Custom Preview";
	ShowMessage("Error opening file: " + ex->Message);
	MainPreview->InvalidatePreview();
	return;
  }

  for (int i = 1; i <= Xls->SheetCount; i++)
  {
	lbSheets->Items->Add(Xls->GetSheetName(i));
  }
  lbSheets->ItemIndex = Xls->ActiveSheet - 1;

  EnableCommonActions(true);
  ActionPrint->Enabled = true;
  ActionPdf->Enabled = true;
  ActionZoom->Enabled = true;
  ActionAutofit->Enabled = true;
  Caption = "Custom Preview: " + OpenDialog->FileName;
  PanelSelectPage->Visible = true;
  ToolBarAutofit->Left = PanelSelectPage->Left + 10; //Make the panel appear to the left of the toolbar.
  MainPreview->InvalidatePreview();
}


void __fastcall TFCustomPreview::cbAllSheetsClick(TObject *Sender)
{
  PanelSheets->Visible = !cbAllSheets->Checked;
  ImgExport->AllVisibleSheets = cbAllSheets->Checked;
  MainPreview->InvalidatePreview();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::lbSheetsClick(TObject *Sender)
{
  if (lbSheets->Items->Count > Xls->SheetCount) return;
  Xls->ActiveSheet = lbSheets->ItemIndex + 1;
  MainPreview->InvalidatePreview();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::EnableCommonActions(bool Enable)
{
  if (Enable) DisabledCount--; else DisabledCount++;
  if (DisabledCount < 0) DisabledCount = 0;
  if (Enable && DisabledCount > 0) return; //we would be both printing and exporting to pdf, if one finishes, the buttons shouldn't be enabled util the other finishes too.


  ActionOpen->Enabled = Enable;
  ActionGridLines->Enabled = Enable;
  ActionHeadings->Enabled = Enable;
  ActionRecalc->Enabled = Enable;
}

void __fastcall TFCustomPreview::PdfProgressFeedback(int Progress, String Msg)
{
  PdfProgressBar->Position = Progress;
  lblPdfPage->Caption = Msg;
}

void __fastcall TFCustomPreview::PdfFinalFeedback(bool Ok, String Msg)
{
  PanelPdf->Visible = false;
  if (!Ok)
  {
	PanelPdfError->Visible = true;
	lblPdfError->Caption = "Error exporting to PDF: " + Msg;
  }
  else
  {
	PanelPdfOk->Visible = true;
  }

  EnableCommonActions(true);
  ActionPdf->Enabled = true;
}

void __fastcall TFCustomPreview::ActionPdfExecute(TObject *Sender)
{
  if (!(PdfSaveDialog->Execute())) return;

  PdfProgressBar->Position = 0;
  lblPdfPage->Caption = "Initializing";
  EnableCommonActions(false);
  ActionPdf->Enabled = false;
  btnPdfCancel->Enabled = true;
  btnPdfCancel->Caption = "Cancel";

  PanelPdfOk->Visible = false;
  PanelPdfError->Visible = false;
  PanelPdf->Visible = true;

  PdfThread->Free();

  PdfThread = new TPdfThread(
	Xls,
	PdfProgressFeedback,
	PdfFinalFeedback,
	PdfSaveDialog->FileName,
	cbAllSheets->Checked);

  PdfThread->Start();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::PrintProgressFeedback(int Progress, String Msg)
{
  PrintProgressBar->Position = Progress;
  lblPrintPage->Caption = Msg;
}

void __fastcall TFCustomPreview::PrintFinalFeedback(bool Ok, String Msg)
{
  PanelPrinting->Visible = false;
  if (!Ok)
  {
	PanelPrintingError->Visible = true;
	lblPrintingError->Caption = "Error printing: " + Msg;
  }
  else
  {
	PanelPrintingOk->Visible = true;
  }

  EnableCommonActions(true);
  ActionPrint->Enabled = true;
}

void __fastcall TFCustomPreview::ActionPrintExecute(TObject *Sender)
{
  if (!(PrintDialog->Execute())) return;

  PrintProgressBar->Position = 0;
  lblPrintPage->Caption = "Initializing";
  EnableCommonActions(false);
  ActionPrint->Enabled = false;

  btnPrintCancel->Enabled = true;
  btnPrintCancel->Caption = "Cancel";

  PanelPrintingOk->Visible = false;
  PanelPrintingError->Visible = false;
  PanelPrinting->Visible = true;

  PrintingThread->Free();
  PrintingThread = new TPrintingThread(
	Xls,
	&PrintProgressFeedback,
	&PrintFinalFeedback,
	"",
	cbAllSheets->Checked);

  PrintingThread->Start();

}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnOpenGeneratedFileClick(TObject *Sender)
{
  ShellExecute(0, L"open", PdfSaveDialog->FileName.c_str(), L"", L"", SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPdfCancelClick(TObject *Sender)
{
  if (PdfThread == NULL) //it shouldn't really happen
  {
	PanelPdf->Visible = false;
	return;
  }
  btnPdfCancel->Enabled = false;
  btnPdfCancel->Caption = "Canceling...";
  PdfThread->Terminate(); //FlexCel will check that we set terminated, and exit as fast as it can.
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPrintCancelClick(TObject *Sender)
{
  if (PrintingThread == NULL) //it shouldn't really happen
  {
	PanelPrinting->Visible = false;
	return;
  }
  btnPrintCancel->Enabled = false;
  btnPrintCancel->Caption = "Canceling...";
  PrintingThread->Terminate(); //FlexCel will check that we set terminated, and exit as fast as it can.
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPdfErrorCloseClick(TObject *Sender)
{
  PanelPdfError->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPrintingErrorCloseClick(TObject *Sender)
{
  PanelPrintingError->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPrintOkCloseClick(TObject *Sender)
{
  PanelPrintingOk->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btnPdfOkCloseClick(TObject *Sender)
{
  PanelPdfOk->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::UpdatePages()
{
  edPage->Text = IntToStr(MainPreview->StartPage);
  lblTotalPages->Caption = "of " + IntToStr(MainPreview->TotalPages);
}

void __fastcall TFCustomPreview::ChangePages()
{
  int pn;
  if (TryStrToInt(Trim(edPage->Text), pn)) MainPreview->StartPage = pn;
}

void __fastcall TFCustomPreview::DPIChanged()
{
  MainPreview->InvalidatePreview();
}

void __fastcall TFCustomPreview::MainPreviewStartPageChanged(TObject *Sender)
{
  UpdatePages();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::edPageExit(TObject *Sender)
{
  ChangePages();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::edPageKeyPress(TObject *Sender, System::WideChar &Key)

{
  if (Key == (char)13)
  {
	ChangePages();
	Key = (char)0;
  }
  else if (Key == (char)27)
  {
	UpdatePages();
	Key = (char)0;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::UpdateZoom()
{
  ActionZoom->Caption = IntToStr((int)(MainPreview->Zoom * 100)) + "%";
  if (MainPreview->AutofitPreview == TAutofitPreview::None) UpdateAutofitText();
  ChangingZoom = true;
  __try
  {
	TrackBarZoom->Position = (int)(MainPreview->Zoom * 100);
  }
  __finally
  {
	ChangingZoom = false;
  }
}
void __fastcall TFCustomPreview::MainPreviewZoomChanged(TObject *Sender)
{
   UpdateZoom();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::ActionZoomExecute(TObject *Sender)
{
  System::Types::TPoint p;
  p.X = ToolButtonZoom->Left;
  p.Y = ToolButtonZoom->Top + ToolButtonZoom->Height;
  p = ToolButtonZoom->ClientToParent(p, FCustomPreview);

  PanelZoom->Left = p.X;
  PanelZoom->Top = p.Y;
  PanelZoom->Visible = true;
  ActiveControl = TrackBarZoom;

}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btn25Click(TObject *Sender)
{
  MainPreview->Zoom = 0.25;
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btn50Click(TObject *Sender)
{
  MainPreview->Zoom = 0.50;
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btn75Click(TObject *Sender)
{
  MainPreview->Zoom = 0.75;
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btn100Click(TObject *Sender)
{
  MainPreview->Zoom = 1;
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::btn150Click(TObject *Sender)
{
  MainPreview->Zoom = 1.5;
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::TrackBarZoomChange(TObject *Sender)
{
  if (ChangingZoom) return; //avoid recursive calls.
  MainPreview->Zoom = TrackBarZoom->Position / 100.0;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::TrackBarZoomEnter(TObject *Sender)
{
  PanelZoom->SetFocus();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::PanelZoomExit(TObject *Sender)
{
  PanelZoom->Visible = false;
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::UpdateAutofitText()
{
  switch (MainPreview->AutofitPreview)
  {
	case TAutofitPreview::None: ActionAutofit->Caption = "No Autofit"; break;
	case TAutofitPreview::Width: ActionAutofit->Caption = "Fit to Width"; break;
	case TAutofitPreview::Height: ActionAutofit->Caption = "Fit to Height"; break;
	case TAutofitPreview::Full: ActionAutofit->Caption = "Fit to Page"; break;
  }
}


void __fastcall TFCustomPreview::ActionAutofitExecute(TObject *Sender)
{
  if (!(dynamic_cast<TControl* >(Sender))) return;

  System::Types::TPoint PopPoint;
  PopPoint.X = ((TControl*)Sender)->Left;
  PopPoint.Y = ((TControl*)Sender)->Top + ((TControl*)Sender)->Height;
  PopPoint = ClientToScreen(PopPoint);
  AutofitMenu->Popup(PopPoint.X, PopPoint.Y);

}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::NoAutofit1Click(TObject *Sender)
{
  MainPreview->AutofitPreview = TAutofitPreview::None;
  UpdateAutofitText();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::FittoWidth1Click(TObject *Sender)
{
  MainPreview->AutofitPreview = TAutofitPreview::Width;
  UpdateAutofitText();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::FittoHeight1Click(TObject *Sender)
{
  MainPreview->AutofitPreview = TAutofitPreview::Height;
  UpdateAutofitText();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::FittoPage1Click(TObject *Sender)
{
  MainPreview->AutofitPreview = TAutofitPreview::Full;
  UpdateAutofitText();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::ActionRecalcExecute(TObject *Sender)
{
  Xls->Recalc();
  MainPreview->InvalidatePreview();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::ActionGridLinesExecute(TObject *Sender)
{
  if (cbAllSheets->Checked)
  {
	int SaveActiveSheet = Xls->ActiveSheet;
	for (int i = 1; i <= Xls->SheetCount; i++)
	{
	  Xls->ActiveSheet = i;
	  Xls->PrintGridLines = ActionGridLines->Checked;
	}
	Xls->ActiveSheet = SaveActiveSheet;
  }
  else
  {
	Xls->PrintGridLines = ActionGridLines->Checked;
  }
  MainPreview->InvalidatePreview();
}
//---------------------------------------------------------------------------

void __fastcall TFCustomPreview::ActionHeadingsExecute(TObject *Sender)
{
  if (cbAllSheets->Checked)
  {
	int SaveActiveSheet = Xls->ActiveSheet;
	for (int i = 1; i <= Xls->SheetCount; i++)
	{
	  Xls->ActiveSheet = i;
	  Xls->PrintHeadings = ActionHeadings->Checked;
	}
	Xls->ActiveSheet = SaveActiveSheet;
  }
  else
  {
	Xls->PrintHeadings = ActionHeadings->Checked;
  }
  MainPreview->InvalidatePreview();
}
//---------------------------------------------------------------------------



UPasswordDialog.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UPasswordDialog.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

//---------------------------------------------------------------------------
__fastcall TPasswordDialog::TPasswordDialog(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

String __fastcall TPasswordDialog::Password()
{
   return edPassword->Text;
}

void __fastcall TPasswordDialog::SetFileName(const String FileName)
{
  lblFileName->Caption = ExtractFileName(FileName);
}


UPdfExporting.cpp

//---------------------------------------------------------------------------

#pragma hdrstop

#include "UPdfExporting.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

__fastcall TPdfThread::TPdfThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets)
	  : TProgressThread(aXls, aProgressFeedback, aFinalFeedback, aFileName, aAllSheets)
{
}


void __fastcall TPdfThread::Execute()
{
  TFlexCelPdfExport* pdf = new TFlexCelPdfExport(Xls, true);
  try
  {
	pdf->AfterGeneratePage = ShowProgress;

	if (AllSheets)
	{
	  TFileStream* fs = new TFileStream(FileName, fmCreate);
	  try
	  {
		pdf->BeginExport(fs);
		pdf->PageLayout = TPageLayout::Outlines;
		pdf->ExportAllVisibleSheets(false, TPath::GetFileNameWithoutExtension(FileName));
		pdf->EndExport();
	  }
	  __finally
	  {
		fs->Free();
	  }
	}
	else
	{
	  pdf->Export(FileName);
	}
  }
  __finally
  {
	pdf->Free();
  }
}

#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
void __fastcall TPdfThread::ShowProgress(const TObject* sender, const TPageEventArgs* e)
#else
void __fastcall TPdfThread::ShowProgress(TObject* const sender, TPageEventArgs* const e)
#endif
{
  TFlexCelPdfExportProgress* Prog = ((TFlexCelPdfExport*)sender)->Progress;
  int Percent;
  if (Prog->TotalPage == 0) Percent = 100; else Percent = (int)(Prog->Page * 100.0 / Prog->TotalPage);

  ProgressFeedback_percent = Percent;
  ProgressFeedback_msg = String(L"Page ") + IntToStr(Prog->Page) + L" of " + IntToStr(Prog->TotalPage);
  Synchronize(&DoProgressFeedback);

}


UPrinting.cpp

//---------------------------------------------------------------------------

#pragma hdrstop

#include "UPrinting.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

__fastcall TPrintingThread::TPrintingThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets)
	  : TProgressThread(aXls, aProgressFeedback, aFinalFeedback, aFileName, aAllSheets)
{
}


void __fastcall TPrintingThread::Execute()
{
  TFlexCelPrintDocument* doc = new TFlexCelPrintDocument(Xls);
  try
  {
	doc->AfterGeneratePage = ShowProgress;

	if (AllSheets)
	{
		doc->BeginPrint();
		try
		{
		  doc->PrintAllVisibleSheets(false);
		}
		__finally
		{
		  doc->EndPrint();
		}
	}
	else
	{
	  doc->Print();
	}
  }
  __finally
  {
	doc->Free();
  }
}

#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
void __fastcall TPrintingThread::ShowProgress(const TObject* sender, const TPrintPageEventArgs* e)
#else
void __fastcall TPrintingThread::ShowProgress(TObject* const sender, TPrintPageEventArgs* const e)
#endif
{
  TFlexCelPrintingProgress* Prog = ((TFlexCelPrintDocument*)sender)->Progress;
  int Percent;
  if (Prog->TotalPage == 0) Percent = 100; else Percent = (int)(Prog->Page * 100.0 / Prog->TotalPage);

  ProgressFeedback_percent = Percent;
  ProgressFeedback_msg = String(L"Page ") + IntToStr(Prog->Page) + L" of " + IntToStr(Prog->TotalPage);
  Synchronize(&DoProgressFeedback);
}




UProgressThread.cpp

//---------------------------------------------------------------------------

#pragma hdrstop

#include "UProgressThread.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

__fastcall TProgressThread::TProgressThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets): TThread(true)
{
  FreeOnTerminate = false;
  Canceled = false;
  Xls = aXls;
  ProgressFeedback = aProgressFeedback;
  FinalFeedback = aFinalFeedback;
  FileName = aFileName;
  AllSheets = aAllSheets;

}

void __fastcall TProgressThread::TerminatedSet()
{
  TThread::TerminatedSet();
  Canceled = true;
}
//---------------------------------------------------------------------------

void __fastcall TProgressThread::DoTerminate()
{
  TThread::DoTerminate();
  FinalFeedback_msg = "";
  FinalFeedback_ok = !Canceled;
  if (FatalException != NULL)
  {
	FinalFeedback_ok = false;
	if (dynamic_cast<Exception*>(FatalException))
	{
	  FinalFeedback_msg = ((Exception*)FatalException)->Message;
	}
	else FinalFeedback_msg = "Unexpected error: " + FatalException->ClassName();
  }

  if (Canceled) FinalFeedback_msg = "Operation canceled by the user.";


  //DoTerminate runs in the thread context, not the main thread context as OnTerminate.
  Synchronize(&DoFinalFeedback);

}
//---------------------------------------------------------------------------

void __fastcall TProgressThread::DoFinalFeedback()
{
	FinalFeedback(FinalFeedback_ok, FinalFeedback_msg);
}

void __fastcall TProgressThread::DoProgressFeedback()
{
	ProgressFeedback(ProgressFeedback_percent, ProgressFeedback_msg);
}


UCustomPreview.h

//---------------------------------------------------------------------------

#ifndef UCustomPreviewH
#define UCustomPreviewH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ActnList.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.Dialogs.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.ImgList.hpp>
#include <Vcl.Menus.hpp>
#include <Vcl.ToolWin.hpp>
#include "FlexCel.Preview.hpp"
#include "FlexCel.Render.hpp"
#include "FlexCel.XlsAdapter.hpp"
#include "FlexCel.VCLSupport.hpp"
#include "FlexCel.Core.hpp"
#include "UPdfExporting.h"
#include "UPrinting.h"
#include "UPasswordDialog.h"
#include "UFlexCelHDPI.hpp"
//---------------------------------------------------------------------------
class TFCustomPreview : public TForm
{
__published:	// IDE-managed Components
	TSplitter *Splitter1;
	TPanel *Panel1;
	TSplitter *Splitter2;
	TPanel *Panel3;
	TCheckBox *cbAllSheets;
	TPanel *Panel4;
	TPanel *Panel5;
	TPanel *Panel6;
	TFlexCelPreviewer *Thumbs;
	TPanel *PanelSheets;
	TListBox *lbSheets;
	TPanel *Panel2;
	TFlexCelPreviewer *MainPreview;
	TPanel *PanelPrinting;
	TLabel *lblProgressTask;
	TLabel *lblPrintPage;
	TProgressBar *PrintProgressBar;
	TButton *btnPrintCancel;
	TPanel *PanelPdf;
	TLabel *Label1;
	TLabel *lblPdfPage;
	TProgressBar *PdfProgressBar;
	TButton *btnPdfCancel;
	TPanel *PanelPdfError;
	TLabel *lblPdfError;
	TButton *btnPdfErrorClose;
	TPanel *PanelPrintingError;
	TLabel *lblPrintingError;
	TButton *btnPrintingErrorClose;
	TPanel *PanelPrintingOk;
	TLabel *Label2;
	TButton *btnPrintOkClose;
	TPanel *PanelPdfOk;
	TLabel *Label3;
	TButton *btnPdfOkClose;
	TButton *btnOpenGeneratedFile;
	TPanel *FlowPanel1;
	TToolBar *ToolBar2;
	TToolButton *ToolButton14;
	TToolButton *ToolButton15;
	TToolButton *ToolButton16;
	TToolButton *ToolButton17;
	TToolButton *ToolButton18;
	TPanel *PanelSelectPage;
	TLabel *Label4;
	TLabel *lblTotalPages;
	TEdit *edPage;
	TToolBar *ToolBar4;
	TToolButton *ToolButtonZoom;
	TToolButton *ToolButton27;
	TToolButton *ToolButton28;
	TToolButton *ToolButton29;
	TToolButton *ToolButton30;
	TToolButton *ToolButton31;
	TToolButton *ToolButton32;
	TPanel *PanelZoom;
	TTrackBar *TrackBarZoom;
	TButton *btn25;
	TButton *btn50;
	TButton *btn75;
	TButton *btn100;
	TButton *btn150;
	TPanel *PanelPrint;
	TButton *btnPrint;
	TActionList *Actions;
	TAction *ActionOpen;
	TAction *ActionAutofit;
	TAction *ActionRecalc;
	TAction *ActionHeadings;
	TAction *ActionPdf;
	TAction *ActionPrint;
	TAction *ActionGridLines;
	TAction *ActionClose;
	TAction *ActionZoom;
	TOpenDialog *OpenDialog;
	TImageList *ToolbarImages;
	TImageList *ToolbarImagesDisabled;
	TSaveDialog *PdfSaveDialog;
	TPrintDialog *PrintDialog;
	TPopupMenu *AutofitMenu;
	TMenuItem *NoAutofit1;
	TMenuItem *FittoWidth1;
	TMenuItem *FittoHeight1;
	TMenuItem *FittoPage1;
	TImageList *ToolbarImages_100Scale;
	TImageList *ToolbarImages_300Scale;
	TToolBar *ToolBarAutofit;
	TToolButton *ToolButton1;
	void __fastcall FormCreate(TObject *Sender);
	void __fastcall ActionCloseExecute(TObject *Sender);
	void __fastcall ActionOpenExecute(TObject *Sender);
	void __fastcall cbAllSheetsClick(TObject *Sender);
	void __fastcall lbSheetsClick(TObject *Sender);
	void __fastcall ActionPdfExecute(TObject *Sender);
	void __fastcall ActionPrintExecute(TObject *Sender);
	void __fastcall btnOpenGeneratedFileClick(TObject *Sender);
	void __fastcall btnPdfCancelClick(TObject *Sender);
	void __fastcall btnPrintCancelClick(TObject *Sender);
	void __fastcall btnPdfErrorCloseClick(TObject *Sender);
	void __fastcall btnPrintingErrorCloseClick(TObject *Sender);
	void __fastcall btnPrintOkCloseClick(TObject *Sender);
	void __fastcall btnPdfOkCloseClick(TObject *Sender);
	void __fastcall MainPreviewStartPageChanged(TObject *Sender);
	void __fastcall edPageExit(TObject *Sender);
	void __fastcall edPageKeyPress(TObject *Sender, System::WideChar &Key);
	void __fastcall MainPreviewZoomChanged(TObject *Sender);
	void __fastcall ActionZoomExecute(TObject *Sender);
	void __fastcall btn25Click(TObject *Sender);
	void __fastcall btn50Click(TObject *Sender);
	void __fastcall btn75Click(TObject *Sender);
	void __fastcall btn100Click(TObject *Sender);
	void __fastcall btn150Click(TObject *Sender);
	void __fastcall TrackBarZoomChange(TObject *Sender);
	void __fastcall TrackBarZoomEnter(TObject *Sender);
	void __fastcall PanelZoomExit(TObject *Sender);
	void __fastcall ActionAutofitExecute(TObject *Sender);
	void __fastcall NoAutofit1Click(TObject *Sender);
	void __fastcall FittoWidth1Click(TObject *Sender);
	void __fastcall FittoHeight1Click(TObject *Sender);
	void __fastcall FittoPage1Click(TObject *Sender);
	void __fastcall ActionRecalcExecute(TObject *Sender);
	void __fastcall ActionGridLinesExecute(TObject *Sender);
	void __fastcall ActionHeadingsExecute(TObject *Sender);
	void __fastcall FormDestroy(TObject *Sender);
private:	// User declarations
	TExcelFile *Xls;
	TFlexCelImgExport *ImgExport;
	TPrintingThread *PrintingThread;
	TPdfThread *PdfThread;
	int DisabledCount;
	bool ChangingZoom;
	void __fastcall EnableCommonActions(bool Enable);
	void __fastcall LoadFile(String FileName);
#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older, this should be "TOnPasswordEventArgs * const e".
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
	void __fastcall GetPassword(const TOnPasswordEventArgs *e);
#else
	void __fastcall GetPassword(TOnPasswordEventArgs* const e);
#endif

	void __fastcall UpdateZoom();
	void __fastcall UpdateAutofitText();
	void __fastcall UpdatePages();
	void __fastcall ChangePages();
	void __fastcall DPIChanged();
	void __fastcall PdfFinalFeedback(bool Ok, String  Msg);
	void __fastcall PdfProgressFeedback(int Progress, String Msg);
	void __fastcall PrintFinalFeedback(bool Ok, String  Msg);
	void __fastcall PrintProgressFeedback(int Progress, String Msg);

public:		// User declarations
	__fastcall TFCustomPreview(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFCustomPreview *FCustomPreview;
//---------------------------------------------------------------------------
#endif

UPasswordDialog.h

//---------------------------------------------------------------------------

#ifndef UPasswordDialogH
#define UPasswordDialogH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TPasswordDialog : public TForm
{
__published:	// IDE-managed Components
	TLabel *Label1;
	TLabel *lblFileName;
	TButton *Button1;
	TButton *Button2;
	TEdit *edPassword;
private:	// User declarations
public:		// User declarations
	__fastcall TPasswordDialog(TComponent* Owner);

	__fastcall String Password();
	__fastcall void SetFileName(const String FileName);

};
//---------------------------------------------------------------------------
extern PACKAGE TPasswordDialog *PasswordDialog;
//---------------------------------------------------------------------------
#endif

UPdfExporting.h

//---------------------------------------------------------------------------

#ifndef UPdfExportingH
#define UPdfExportingH
//---------------------------------------------------------------------------

#include <IOUtils.hpp>
#include "UProgressThread.h"
#include "FlexCel.Pdf.hpp"
#include "FlexCel.Render.hpp"
#include "FlexCel.Core.hpp"
//---------------------------------------------------------------------------
class TPdfThread: public TProgressThread
{
  public:
	__fastcall TPdfThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets);


  virtual void __fastcall Execute();
#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
void __fastcall ShowProgress(const TObject* sender, const TPageEventArgs* e);
#else
void __fastcall ShowProgress(TObject* const sender, TPageEventArgs* const e);
#endif
};
//---------------------------------------------------------------------------

#endif

UPrinting.h

//---------------------------------------------------------------------------

#ifndef UPrintingH
#define UPrintingH
//---------------------------------------------------------------------------
#include "UProgressThread.h"
#include "FlexCel.Render.hpp"
//---------------------------------------------------------------------------
class TPrintingThread: public TProgressThread
{
  public:
	__fastcall TPrintingThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets);


  virtual void __fastcall Execute();
#if (__BORLANDC__ < 0x0650) //XE2 or older
//C++ builder header translations are wrong for XE2 or older
//see http://qc.embarcadero.com/wc/qcmain.aspx?d=42782
void __fastcall ShowProgress(const TObject* sender, const TPrintPageEventArgs* e);
#else
void __fastcall ShowProgress(TObject* const sender, TPrintPageEventArgs* const e);
#endif
};
//---------------------------------------------------------------------------
#endif

UProgressThread.h

//---------------------------------------------------------------------------

#ifndef UProgressThreadH
#define UProgressThreadH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include "FlexCel.Core.hpp"

typedef void __fastcall (__closure *TFeedbackMethod)(int Progress, String Msg);
typedef void __fastcall (__closure *TFinalFeedbackMethod)(bool Ok, String Msg);

//---------------------------------------------------------------------------
class TProgressThread: public TThread
{
  private:
	String FinalFeedback_msg;
	bool FinalFeedback_ok;
	void __fastcall DoFinalFeedback();
  protected:
	String ProgressFeedback_msg;
	bool ProgressFeedback_percent;
	void __fastcall DoProgressFeedback();

  protected:
	TFeedbackMethod ProgressFeedback;
	TFinalFeedbackMethod FinalFeedback;
	TExcelFile *Xls;
	String FileName;
	bool AllSheets;
	bool Canceled;

	virtual void __fastcall TerminatedSet();
	virtual void __fastcall DoTerminate();

  public:
	__fastcall TProgressThread(TExcelFile *aXls, TFeedbackMethod aProgressFeedback,
	  TFinalFeedbackMethod aFinalFeedback, String aFileName, bool aAllSheets);

};
//---------------------------------------------------------------------------
#endif