// SDKPrint.cpp : implementation file
//

#include "stdafx.h"
#include "afxdialogex.h"
#include "windows.h"
#include "winspool.h"
#include "DTC_C++Demo.h"
#include "MainSheet.h"
#include "PrinterSettings.h"
#include "PrintDemo.h"
#include <GdiPlus.h>
using namespace Gdiplus;

//#############################################################################

// CPrintDemo dialog

IMPLEMENT_DYNAMIC(CPrintDemo, CPropertyPage)

CPrintDemo::CPrintDemo()
	: CPropertyPage(CPrintDemo::IDD)
{
	CardFront = NULL;
	CardBack  = NULL;
}

CPrintDemo::~CPrintDemo()
{
	if (CardFront)
	{
		CardFront->DestroyWindow();
		delete CardFront;
	}

	if (CardBack)
	{
		CardBack->DestroyWindow();
		delete CardBack;
	}
}

void CPrintDemo::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_FRONT_CHECK, CardFrontTick);
	DDX_Control(pDX, IDC_BACK_CHECK, CardBackTick);
	DDX_Control(pDX, IDC_BTN_PRINT, PrintDemoBtn);
	DDX_Control(pDX, IDC_TAB, CardTab);
	DDX_Control(pDX, IDC_GDIPRINT, GDIPrint);
	DDX_Control(pDX, IDC_600DPI_CHECK, Functions600DPI);
}

BEGIN_MESSAGE_MAP(CPrintDemo, CPropertyPage)
	ON_BN_CLICKED(IDC_BTN_PRINT,   &CPrintDemo::OnBnClickedBtnPrint)
	ON_BN_CLICKED(IDC_FRONT_CHECK, &CPrintDemo::OnBnClickedFrontCheck)
	ON_BN_CLICKED(IDC_BACK_CHECK,  &CPrintDemo::OnBnClickedBackCheck)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB, &CPrintDemo::OnTcnSelchangeTab)
	ON_NOTIFY(TCN_SELCHANGING, IDC_TAB, &CPrintDemo::OnTcnSelchangingTab)
	ON_BN_CLICKED(IDC_PRINTERPREFS, &CPrintDemo::OnBnClickedPrinterPrefs)
	ON_BN_CLICKED(IDC_GDIPRINT, &CPrintDemo::OnBnClickedGdiprint)
END_MESSAGE_MAP()

//#############################################################################

const TABLE_ENTRY CPrintDemo::ColourTable[] = {_T("Red"),		ID_COLOUR_RED,
                                               _T("Green"),		ID_COLOUR_GREEN,
                                               _T("Blue"),		ID_COLOUR_BLUE,
                                               _T("Cyan"),		ID_COLOUR_CYAN,
                                               _T("Magenta"),	ID_COLOUR_MAGENTA,
                                               _T("Yellow"),	ID_COLOUR_YELLOW,
                                               _T("White"),		ID_COLOUR_WHITE,
                                               _T("Black"),		ID_COLOUR_BLACK,
                                               _T("Transparent"), HOLLOW_BRUSH,		//Only used in Shape Fill
};

const TABLE_ENTRY CPrintDemo::ShapeTable[] = {_T("Rectangle"),	ID_SHAPE_RECTANGLE,
                                              _T("Ellipse"),	ID_SHAPE_ELLIPSE,
                                              _T("RoundRect"),	ID_SHAPE_ROUNDRECT,
                                              _T("Pie"),		ID_SHAPE_PIE,
                                              _T("Chord"),		ID_SHAPE_CHORD,
};

//#############################################################################
// CPrintDemo message handlers
//#############################################################################

BOOL CPrintDemo::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	Parent = ((CMainSheet *)GetParent());

	CardFront = new CCardFront(this);
	CardBack  = new CCardBack(this);

	CardFront->Create(CCardFront::IDD, &CardTab);
	CardBack->Create(CCardBack::IDD, &CardTab);

	RECT r;
	TCITEM tci;
	CardTab.GetClientRect(&r);
	tci.mask    = TCIF_TEXT;
	tci.iImage  = -1;
	tci.pszText = _T("Front");
	CardTab.InsertItem(0, &tci);

	tci.pszText = _T("Back");
	CardTab.InsertItem(1, &tci);

	OnTcnSelchangeTab(NULL, NULL);

	CardFrontTick.SetCheck(TRUE);
	CardBackTick.SetCheck(FALSE);
	OnBnClickedFrontCheck();
	OnBnClickedBackCheck();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

//****************************************************************************

BOOL CPrintDemo::OnSetActive()
{
	CPropertyPage::OnSetActive();

	Functions600DPI.ShowWindow(PrinterIs600DPICapable());
	Functions600DPI.SetCheck(ResolutionIs600());

	return TRUE;  // return TRUE  unless you set the focus to a control
}

//****************************************************************************

BOOL CPrintDemo::ResolutionIs600()
{
	BYTE Value;

	PFNIDRESOLUTION pFnResolution = (PFNIDRESOLUTION)GetProcAddress(Parent->hLib, "ID_Resolution");
	(*pFnResolution)(Parent->hSession, ID_READ, &Value);

	return (Value != 0);
}

//****************************************************************************

void CPrintDemo::OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult)
{
	RECT rc;
	CardTab.GetItemRect(0,&rc);

	CDialog *pTab;
	switch (CardTab.GetCurSel())
	{
	case 0: pTab = CardFront; break;
	case 1: pTab = CardBack;  break;
	}

	pTab->SetWindowPos(NULL,
					   rc.left + 1,
					   rc.bottom + 1,
					   0,
					   0,
					   SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
	pTab->SetFocus();
}

//****************************************************************************

void CPrintDemo::OnTcnSelchangingTab(NMHDR *pNMHDR, LRESULT *pResult)
{
	switch (CardTab.GetCurSel())
	{
	case 0: CardFront->ShowWindow(SW_HIDE); break;
	case 1: CardBack->ShowWindow(SW_HIDE);  break;
	}
}

//****************************************************************************

void CPrintDemo::OnBnClickedFrontCheck()
{
	BOOL bControl = (CardFrontTick.GetCheck() == BST_CHECKED);

	CardFront->EnableGetSetControls(bControl);

	if (bControl || (CardBackTick.GetCheck() == BST_CHECKED))
	{
		PrintDemoBtn.EnableWindow(TRUE);
	}
	else
	{
		PrintDemoBtn.EnableWindow(FALSE);
	}
}

void CPrintDemo::OnBnClickedBackCheck()
{
	BOOL bControl = (CardBackTick.GetCheck() == BST_CHECKED);

	CardBack->EnableGetSetControls(bControl);

	if (bControl || (CardFrontTick.GetCheck() == BST_CHECKED))
	{
		PrintDemoBtn.EnableWindow(TRUE);
	}
	else
	{
		PrintDemoBtn.EnableWindow(FALSE);
	}
}

void CPrintDemo::OnBnClickedGdiprint()
{
	BOOL visible = (GDIPrint.GetCheck() != BST_CHECKED);

	CardFront->TextResin.ShowWindow(visible);
	CardFront->ShapeResin.ShowWindow(visible);
	CardFront->LineResin.ShowWindow(visible);
	CardFront->ImageResin.ShowWindow(visible);
	CardBack->TextResin.ShowWindow(visible);
	CardBack->ShapeResin.ShowWindow(visible);
	CardBack->LineResin.ShowWindow(visible);
	CardBack->ImageResin.ShowWindow(visible);
}

//****************************************************************************

static BOOL FileExists
(
	LPCTSTR szPath
)
{
	DWORD dwAttrib = GetFileAttributes(szPath);

	return (dwAttrib != INVALID_FILE_ATTRIBUTES
			&& !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

//****************************************************************************

BOOL CPrintDemo::PrinterIs600DPICapable()
{
	return (   (Parent->PrinterType == ID_GENERATION2)
		   && ((Parent->PrinterModel & ID_FN_600DPI) != 0));
}

//****************************************************************************

void CPrintDemo::GDIPrintText
(
	HDC        hDC, 
	CComboBox *pencolour,
	CEdit     *size,
	CButton   *bold,
	CButton   *italic,
	CButton   *underline,
	CButton   *strikeout,
	CEdit     *textX,
	CEdit     *textY,
	CEdit     *text
)
{

	//Set transparent mode
	int old_bk_mode = GetBkMode(hDC);
	SetBkMode(hDC, TRANSPARENT);

	//Select text in the new colour
	COLORREF oldColour = SetTextColor(hDC, ColourTable[pencolour->GetCurSel()].Reference);

#define FONT _T("Comic Sans MS")
	HFONT hFontOld, hFont;
	LOGFONT LogFont;
	SecureZeroMemory(&LogFont, sizeof(LogFont));

	CString temp;
	size->GetWindowText(temp);
	LogFont.lfHeight     = -MulDiv(_ttoi(temp), GetDeviceCaps(PrinterDC, LOGPIXELSY), 72);
	LogFont.lfEscapement = 0;
			
	if (bold->GetCheck()      == BST_CHECKED) LogFont.lfWeight    = FW_BOLD;
	if (italic->GetCheck()    == BST_CHECKED) LogFont.lfItalic    = TRUE;
	if (underline->GetCheck() == BST_CHECKED) LogFont.lfUnderline = TRUE;
	if (strikeout->GetCheck() == BST_CHECKED) LogFont.lfStrikeOut = TRUE;
	LogFont.lfQuality = PROOF_QUALITY;
	_tcscpy_s(LogFont.lfFaceName, max(_tcslen(FONT), _countof(LogFont.lfFaceName)), FONT);
	LogFont.lfCharSet = DEFAULT_CHARSET;

	//Create the font object
	hFont = CreateFontIndirect(&LogFont);
	hFontOld = (HFONT)SelectObject(hDC, hFont);

	//Write the text to the canvas
	CString X, Y, outstr;
	textX->GetWindowText(X);
	textY->GetWindowText(Y);
	text->GetWindowText(outstr);
	outstr += "(via GDI)";
	TextOut(hDC, _ttoi(X), _ttoi(Y), outstr.GetBuffer(), outstr.GetLength());

	SetBkMode(hDC, old_bk_mode);
	SetTextColor(hDC, oldColour);
	SelectObject(hDC, hFontOld);
	DeleteObject(hFont);
}

//****************************************************************************

void CPrintDemo::GDIPrintShape
(
	HDC        hDC,
	CComboBox *shape,
	CComboBox *shapepen,
	CEdit     *penwidth,
	CComboBox *shapebrush,
	CEdit     *editleft,
	CEdit     *edittop,
	CEdit     *editright,
	CEdit     *editbottom
)
{
	//Create pen in the new colour, and select it
	HPEN oldPen, newPen;
	CString width;
	penwidth->GetWindowText(width);
	newPen = CreatePen(PS_SOLID, _ttoi(width), ColourTable[shapepen->GetCurSel()].Reference);
	oldPen = (HPEN)SelectObject(hDC, newPen);

	HBRUSH oldBrush, newBrush;
	if (ColourTable[shapebrush->GetCurSel()].Reference == ID_TRANSPARENT)
	{
		//Select the transparent brush
		oldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
	}
	else
	{
		//Create brush in the new colour, and select it
		newBrush = CreateSolidBrush(ColourTable[shapebrush->GetCurSel()].Reference);
		oldBrush = (HBRUSH)SelectObject(hDC, newBrush);
	}

	CString left, top, right, bottom;
	editleft->GetWindowText(left);
	edittop->GetWindowText(top);
	editright->GetWindowText(right);
	editbottom->GetWindowText(bottom);
	switch (ShapeTable[shape->GetCurSel()].Reference)
	{
	case ID_SHAPE_RECTANGLE:
		Rectangle(hDC, _ttoi(left), _ttoi(top), _ttoi(right), _ttoi(bottom));
		break;

	case ID_SHAPE_ELLIPSE:
		Ellipse(hDC, _ttoi(left), _ttoi(top), _ttoi(right), _ttoi(bottom));
		break;

	case ID_SHAPE_ROUNDRECT:
		RoundRect(hDC, _ttoi(left), _ttoi(top), _ttoi(right), _ttoi(bottom), 50, 50);
		break;

	case ID_SHAPE_PIE:
		//Use hard coded values for simplicity, since we havent got p1, p2, p3 and p4 on GUI
		Pie(hDC, 40, 20, 800, 500, 0, 0, 700, 115); 
		break;

	case ID_SHAPE_CHORD:
		//Use hard coded values for simplicity, since we havent got p1, p2, p3 and p4 on GUI
		Chord(hDC, 40, 20, 800, 500, 0, 0, 700, 115);
		break;
	}

	//Restore the original settings
	SelectObject(hDC, oldBrush);
	SelectObject(hDC, oldPen);
	DeleteObject(newPen);
	if (ColourTable[CardFront->ShapeBrush.GetCurSel()].Reference != ID_TRANSPARENT) 
		DeleteObject(newBrush);
}

//****************************************************************************

void CPrintDemo::GDIPrintLine
(
	HDC        hDC, 
	CComboBox *pencolour,
	CEdit     *penwidth,
	CEdit     *beginX,
	CEdit     *beginY,
	CEdit     *finishX,
	CEdit     *finishY
)
{
	HPEN oldPen, newPen;
	CString width;
	penwidth->GetWindowText(width);
	newPen = CreatePen(PS_DOT, _ttoi(width), ColourTable[pencolour->GetCurSel()].Reference);
	oldPen = (HPEN)SelectObject(hDC, newPen);

	//Draw the line
	CString startX, startY, endX, endY;
	beginX->GetWindowText(startX);
	beginY->GetWindowText(startY);
	finishX->GetWindowText(endX);
	finishY->GetWindowText(endY);
	MoveToEx(hDC, _ttoi(startX), _ttoi(startY), NULL);
	LineTo(hDC, _ttoi(endX), _ttoi(endY));

	//Restore the original settings
	SelectObject(hDC, oldPen);
	DeleteObject(newPen);
}

//****************************************************************************

void CPrintDemo::GDIPrintImage
(
	HDC      hDC, 
	CString  filename,
	CEdit   *left,
	CEdit   *top,
	CEdit   *P1,
	CEdit   *P2
)
{
	ULONG_PTR m_gdiplusToken;
	GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

	if ((!filename.IsEmpty())
	&&  FileExists(filename))
	{
		Bitmap image(filename);
		int width  = image.GetWidth();
		int height = image.GetHeight();

		//Adjust the Image size, scaling or constraining as required
		CString temp;
		P1->GetWindowText(temp);
		int p1 = _ttoi(temp);
		P2->GetWindowText(temp);
		int p2 = _ttoi(temp);
		if (p1 == 0)
		{
			//No scaling or constraining - Use original size of image
		}
		else if (p2 == 0)
		{
			//Scaling - Modify image dimensions by scaling with the given percentage
			//(p1), while maintaining the aspect ratio
			width  = (width  * p1) / 100;
			height = (height * p1) / 100;
		}
		else
		{
			//Constraining - Restrict the image to the given rectangle, ignoring aspect ratio
			//(p1 = new width, p2 = new height)
			width  = p1;
			height = p2;
		}

		int cornerX, cornerY;
		left->GetWindowText(temp);
		cornerX = _ttoi(temp);
		top->GetWindowText(temp);
		cornerY = _ttoi(temp);

		Graphics graphics(hDC);
		graphics.SetPageUnit(UnitPixel);
		Rect destRect(cornerX, cornerY, width, height);
		graphics.DrawImage(&image, destRect);
	}
}

//****************************************************************************

void CPrintDemo::PrintUsingGDI()
{
	PFNIDUPDC pFnUpdateDC = (PFNIDUPDC)GetProcAddress(Parent->hLib, "ID_UpdateDC");

	HDC hDC = PrinterDC;
	int SDKReturn = (*pFnUpdateDC)(Parent->hSession, hDC);
	if (SDKReturn != ID_SUCCESS)
	{
		DISPLAY_ERROR(UpdateDC, SDKReturn);
		return;
	}
    
    DOCINFO di;
    di.cbSize      = sizeof(di);
    di.lpszDocName = L"ID SDK";
    di.lpszOutput  = NULL;

	StartDoc(hDC, &di);

	if (CardFrontTick.GetCheck() == BST_CHECKED)
	{
		StartPage(hDC);
	
		CString strcmd;
		if (CardFront->TextEnabled.GetCheck())
		{
			GDIPrintText(hDC, 
						 &CardFront->TextColour,
						 &CardFront->TextSize,
						 &CardFront->TextBold,
						 &CardFront->TextItalic,
						 &CardFront->TextUnderline,
						 &CardFront->TextStrikeout,
						 &CardFront->TextX,
						 &CardFront->TextY,
						 &CardFront->Text);
		}

		if (CardFront->ShapeEnabled.GetCheck())
		{
			GDIPrintShape(hDC,
						  &CardFront->Shape,
						  &CardFront->ShapePen,
						  &CardFront->ShapePenWidth,
						  &CardFront->ShapeBrush,
						  &CardFront->ShapeLeft,
						  &CardFront->ShapeTop,
						  &CardFront->ShapeRight,
						  &CardFront->ShapeBottom);
		}

		if (CardFront->LineEnabled.GetCheck())
		{
			GDIPrintLine(hDC,
						 &CardFront->LineColour,
						 &CardFront->LineWidth,
						 &CardFront->LineStartX,
						 &CardFront->LineStartY,
						 &CardFront->LineEndX,
						 &CardFront->LineEndY);
		}

		if (CardFront->ImageEnabled.GetCheck())
		{
			if (CardFront->ImageFilename.GetWindowTextLength())
			{
				GDIPrintImage(hDC,
							  CardFront->Image,
							  &CardFront->ImageLeft,
							  &CardFront->ImageTop,
							  &CardFront->ImageP1,
							  &CardFront->ImageP2);
			}
		}

		EndPage(hDC);
	}
	
	if (CardBackTick.GetCheck() == BST_CHECKED)
	{
		StartPage(hDC);
	
		if (CardBack->TextEnabled.GetCheck())
		{
			GDIPrintText(hDC, 
						 &CardBack->TextColour,
						 &CardBack->TextSize,
						 &CardBack->TextBold,
						 &CardBack->TextItalic,
						 &CardBack->TextUnderline,
						 &CardBack->TextStrikeout,
						 &CardBack->TextX,
						 &CardBack->TextY,
						 &CardBack->Text);
		}

		if (CardBack->ShapeEnabled.GetCheck())
		{
			GDIPrintShape(hDC,
						  &CardBack->Shape,
						  &CardBack->ShapePen,
						  &CardBack->ShapePenWidth,
						  &CardBack->ShapeBrush,
						  &CardBack->ShapeLeft,
						  &CardBack->ShapeTop,
						  &CardBack->ShapeRight,
						  &CardBack->ShapeBottom);
		}

		if (CardBack->LineEnabled.GetCheck())
		{
			GDIPrintLine(hDC,
						 &CardBack->LineColour,
						 &CardBack->LineWidth,
						 &CardBack->LineStartX,
						 &CardBack->LineStartY,
						 &CardBack->LineEndX,
						 &CardBack->LineEndY);
		}

		if (CardBack->ImageEnabled.GetCheck())
		{
			if (CardBack->ImageFilename.GetWindowTextLength() != 0)
			{
				GDIPrintImage(hDC,
							  CardBack->Image,
							  &CardBack->ImageLeft,
							  &CardBack->ImageTop,
							  &CardBack->ImageP1,
							  &CardBack->ImageP2);
			}
		}

		EndPage(hDC);
	}

	EndDoc(hDC);
}

//****************************************************************************

void CPrintDemo::OnBnClickedBtnPrint()
{
	if (GDIPrint.GetCheck())
	{
		PrintUsingGDI();
		return;
	}

	CWaitCursor wait;
	HDC FrontDC = NULL, BackDC = NULL, FrontResinDC = NULL, BackResinDC = NULL;
	CString strCmd;
	ID_TEXTDEF  TextDef  = {};
	ID_SHAPEDEF ShapeDef = {};
	ID_IMAGEDEF ImageDef = {};
	ID_LINEDEF  LineDef  = {};
	ID_MAGTEXT  MagText  = {};

	PFNIDINIT	  pFnCanvasInit    = (PFNIDINIT)GetProcAddress(Parent->hLib,     "ID_CanvasInit");
	PFNIDTEXT	  pFnDrawText      = (PFNIDTEXT)GetProcAddress(Parent->hLib,     IDFN_DRAWTEXT);
	PFNIDSHAPE	  pFnDrawShape     = (PFNIDSHAPE)GetProcAddress(Parent->hLib,    "ID_DrawShape");
	PFNIDLINE	  pFnDrawLine      = (PFNIDLINE)GetProcAddress(Parent->hLib,     "ID_DrawLine");
	PFNIDIMAGE	  pFnDrawImage     = (PFNIDIMAGE)GetProcAddress(Parent->hLib,    IDFN_DRAWIMAGE);
	PFNIDMAGTEXT  pFnDrawMagText   = (PFNIDMAGTEXT)GetProcAddress(Parent->hLib,  IDFN_MAGTEXT);
	PFNIDPRINT	  pFnPrintCard     = (PFNIDPRINT)GetProcAddress(Parent->hLib,    "ID_PrintCard");
	PFNIDPRINTSET pFnPrintSettings = (PFNIDPRINTSET)GetProcAddress(Parent->hLib, "ID_PrintSettings");
	PFNIDCARDSET  pFnCardSettings  = (PFNIDCARDSET) GetProcAddress(Parent->hLib, "ID_CardSettings");

	if (!pFnCanvasInit
	||  !pFnDrawText
	||  !pFnDrawShape
	||  !pFnDrawLine
	||  !pFnDrawImage
	||  !pFnPrintCard
	||  !pFnPrintSettings
	||  !pFnCardSettings)
	{
		//Exit if any function has not been successfully linked to
		FUNCTION_NOT_ACCESSED(PrintCard);
		return;
	}

	PFNIDRESOLUTION pFnResolution = (PFNIDRESOLUTION)GetProcAddress(Parent->hLib, "ID_Resolution");
	BYTE Resolution = (Functions600DPI.GetCheck() == BST_CHECKED) ? 1 : 0;
	ID_RETURN SDKReturn = (*pFnResolution)(Parent->hSession, ID_WRITE, &Resolution);
	if (SDKReturn != ID_SUCCESS)
	{
		DISPLAY_ERROR(Print-SetResolution, SDKReturn);
		return;
	}

	do
	{
/*
		//************************************************************************************
		//* Currently, the demo app uses the driver settings as configured under the Driver1 *
		//* and Driver2 tabs.  Should the developer wish to separately control and/or modify *
		//* these settings, a process such as shown here could be used.                      *
		//************************************************************************************
		PRINTSET PrintSettings, OldPrintSettings;

		//Call SDK function to read the print settings for the card so that they can be preserved
		SDKReturn = (*pFnPrintSettings)(Parent->hSession, ID_READ, &OldPrintSettings);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(OldPrintSettings, SDKReturn);
			return;
		}
		PrintSettings = OldPrintSettings;

		//Determine which sides of the card need to be printed
		if ((CardFrontTick.GetCheck() == BST_CHECKED)
		&&  (CardBackTick.GetCheck()  == BST_CHECKED))
		{
			PrintSettings.Duplex = ID_BOTH_SIDES;
		}
		else if (CardFrontTick.GetCheck() == BST_CHECKED)
		{
			PrintSettings.Duplex = ID_FRONT_ONLY;
		}
		else
		{
			PrintSettings.Duplex = ID_BACK_ONLY;
		}

		//Change the print settings for the card
		SDKReturn = (*pFnPrintSettings)(Parent->hSession, ID_WRITE, &PrintSettings);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(WritePrintSettings, SDKReturn);
			return;
		}

		//Read the current settings for the Back of the card
		CARDSET CardSettings, OldBackSettings;
		SDKReturn = (*pFnCardSettings)(Parent->hSession, ID_READ, ID_SIDE_BACK, &OldBackSettings);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(OldCardSettings, SDKReturn);
			return;
		}
		CardSettings = OldBackSettings;
*/
		//-------------------------------------------------------------------

		//Is there a front to be printed?
		if (CardFrontTick.GetCheck() == BST_CHECKED)
		{
			//Initialise Front Canvas
			SDKReturn = (*pFnCanvasInit)(Parent->hSession, &FrontDC, ID_CANVAS_FRONT);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(CanvasInitFront, SDKReturn);
				return;
			}

			if ((CardFront->TextResin.GetCheck()  == BST_CHECKED)
			||  (CardFront->ShapeResin.GetCheck() == BST_CHECKED)
			||  (CardFront->LineResin.GetCheck()  == BST_CHECKED)
			||  (CardFront->ImageResin.GetCheck()  == BST_CHECKED))
			{
				SDKReturn = (*pFnCanvasInit)(Parent->hSession, &FrontResinDC, ID_CANVAS_FRONT_RESIN);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(CanvasInitFrontResin, SDKReturn);
					break;
				}
			}

			if (CardFront->TextEnabled.GetCheck())
			{
				//===== Front Text.... =====
				//Define the font
				CardFront->TextSize.GetWindowText(strCmd);
				TextDef.FontName = _T("Comic Sans MS");
				TextDef.Size     = _ttoi(strCmd);
				TextDef.Colour   = ColourTable[CardFront->TextColour.GetCurSel()].Reference;
				TextDef.Style    = 0;
				if (CardFront->TextBold.GetCheck() == BST_CHECKED)      TextDef.Style |= ID_TEXT_BOLD;
				if (CardFront->TextItalic.GetCheck() == BST_CHECKED)    TextDef.Style |= ID_TEXT_ITALIC;
				if (CardFront->TextUnderline.GetCheck() == BST_CHECKED) TextDef.Style |= ID_TEXT_UNDERLINE;
				if (CardFront->TextStrikeout.GetCheck() == BST_CHECKED) TextDef.Style |= ID_TEXT_STRIKEOUT;

				//Get the location and angle for the text
				CardFront->TextX.GetWindowText(strCmd);
				TextDef.X = _ttoi(strCmd);
				CardFront->TextY.GetWindowText(strCmd);
				TextDef.Y = _ttoi(strCmd);
				TextDef.Angle = 0;

				//Get the text to be drawn
				CardFront->Text.GetWindowText(strCmd);
				TextDef.Text = strCmd.GetBuffer();

				//Call the SDK function to draw the text on the canvas
				SDKReturn = (*pFnDrawText)(Parent->hSession,
										   CardFront->TextResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_FRONT_RESIN : ID_CANVAS_FRONT,
										   &TextDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawTextFront, SDKReturn);
					break;
				}
			}

			if (CardFront->ShapeEnabled.GetCheck())
			{
				//===== Front Shape... =====
				//Get the shape's definition
				ShapeDef.Shape      = (ID_SHAPE)ShapeTable[CardFront->Shape.GetCurSel()].Reference;
				ShapeDef.PenColour  = ColourTable[CardFront->ShapePen.GetCurSel()].Reference;
				ShapeDef.FillColour = ColourTable[CardFront->ShapeBrush.GetCurSel()].Reference;
				CardFront->ShapePenWidth.GetWindowText(strCmd);
				ShapeDef.PenWidth  = _ttoi(strCmd);

				//Get the shape location
				CardFront->ShapeLeft.GetWindowText(strCmd);
				ShapeDef.Bound.left = _ttoi(strCmd);
				CardFront->ShapeTop.GetWindowText(strCmd);
				ShapeDef.Bound.top = _ttoi(strCmd);
				CardFront->ShapeRight.GetWindowText(strCmd);
				ShapeDef.Bound.right = _ttoi(strCmd);
				CardFront->ShapeBottom.GetWindowText(strCmd);
				ShapeDef.Bound.bottom = _ttoi(strCmd);

				//Set up the specific parameters for given shapes.
				//For simplicity, these have been hard codes here rather than GUI selectable
				switch (ShapeDef.Shape)
				{
				case ID_SHAPE_ROUNDRECT:
					ShapeDef.p1 = 50;				// Corner Width
					ShapeDef.p2 = 50;				// Corner Height
					break;
				case ID_SHAPE_PIE:
				case ID_SHAPE_CHORD:
					ShapeDef.Bound.left   = 40;
					ShapeDef.Bound.top    = 20;
					ShapeDef.Bound.right  = 800;
					ShapeDef.Bound.bottom = 500;
					ShapeDef.p1			  = 0;		// Radial 1 X Co-ord
					ShapeDef.p2			  = 0;		// Radial 1 Y Co-ord
					ShapeDef.p3			  = 700;	// Radial 2 X Co-ord
					ShapeDef.p4			  = 115;	// Radial 2 Y Co-ord
					break;
				}

				//Call the SDK function to draw the shape on the canvas
				SDKReturn = (*pFnDrawShape)(Parent->hSession,
											CardFront->ShapeResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_FRONT_RESIN : ID_CANVAS_FRONT,
											&ShapeDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawShapeFront, SDKReturn);
					break;
				}
			}

			if (CardFront->LineEnabled.GetCheck())
			{
				//===== Front Line... =====
				//Get the line's definition
				LineDef.Colour = ColourTable[CardFront->LineColour.GetCurSel()].Reference;
				CardFront->LineWidth.GetWindowText(strCmd);
				LineDef.Width = _ttoi(strCmd);

				//Get the line location
				CardFront->LineStartX.GetWindowText(strCmd);
				LineDef.StartX = _ttoi(strCmd);
				CardFront->LineStartY.GetWindowText(strCmd);
				LineDef.StartY = _ttoi(strCmd);
				CardFront->LineEndX.GetWindowText(strCmd);
				LineDef.EndX   = _ttoi(strCmd);
				CardFront->LineEndY.GetWindowText(strCmd);
				LineDef.EndY   = _ttoi(strCmd);

				//Call the SDK function to draw the line on the canvas
				SDKReturn = (*pFnDrawLine)(Parent->hSession,
										   CardFront->LineResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_FRONT_RESIN : ID_CANVAS_FRONT,
										   &LineDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawLineFront, SDKReturn);
					break;
				}
			}

			if (CardFront->ImageEnabled.GetCheck())
			{
				//===== Front image..... =====
				if (CardFront->ImageFilename.GetWindowTextLength() != 0)
				{
					//Front Image.......
					//Get the image boundaries
					CardFront->ImageLeft.GetWindowText(strCmd);
					ImageDef.X = _ttoi(strCmd);
					CardFront->ImageTop.GetWindowText(strCmd);
					ImageDef.Y = _ttoi(strCmd);
					CardFront->ImageP1.GetWindowText(strCmd);
					ImageDef.p1 = _ttoi(strCmd);
					CardFront->ImageP2.GetWindowText(strCmd);
					ImageDef.p2 = _ttoi(strCmd);

					ImageDef.Filename = CardFront->Image.GetBuffer();

					//Call the SDK function to draw the image on the canvas
					SDKReturn = (*pFnDrawImage)(Parent->hSession,
												CardFront->ImageResin.GetCheck() == BST_CHECKED
													? ID_CANVAS_FRONT_RESIN : ID_CANVAS_FRONT,
												&ImageDef);
					if (SDKReturn != ID_SUCCESS)
					{
						DISPLAY_ERROR(DrawImageFront, SDKReturn);
						break;
					}
				}
			}
		}

		if (CardFront->MagDataEnabled.GetCheck())
		{
			//===== Front Magnetic Data =====
			if (CardFront->Mag1Data.GetWindowTextLength())
			{
				MagText.Track = 1;
				CardFront->Mag1Data.GetWindowText(strCmd);
				MagText.Data = strCmd.GetBuffer();

				//Call the SDK function to draw the image on the canvas
				SDKReturn = (*pFnDrawMagText)(Parent->hSession, ID_SIDE_FRONT, &MagText);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(Mag1DataFront, SDKReturn);
					break;
				}
			}

			if (CardFront->Mag2Data.GetWindowTextLength())
			{
				MagText.Track = 2;
				CardFront->Mag1Data.GetWindowText(strCmd);
				MagText.Data = strCmd.GetBuffer();

				//Call the SDK function to draw the image on the canvas
				SDKReturn = (*pFnDrawMagText)(Parent->hSession, ID_SIDE_FRONT, &MagText);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(Mag2DataFront, SDKReturn);
					break;
				}
			}

			if (CardFront->Mag3Data.GetWindowTextLength())
			{
				MagText.Track = 3;
				CardFront->Mag1Data.GetWindowText(strCmd);
				MagText.Data = strCmd.GetBuffer();

				//Call the SDK function to draw the image on the canvas
				SDKReturn = (*pFnDrawMagText)(Parent->hSession, ID_SIDE_FRONT, &MagText);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(Mag3DataFront, SDKReturn);
					break;
				}
			}
		}

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

		//Is there a back to be printed?
		if (CardBackTick.GetCheck() == BST_CHECKED)
		{
/*
			//***********************************************************************************
			//* Similarly, settings for the back of the card are defined under the Driver1 and  *
			//* Driver 2 tabs.  This code block reads the settings to save them for restore     *
			//* later, and modifies the colour settings according to the Print Demo tab         *
			//* selections.                                                                     *
			//***********************************************************************************
			CARDSET CardSettings,  OldBackSettings;

			//Read the current settings for the Back of the card
			SDKReturn = (*pFnCardSettings)(Parent->hSession,
										   ID_READ,
										   ID_SIDE_BACK,
										   &OldBackSettings);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(OldCardSettings, SDKReturn);
				return;
			}
			CardSettings = OldBackSettings;

			//If colour is required, modify the card settings for the back of the card
			if ((ColourTable[CardBack->TextColour.GetCurSel()].Reference != ID_COLOUR_BLACK)
			||  (ColourTable[CardBack->ShapePen.GetCurSel()].Reference   != ID_COLOUR_BLACK)
			||  (ColourTable[CardBack->ShapeBrush.GetCurSel()].Reference != ID_COLOUR_BLACK)
			||  (ColourTable[CardBack->LineColour.GetCurSel()].Reference != ID_COLOUR_BLACK))
			{
				CardSettings.ColourFormat = ID_COLOURFORMAT_YMCK;

				SDKReturn = (*pFnCardSettings)(Parent->hSession,
											   ID_WRITE,
											   ID_SIDE_BACK,
											   &CardSettings);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(CardSettingsBack, SDKReturn);
					return;
				}
			}
*/
			//Initialise Rear Canvas
			SDKReturn = (*pFnCanvasInit)(Parent->hSession, &BackDC, ID_CANVAS_BACK);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(CanvasInitBack, SDKReturn);
				break;
			}

				//Is a rear resin canvas required?
			if ((CardBack->TextResin.GetCheck() == BST_CHECKED)
			||  (CardBack->LineResin.GetCheck() == BST_CHECKED)
			||  (CardBack->ShapeResin.GetCheck() == BST_CHECKED)
			||  (CardBack->ImageResin.GetCheck() == BST_CHECKED))
			{
				//Yes, so call the SDK to initialise one
				SDKReturn = (*pFnCanvasInit)(Parent->hSession, &BackResinDC, ID_CANVAS_BACK_RESIN);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(CanvasInitBackResin, SDKReturn);
					break;
				}
			}

			if (CardBack->TextEnabled.GetCheck())
			{
				//Rear Text
				CardBack->TextSize.GetWindowText(strCmd);
				TextDef.FontName = _T("Comic Sans MS");
				TextDef.Size     = _ttoi(strCmd);
				TextDef.Colour   = ColourTable[CardBack->TextColour.GetCurSel()].Reference;
				TextDef.Style    = 0;
				if (CardBack->TextBold.GetCheck() == BST_CHECKED)      TextDef.Style |= ID_TEXT_BOLD;
				if (CardBack->TextItalic.GetCheck() == BST_CHECKED)    TextDef.Style |= ID_TEXT_ITALIC;
				if (CardBack->TextUnderline.GetCheck() == BST_CHECKED) TextDef.Style |= ID_TEXT_UNDERLINE;
				if (CardBack->TextStrikeout.GetCheck() == BST_CHECKED) TextDef.Style |= ID_TEXT_STRIKEOUT;
				CardBack->TextX.GetWindowText(strCmd);
				TextDef.X = _ttoi(strCmd);
				CardBack->TextY.GetWindowText(strCmd);
				TextDef.Y = _ttoi(strCmd);
				TextDef.Angle = 0;

				//Get the text to be drawn
				CardBack->Text.GetWindowText(strCmd);
				TextDef.Text = strCmd.GetBuffer();

				//Call the SDK function to draw the text on the canvas
				SDKReturn = (*pFnDrawText)(Parent->hSession,
										   CardBack->TextResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_BACK_RESIN : ID_CANVAS_BACK,
										   &TextDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawTextback, SDKReturn);
					break;
				}
			}

			if (CardBack->ShapeEnabled.GetCheck())
			{
				//Rear Shape
				ShapeDef.Shape      = (ID_SHAPE)ShapeTable[CardBack->Shape.GetCurSel()].Reference;
				ShapeDef.PenColour  = ColourTable[CardBack->ShapePen.GetCurSel()].Reference;
				ShapeDef.FillColour = ColourTable[CardBack->ShapeBrush.GetCurSel()].Reference;

				CardBack->ShapePenWidth.GetWindowText(strCmd);
				ShapeDef.PenWidth  = _ttoi(strCmd);
				CardBack->ShapeLeft.GetWindowText(strCmd);
				ShapeDef.Bound.left = _ttoi(strCmd);
				CardBack->ShapeTop.GetWindowText(strCmd);
				ShapeDef.Bound.top = _ttoi(strCmd);
				CardBack->ShapeRight.GetWindowText(strCmd);
				ShapeDef.Bound.right = _ttoi(strCmd);
				CardBack->ShapeBottom.GetWindowText(strCmd);
				ShapeDef.Bound.bottom = _ttoi(strCmd);

				//Set up the specific parameters for given shapes.
				//Again, for simplicity, these have been hard coded here rather than being
				//GUI selectable
				switch (ShapeDef.Shape)
				{
				case ID_SHAPE_ROUNDRECT:
					ShapeDef.p1 = 50;				// Corner Width
					ShapeDef.p2 = 50;				// Corner Height
					break;
				case ID_SHAPE_PIE:
				case ID_SHAPE_CHORD:
					ShapeDef.Bound.left   = 40;
					ShapeDef.Bound.top    = 20;
					ShapeDef.Bound.right  = 800;
					ShapeDef.Bound.bottom = 500;
					ShapeDef.p1			  = 0;		// Radial 1 X Co-ord
					ShapeDef.p2			  = 0;		// Radial 1 Y Co-ord
					ShapeDef.p3			  = 700;	// Radial 2 X Co-ord
					ShapeDef.p4			  = 115;	// Radial 2 Y Co-ord
					break;
				}

				//Call the SDK function to draw the shape on the canvas
				SDKReturn = (*pFnDrawShape)(Parent->hSession,
											CardBack->ShapeResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_BACK_RESIN : ID_CANVAS_BACK,
											&ShapeDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawShapeBack, SDKReturn);
					break;
				}
			}

			if (CardBack->LineEnabled.GetCheck())
			{
				//Back Line...
				//Get the line's definition
				ID_LINEDEF LineDef;
				LineDef.Colour = ColourTable[CardBack->LineColour.GetCurSel()].Reference;
				CardBack->LineWidth.GetWindowText(strCmd);
				LineDef.Width = _ttoi(strCmd);

				//Get the line location
				CardBack->LineStartX.GetWindowText(strCmd);
				LineDef.StartX = _ttoi(strCmd);
				CardBack->LineStartY.GetWindowText(strCmd);
				LineDef.StartY = _ttoi(strCmd);
				CardBack->LineEndX.GetWindowText(strCmd);
				LineDef.EndX   = _ttoi(strCmd);
				CardBack->LineEndY.GetWindowText(strCmd);
				LineDef.EndY   = _ttoi(strCmd);

				//Call the SDK function to draw the line on the canvas
				SDKReturn = (*pFnDrawLine)(Parent->hSession,
										   CardBack->LineResin.GetCheck() == BST_CHECKED
												? ID_CANVAS_BACK_RESIN : ID_CANVAS_BACK,
										   &LineDef);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(DrawLineback, SDKReturn);
					break;
				}
			}

			if (CardBack->ImageEnabled.GetCheck())
			{
				//===== Back Image... =====
				if (CardBack->ImageFilename.GetWindowTextLength() != 0)
				{
					//Back Image.......
					//Get the image boundaries
					CardBack->ImageLeft.GetWindowText(strCmd);
					ImageDef.X = _ttoi(strCmd);
					CardBack->ImageTop.GetWindowText(strCmd);
					ImageDef.Y = _ttoi(strCmd);
					CardBack->ImageP1.GetWindowText(strCmd);
					ImageDef.p1 = _ttoi(strCmd);
					CardBack->ImageP2.GetWindowText(strCmd);
					ImageDef.p2 = _ttoi(strCmd);

					ImageDef.Filename = CardBack->Image.GetBuffer();

					//Call the SDK function to draw the image on the canvas
					SDKReturn = (*pFnDrawImage)(Parent->hSession,
												CardBack->ImageResin.GetCheck() == BST_CHECKED
													? ID_CANVAS_BACK_RESIN : ID_CANVAS_BACK,
												&ImageDef);
					if (SDKReturn != ID_SUCCESS)
					{
						DISPLAY_ERROR(DrawImageBack, SDKReturn);
						break;
					}
				}
			}
		}

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

		if(Parent->PrinterType == ID_GENERATION2)
		{
			if (!Parent->PrintToFile)
			{
				PFNIDPREPARE pFnPrepare =  (PFNIDPREPARE)GetProcAddress(Parent->hLib, "ID_PrepareForPrint");
				SDKReturn = (*pFnPrepare)(Parent->hSession);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(PrintCardPrepare, SDKReturn);
					break;
				}
			}
		}
	
		//Print the Card
		SDKReturn = (*pFnPrintCard)(Parent->hSession);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(PrintCard, SDKReturn);
			break;
		}

		if (!Parent->PrintToFile)
		{
			if(Parent->PrinterType == ID_GENERATION2)
			{
				PFNIDPRINTCOMP pFnComplete = (PFNIDPRINTCOMP)GetProcAddress(Parent->hLib, "ID_WaitPrintComplete");
				SDKReturn = (*pFnComplete)(Parent->hSession);
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(PrintCardComplete, SDKReturn);
					break;
				}
			}
			else
			{
				//Wait for the printing to complete
				SDKReturn = Parent->WaitForPrinterToFinish();
				if (SDKReturn != ID_SUCCESS)
				{
					DISPLAY_ERROR(PrintCardWait, SDKReturn);
					break;
				}
			}
		}

/*
		//**************************************************************************************
		//* If either of the previous commented out sections of code have been used, this      *
		//* section (or parts of it) will be required.                                         *
		//* Restore the settings for the print job, and for the card back, as saved previously *
		//**************************************************************************************
		//Restore Original Print Settings
		SDKReturn = (*pFnPrintSettings)(Parent->hSession, ID_WRITE, &OldPrintSettings);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(RestorePrintSettings, SDKReturn);
			break;
		}

		//Restore the Original Settings for the Back of the Card
		SDKReturn = (*pFnCardSettings)(Parent->hSession,
									   ID_WRITE,
									   ID_SIDE_BACK,
									   &OldBackSettings);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(RestoreBackSettings, SDKReturn);
		}
*/

    } while (false);  //End of single pass do..while loop

    //All 'breaks' from the single pass do..while loop come here
	PFNIDDELETE	pFnCanvasDelete = (PFNIDDELETE)GetProcAddress(Parent->hLib, "ID_CanvasDelete");
	if (FrontDC)      (*pFnCanvasDelete)(Parent->hSession, ID_CANVAS_FRONT);
	if (FrontResinDC) (*pFnCanvasDelete)(Parent->hSession, ID_CANVAS_FRONT_RESIN);
	if (BackDC)       (*pFnCanvasDelete)(Parent->hSession, ID_CANVAS_BACK);
	if (BackResinDC)  (*pFnCanvasDelete)(Parent->hSession, ID_CANVAS_BACK_RESIN);
}

//****************************************************************************

void CPrintDemo::OnBnClickedPrinterPrefs()
{
	//Get the SDK function address
	PFNIDPPREFS pFnPrinterPrefs = (PFNIDPPREFS)GetProcAddress(Parent->hLib, "ID_PrinterPrefs");
	if (!pFnPrinterPrefs)
	{
		FUNCTION_NOT_ACCESSED(PrinterPrefs);
	}

	else
	{
		//Display Printer Preferences and apply any changes 
		ID_RETURN SDKReturn = (*pFnPrinterPrefs)(Parent->hSession, GetActiveWindow()->m_hWnd);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(PrinterPrefs, SDKReturn);
		}
	}
}
